Skip to content

Commit dfb8a7c

Browse files
Enable OTA support for RP2350
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 example for the 2350
1 parent 5fbda35 commit dfb8a7c

File tree

9 files changed

+5817
-56
lines changed

9 files changed

+5817
-56
lines changed

docs/ota.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
OTA Updates
22
===========
33

4-
**NOTE:** OTA is not yet supported on the RP2350. PRs gladly accepted!
5-
64
Introduction
75
------------
86

docs/rp2350.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ is supported by the core with some minor caveats:
77
* PSRAM is supported via a new ``pmalloc`` call and ``PSRAM`` variable decorator.
88
* Both RP2350A and RP2350B (48 GPIOs) are supported.
99
* Only ARM mode is available. For RISC-V (Hazard3), please use the raw SDK.
10-
* OTA is not yet supported.
1110

1211
P2350-E9 Errata ("Increased leakage current on Bank 0 GPIO when pad input is enabled")
1312
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

lib/rp2350/memmap_default.ld

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
__stack (== StackTop)
2222
*/
2323

24+
25+
26+
2427
MEMORY
2528
{
2629
FLASH(rx) : ORIGIN = 0x10000000, LENGTH = __FLASH_LENGTH__
@@ -42,6 +45,20 @@ SECTIONS
4245
__flash_binary_start = .;
4346
} > FLASH
4447

48+
.ota : {
49+
/* Start image with OTA */
50+
KEEP (*(.OTA))
51+
*ota.o
52+
} > FLASH
53+
54+
.partition : {
55+
. = __flash_binary_start + 0x2ff0;
56+
LONG(__FS_START__)
57+
LONG(__FS_END__)
58+
LONG(__EEPROM_START__)
59+
LONG(__FLASH_LENGTH__)
60+
} > FLASH
61+
4562
/* The bootrom will enter the image at the point indicated in your
4663
IMAGE_DEF, which is usually the reset handler of your vector table.
4764
@@ -53,8 +70,8 @@ SECTIONS
5370
*/
5471

