Enable OTA support for RP2350 (#2472)

The RP2350 has a different blob header requirement to identify a working
image.  Ensure that header is present in the OTA loader.

Update the PicoOTA examples for the 2350
This commit is contained in:
Earle F. Philhower, III 2024-09-17 15:05:42 -07:00 committed by GitHub
parent 4504d72972
commit 2063a2d23d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 9752 additions and 57 deletions

View file

@ -1,8 +1,6 @@
OTA Updates
===========
**NOTE:** OTA is not yet supported on the RP2350. PRs gladly accepted!
Introduction
------------

View file

@ -7,7 +7,6 @@ is supported by the core with some minor caveats:
* PSRAM is supported via a new ``pmalloc`` call and ``PSRAM`` variable decorator.
* Both RP2350A and RP2350B (48 GPIOs) are supported.
* Only ARM mode is available. For RISC-V (Hazard3), please use the raw SDK.
* OTA is not yet supported.
P2350-E9 Errata ("Increased leakage current on Bank 0 GPIO when pad input is enabled")
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -21,6 +21,9 @@
__stack (== StackTop)
*/
MEMORY
{
FLASH(rx) : ORIGIN = 0x10000000, LENGTH = __FLASH_LENGTH__
@ -42,6 +45,20 @@ SECTIONS
__flash_binary_start = .;
} > FLASH
.ota : {
/* Start image with OTA */
KEEP (*(.OTA))
*ota.o
} > FLASH
.partition : {
. = __flash_binary_start + 0x2ff0;
LONG(__FS_START__)
LONG(__FS_END__)
LONG(__EEPROM_START__)
LONG(__FLASH_LENGTH__)
} > FLASH
/* The bootrom will enter the image at the point indicated in your
IMAGE_DEF, which is usually the reset handler of your vector table.
@ -53,8 +70,8 @@ SECTIONS
*/
.text : {
__logical_binary_start = .;
KEEP (*(.vectors))
__logical_binary_start = .;
KEEP (*(.binary_info_header))
__binary_info_header_end = .;
KEEP (*(.embedded_block))
@ -276,7 +293,7 @@ SECTIONS
.flash_end : {
KEEP(*(.embedded_end_block*))
PROVIDE(__flash_binary_end = .);
} > FLASH =0xaa
} > FLASH = 0xaa
.psram (NOLOAD) : {
__psram_start__ = .;

Binary file not shown.

View file

@ -12,7 +12,8 @@
#include <PicoOTA.h>
#include <LittleFS.h>
#include "blink_100_1000.h"
#include "blink_100_1000_rp2040.h"
#include "blink_500_500_rp2350.h"
void setup() {
Serial.begin(115200);

View file

@ -1,3 +1,4 @@
#ifdef PICO_RP2040
const unsigned char blink_gz[] = {
0x1f, 0x8b, 0x08, 0x08, 0x86, 0x7e, 0xf3, 0x62, 0x02, 0x03, 0x73, 0x6b,
0x65, 0x74, 0x63, 0x68, 0x5f, 0x61, 0x75, 0x67, 0x31, 0x30, 0x61, 0x2e,
@ -3896,3 +3897,4 @@ const unsigned char blink_gz[] = {
0x03, 0xeb, 0x79, 0x7c, 0xf6, 0x3f, 0x01, 0xa8, 0x7b, 0x69, 0xf7, 0x10,
0x11, 0x01, 0x00
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,8 @@
#include <PicoOTA.h>
#include <LittleFS.h>
#include "blink_100_1000.h"
#include "blink_100_1000_rp2040.h"
#include "blink_500_500_rp2350.h"
void setup() {
Serial.begin(115200);

View file

@ -1,3 +1,4 @@
#ifdef PICO_RP2040
const unsigned char blink[] = {
0x00, 0xb5, 0x32, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21,
0x88, 0x43, 0x98, 0x60, 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2e, 0x4b,
@ -5826,3 +5827,4 @@ const unsigned char blink[] = {
0xc1, 0x45, 0x00, 0x10, 0x9d, 0x48, 0x00, 0x10, 0xad, 0x4b, 0x00, 0x10,
0xed, 0x63, 0x00, 0x10
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -7,10 +7,14 @@ if (${cpu} MATCHES "rp2040")
set(PICO_BOARD pico)
set(PICO_PLATFORM rp2040)
set(PICO_CYW43_SUPPORTED 0)
set(OBJARCH armv6-m)
set(WRAP -Wl,--wrap=clocks_init)
elseif(${cpu} MATCHES "rp2350")
set(PICO_BOARD pico2)
set(PICO_PLATFORM rp2350)
set(PICO_CYW43_SUPPORTED 0)
set(OBJARCH armv8-m)
set(WRAP )
else()
message(FATAL_ERROR "Unknown CPU, '${cpu}'")
endif()
@ -71,7 +75,7 @@ target_compile_options(ota PUBLIC
)
target_link_options(ota PUBLIC
-Wl,--wrap=clocks_init
${WRAP}
-Wl,--wrap=exit
-Wl,--wrap=atexit
-Wl,--wrap=panic_unsupported
@ -97,7 +101,7 @@ target_link_libraries(ota
)
add_custom_command(TARGET ota POST_BUILD
COMMAND ../../system/arm-none-eabi/bin/arm-none-eabi-ld -r -A armv6-m -b binary -o ota.o ota.bin
COMMAND ../../system/arm-none-eabi/bin/arm-none-eabi-ld -r -A ${OBJARCH} -b binary -o ota.o ota.bin
COMMAND ../../system/arm-none-eabi/bin/arm-none-eabi-objcopy --rename-section .data=.OTA ota.o ../../lib/${cpu}/ota.o
COMMAND cp ../ota_command.h ../../include/${cpu}/pico_base/pico/.
)

View file

@ -23,19 +23,17 @@
MEMORY
{
FLASH(rx) : ORIGIN = 0x10000100, LENGTH = 16384k
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 212k
/* We split RAM into main (where the flash->ram code will be copied) and GLOBALS which has all large arrays */
/* By placing those arrays at the end of RAM we can avoid overwriting uninitialize_ram from the main app as */
/* long as those vars are stored after 12K by using an alignment value in the main app linker file. */
INCLUDE "pico_flash_region.ld"
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 212k
GLOBALS(rwx) : ORIGIN = 0x20035000, LENGTH = 44k
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k
SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k
}
ENTRY(_entry_point)
SECTIONS {
SECTIONS
{
/* Second stage bootloader is prepended to the image. It must be 256 bytes big
and checksummed. It is usually built by the boot_stage2 target
in the Raspberry Pi Pico SDK
@ -45,24 +43,19 @@ SECTIONS {
.globals (NOLOAD) : {
} > GLOBALS
.flash_begin : {
__flash_binary_start = .;
} > FLASH
/*
.boot2 : {
__boot2_start__ = .;
KEEP (*(.boot2))
__boot2_end__ = .;
} > FLASH
ASSERT(__boot2_end__ - __boot2_start__ == 256,
"ERROR: Pico second stage bootloader must be 256 bytes in size")
*/
/* The second stage will always enter the image at the start of .text.
/* The bootrom will enter the image at the point indicated in your
IMAGE_DEF, which is usually the reset handler of your vector table.
The debugger will use the ELF entry point, which is the _entry_point
symbol if present, otherwise defaults to start of .text.
This can be used to transfer control back to the bootrom on debugger
launches only, to perform proper flash setup.
symbol, and in our case is *different from the bootrom's entry point.*
This is used to go back through the bootrom on debugger launches only,
to perform the same initial flash setup that would be performed on a
cold boot.
*/
.flashtext : {
@ -70,8 +63,11 @@ SECTIONS {
KEEP (*(.vectors))
KEEP (*(.binary_info_header))
__binary_info_header_end = .;
KEEP (*(.embedded_block))
__embedded_block_end = .;
KEEP (*(.reset))
}
. = ALIGN(4);
} > FLASH
.rodata : {
/* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */
@ -79,23 +75,39 @@ SECTIONS {
. = ALIGN(4);
} > FLASH
.ARM.extab : {
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx : {
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
/* Machine inspectable binary information */
. = ALIGN(4);
__binary_info_start = .;
.binary_info :
{
KEEP(*(.binary_info.keep.*))
*(.binary_info.*)
} > FLASH
__binary_info_end = .;
. = ALIGN(4);
/* Vector table goes first in RAM, to avoid large alignment hole */
.ram_vector_table (COPY): {
.ram_vector_table (NOLOAD): {
*(.ram_vector_table)
} > RAM
.uninitialized_data (NOLOAD): {
. = ALIGN(4);
*(.uninitialized_data*)
} > RAM
.text : {
__ram_text_start__ = .;
*(.init)
@ -119,7 +131,7 @@ SECTIONS {
__ram_text_end__ = .;
} > RAM AT> FLASH
__ram_text_source__ = LOADADDR(.text);
. = ALIGN(4);
.data : {
__data_start__ = .;
@ -176,6 +188,50 @@ SECTIONS {
*(.uninitialized_data*)
} > RAM
.tdata : {
. = ALIGN(4);
*(.tdata .tdata.* .gnu.linkonce.td.*)
/* All data end */
__tdata_end = .;
} > RAM AT> FLASH
PROVIDE(__data_end__ = .);
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
__etext = LOADADDR(.data);
.tbss (NOLOAD) : {
. = ALIGN(4);
__bss_start__ = .;
__tls_base = .;
*(.tbss .tbss.* .gnu.linkonce.tb.*)
*(.tcommon)
__tls_end = .;
} > RAM
.bss : {
. = ALIGN(4);
__tbss_end = .;
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
*(COMMON)
PROVIDE(__global_pointer$ = . + 2K);
*(.sbss*)
. = ALIGN(4);
__bss_end__ = .;
} > RAM
.heap (NOLOAD):
{
__end__ = .;
end = __end__;
KEEP(*(.heap*))
/* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
. = ORIGIN(RAM) + LENGTH(RAM);
__HeapLimit = .;
} > RAM
/* Start and end symbols must be word-aligned */
.scratch_x : {
__scratch_x_start__ = .;
@ -193,22 +249,6 @@ SECTIONS {
} > SCRATCH_Y AT > FLASH
__scratch_y_source__ = LOADADDR(.scratch_y);
.bss : {
. = ALIGN(4);
__bss_start__ = .;
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > RAM
.heap (COPY): {
__end__ = .;
end = __end__;
*(.heap*)
__HeapLimit = .;
} > RAM
/* .stack*_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later
@ -218,16 +258,19 @@ SECTIONS {
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
* stack is not used then all of SCRATCH_X is free.
*/
.stack1_dummy (COPY): {
.stack1_dummy (NOLOAD):
{
*(.stack1*)
} > SCRATCH_X
.stack_dummy (COPY): {
*(.stack*)
.stack_dummy (NOLOAD):
{
KEEP(*(.stack*))
} > SCRATCH_Y
.flash_end : {
__flash_binary_end = .;
} > FLASH
KEEP(*(.embedded_end_block*))
PROVIDE(__flash_binary_end = .);
} > FLASH =0xaa
/* stack limit is poorly named, but historically is maximum heap ptr */
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
@ -237,10 +280,23 @@ SECTIONS {
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* picolibc and LLVM */
PROVIDE (__heap_start = __end__);
PROVIDE (__heap_end = __HeapLimit);
PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1));
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
/* llvm-libc */
PROVIDE (_end = __end__);
PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
/* ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")*/
ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary")
ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary")
/* todo assert on extra code */
}