5572
.text : {
56-
__logical_binary_start = .;
5773
KEEP (*(.vectors))
74+
__logical_binary_start = .;
5875
KEEP (*(.binary_info_header))
5976
__binary_info_header_end = .;
6077
KEEP (*(.embedded_block))
@@ -276,7 +293,7 @@ SECTIONS
276293
.flash_end : {
277294
KEEP(*(.embedded_end_block*))
278295
PROVIDE(__flash_binary_end = .);
279-
} > FLASH =0xaa
296+
} > FLASH = 0xaa
280297
281298
.psram (NOLOAD) : {
282299
__psram_start__ = .;

lib/rp2350/ota.o

40 Bytes
Binary file not shown.

libraries/PicoOTA/examples/OTAfromFile/OTAfromFile.ino

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99

1010
#include <PicoOTA.h>
1111
#include <LittleFS.h>
12-
#include "blink_100_1000.h"
12+
#include "blink_100_1000_rp2040.h"
13+
#include "blink_500_500_rp2350.h"
1314

1415
void setup() {
1516
Serial.begin(115200);

libraries/PicoOTA/examples/OTAfromFile/blink_100_1000.h renamed to libraries/PicoOTA/examples/OTAfromFile/blink_100_1000_rp2040.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#ifdef PICO_RP2040
12
const unsigned char blink[] = {
23
0x00, 0xb5, 0x32, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21,
34
0x88, 0x43, 0x98, 0x60, 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2e, 0x4b,
@@ -5826,3 +5827,4 @@ const unsigned char blink[] = {
58265827
0xc1, 0x45, 0x00, 0x10, 0x9d, 0x48, 0x00, 0x10, 0xad, 0x4b, 0x00, 0x10,
58275828
0xed, 0x63, 0x00, 0x10
58285829
};
5830+
#endif

libraries/PicoOTA/examples/OTAfromFile/blink_500_500_rp2350.h

Lines changed: 5684 additions & 0 deletions
Large diffs are not rendered by default.

ota/CMakeLists.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@ if (${cpu} MATCHES "rp2040")
77
set(PICO_BOARD pico)
88
set(PICO_PLATFORM rp2040)
99
set(PICO_CYW43_SUPPORTED 0)
10+
set(OBJARCH armv6-m)
11+
set(WRAP -Wl,--wrap=clocks_init)
1012
elseif(${cpu} MATCHES "rp2350")
1113
set(PICO_BOARD pico2)
1214
set(PICO_PLATFORM rp2350)
1315
set(PICO_CYW43_SUPPORTED 0)
16+
set(OBJARCH armv8-m)
17+
set(WRAP )
1418
else()
1519
message(FATAL_ERROR "Unknown CPU, '${cpu}'")
1620
endif()
@@ -71,7 +75,7 @@ target_compile_options(ota PUBLIC
7175
)
7276

7377
target_link_options(ota PUBLIC
74-
-Wl,--wrap=clocks_init
78+
${WRAP}
7579
-Wl,--wrap=exit
7680
-Wl,--wrap=atexit
7781
-Wl,--wrap=panic_unsupported
@@ -97,7 +101,7 @@ target_link_libraries(ota
97101
)
98102

99103
add_custom_command(TARGET ota POST_BUILD
100-
COMMAND ../../system/arm-none-eabi/bin/arm-none-eabi-ld -r -A armv6-m -b binary -o ota.o ota.bin
104+
COMMAND ../../system/arm-none-eabi/bin/arm-none-eabi-ld -r -A ${OBJARCH} -b binary -o ota.o ota.bin
101105
COMMAND ../../system/arm-none-eabi/bin/arm-none-eabi-objcopy --rename-section .data=.OTA ota.o ../../lib/${cpu}/ota.o
102106
COMMAND cp ../ota_command.h ../../include/${cpu}/pico_base/pico/.
103107
)

ota/memmap_ota_rp2350.ld

Lines changed: 104 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,17 @@
2323

2424
MEMORY
2525
{
26-
FLASH(rx) : ORIGIN = 0x10000100, LENGTH = 16384k
27-
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 212k
28-
/* We split RAM into main (where the flash->ram code will be copied) and GLOBALS which has all large arrays */
29-
/* By placing those arrays at the end of RAM we can avoid overwriting uninitialize_ram from the main app as */
30-
/* long as those vars are stored after 12K by using an alignment value in the main app linker file. */
26+
INCLUDE "pico_flash_region.ld"
27+
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 212k
3128
GLOBALS(rwx) : ORIGIN = 0x20035000, LENGTH = 44k
32-
SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
33-
SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
29+
SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k
30+
SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k
3431
}
3532

3633
ENTRY(_entry_point)
3734

38-
SECTIONS {
35+
SECTIONS
36+
{
3937
/* Second stage bootloader is prepended to the image. It must be 256 bytes big
4038
and checksummed. It is usually built by the boot_stage2 target
4139
in the Raspberry Pi Pico SDK
@@ -45,57 +43,71 @@ SECTIONS {
4543
.globals (NOLOAD) : {
4644
} > GLOBALS
4745

46+
4847
.flash_begin : {
4948
__flash_binary_start = .;
5049
} > FLASH
51-
/*
52-
.boot2 : {
53-
__boot2_start__ = .;
54-
KEEP (*(.boot2))
55-
__boot2_end__ = .;
56-
} > FLASH
5750

58-
ASSERT(__boot2_end__ - __boot2_start__ == 256,
59-
"ERROR: Pico second stage bootloader must be 256 bytes in size")
60-
*/
61-
/* The second stage will always enter the image at the start of .text.
51+
/* The bootrom will enter the image at the point indicated in your
52+
IMAGE_DEF, which is usually the reset handler of your vector table.
53+
6254
The debugger will use the ELF entry point, which is the _entry_point
63-
symbol if present, otherwise defaults to start of .text.
64-
This can be used to transfer control back to the bootrom on debugger
65-
launches only, to perform proper flash setup.
55+
symbol, and in our case is *different from the bootrom's entry point.*
56+
This is used to go back through the bootrom on debugger launches only,
57+
to perform the same initial flash setup that would be performed on a
58+
cold boot.
6659
*/
6760

6861
.flashtext : {
6962
__logical_binary_start = .;
7063
KEEP (*(.vectors))
7164
KEEP (*(.binary_info_header))
7265
__binary_info_header_end = .;
66+
KEEP (*(.embedded_block))
67+
__embedded_block_end = .;
7368
KEEP (*(.reset))
74-
}
69+
. = ALIGN(4);
70+
} > FLASH
7571

7672
.rodata : {
7773
/* segments not marked as .flashdata are instead pulled into .data (in RAM) to avoid accidental flash accesses */
7874
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
7975
. = ALIGN(4);
8076
} > FLASH
8177

82-
.ARM.extab : {
78+
.ARM.extab :
79+
{
8380
*(.ARM.extab* .gnu.linkonce.armextab.*)
8481
} > FLASH
8582

8683
__exidx_start = .;
87-
.ARM.exidx : {
84+
.ARM.exidx :
85+
{
8886
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
8987
} > FLASH
9088
__exidx_end = .;
9189

90+
/* Machine inspectable binary information */
91+
. = ALIGN(4);
92+
__binary_info_start = .;
93+
.binary_info :
94+
{
95+
KEEP(*(.binary_info.keep.*))
96+
*(.binary_info.*)
97+
} > FLASH
98+
__binary_info_end = .;
9299
. = ALIGN(4);
93100

94101
/* Vector table goes first in RAM, to avoid large alignment hole */
95-
.ram_vector_table (COPY): {
102+
.ram_vector_table (NOLOAD): {
96103
*(.ram_vector_table)
97104
} > RAM
98105

106+
.uninitialized_data (NOLOAD): {
107+
. = ALIGN(4);
108+
*(.uninitialized_data*)
109+
} > RAM
110+
99111
.text : {
100112
__ram_text_start__ = .;
101113
*(.init)
@@ -119,7 +131,7 @@ SECTIONS {
119131
__ram_text_end__ = .;
120132
} > RAM AT> FLASH
121133
__ram_text_source__ = LOADADDR(.text);
122-
134+
. = ALIGN(4);
123135

124136
.data : {
125137
__data_start__ = .;
@@ -176,6 +188,50 @@ SECTIONS {
176188
*(.uninitialized_data*)
177189
} > RAM
178190

191+
.tdata : {
192+
. = ALIGN(4);
193+
*(.tdata .tdata.* .gnu.linkonce.td.*)
194+
/* All data end */
195+
__tdata_end = .;
196+
} > RAM AT> FLASH
197+
PROVIDE(__data_end__ = .);
198+
199+
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
200+
__etext = LOADADDR(.data);
201+
202+
.tbss (NOLOAD) : {
203+
. = ALIGN(4);
204+
__bss_start__ = .;
205+
__tls_base = .;
206+
*(.tbss .tbss.* .gnu.linkonce.tb.*)
207+
*(.tcommon)
208+
209+
__tls_end = .;
210+
} > RAM
211+
212+
.bss : {
213+
. = ALIGN(4);
214+
__tbss_end = .;
215+
216+
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
217+
*(COMMON)
218+
PROVIDE(__global_pointer$ = . + 2K);
219+
*(.sbss*)
220+
. = ALIGN(4);
221+
__bss_end__ = .;
222+
} > RAM
223+
224+
.heap (NOLOAD):
225+
{
226+
__end__ = .;
227+
end = __end__;
228+
KEEP(*(.heap*))
229+
/* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
230+
to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
231+
. = ORIGIN(RAM) + LENGTH(RAM);
232+
__HeapLimit = .;
233+
} > RAM
234+
179235
/* Start and end symbols must be word-aligned */
180236
.scratch_x : {
181237
__scratch_x_start__ = .;
@@ -193,22 +249,6 @@ SECTIONS {
193249
} > SCRATCH_Y AT > FLASH
194250
__scratch_y_source__ = LOADADDR(.scratch_y);
195251

196-
.bss : {
197-
. = ALIGN(4);
198-
__bss_start__ = .;
199-
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
200-
*(COMMON)
201-
. = ALIGN(4);
202-
__bss_end__ = .;
203-
} > RAM
204-
205-
.heap (COPY): {
206-
__end__ = .;
207-
end = __end__;
208-
*(.heap*)
209-
__HeapLimit = .;
210-
} > RAM
211-
212252
/* .stack*_dummy section doesn't contains any symbols. It is only
213253
* used for linker to calculate size of stack sections, and assign
214254
* values to stack symbols later
@@ -218,16 +258,19 @@ SECTIONS {
218258
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
219259
* stack is not used then all of SCRATCH_X is free.
220260
*/
221-
.stack1_dummy (COPY): {
261+
.stack1_dummy (NOLOAD):
262+
{
222263
*(.stack1*)
223264
} > SCRATCH_X
224-
.stack_dummy (COPY): {
225-
*(.stack*)
265+
.stack_dummy (NOLOAD):
266+
{
267+
KEEP(*(.stack*))
226268
} > SCRATCH_Y
227269

228270
.flash_end : {
229-
__flash_binary_end = .;
230-
} > FLASH
271+
KEEP(*(.embedded_end_block*))
272+
PROVIDE(__flash_binary_end = .);
273+
} > FLASH =0xaa
231274

232275
/* stack limit is poorly named, but historically is maximum heap ptr */
233276
__StackLimit = ORIGIN(RAM) + LENGTH(RAM);
@@ -237,10 +280,23 @@ SECTIONS {
237280
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
238281
PROVIDE(__stack = __StackTop);
239282

283+
/* picolibc and LLVM */
284+
PROVIDE (__heap_start = __end__);
285+
PROVIDE (__heap_end = __HeapLimit);
286+
PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
287+
PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1));
288+
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
289+
290+
/* llvm-libc */
291+
PROVIDE (_end = __end__);
292+
PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
293+
240294
/* Check if data + heap + stack exceeds RAM limit */
241295
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
242296

243-
/* ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")*/
297+
ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary")
298+
ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary")
299+
244300
/* todo assert on extra code */
245301
}
246302

0 commit comments

Comments
 (0)