Skip to content

Commit 9efa702

Browse files
committed
Add partitions for Wi-Fi firmware
Enabled using the pico_use_partition_firmware(exe_name) cmake function
1 parent 9260cf7 commit 9efa702

File tree

7 files changed

+348
-8
lines changed

7 files changed

+348
-8
lines changed

src/rp2_common/pico_cyw43_driver/CMakeLists.txt

+100
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,104 @@ if (EXISTS ${PICO_CYW43_DRIVER_PATH}/${CYW43_DRIVER_TEST_FILE})
155155
endfunction()
156156

157157
pico_promote_common_scope_vars()
158+
159+
# Set env var, so it can be accessed in the function
160+
set(ENV{PICO_CYW43_DRIVER_CURRENT_PATH} ${CMAKE_CURRENT_LIST_DIR})
161+
function(pico_use_partition_firmware TARGET)
162+
target_compile_definitions(${TARGET} PRIVATE CYW43_USE_PARTITION_FIRMWARE=1)
163+
pico_embed_pt_in_binary(${TARGET} $ENV{PICO_CYW43_DRIVER_CURRENT_PATH}/wifi_pt.json)
164+
165+
find_package (Python3 REQUIRED COMPONENTS Interpreter)
166+
167+
# Wifi firmware blob
168+
add_custom_target(${TARGET}_firmware_w_blob DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/firmware_w_blob.S)
169+
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/firmware_w_blob.S
170+
COMMAND ${Python3_EXECUTABLE} $ENV{PICO_CYW43_DRIVER_CURRENT_PATH}/cyw43_firmware.py ${PICO_CYW43_DRIVER_PATH}/firmware/w43439A0_7_95_49_00_combined.h ${CMAKE_CURRENT_BINARY_DIR}/firmware_w_blob.S
171+
)
172+
173+
# Wifi and bluetooth firmware blob
174+
add_custom_target(${TARGET}_firmware_wb_blob DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/firmware_wb_blob.S)
175+
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/firmware_wb_blob.S
176+
COMMAND ${Python3_EXECUTABLE} $ENV{PICO_CYW43_DRIVER_CURRENT_PATH}/cyw43_firmware.py ${PICO_CYW43_DRIVER_PATH}/firmware/wb43439A0_7_95_49_00_combined.h ${CMAKE_CURRENT_BINARY_DIR}/firmware_wb_blob.S
177+
)
178+
179+
# Create UF2s for all the variants - Wifi vs Wifi+Bluetooth, and TBYB
180+
add_executable(${TARGET}_firmware_w
181+
$ENV{PICO_CYW43_DRIVER_CURRENT_PATH}/wifi_firmware.S)
182+
add_executable(${TARGET}_firmware_w_tbyb
183+
$ENV{PICO_CYW43_DRIVER_CURRENT_PATH}/wifi_firmware.S)
184+
add_executable(${TARGET}_firmware_wb
185+
$ENV{PICO_CYW43_DRIVER_CURRENT_PATH}/wifi_firmware.S)
186+
add_executable(${TARGET}_firmware_wb_tbyb
187+
$ENV{PICO_CYW43_DRIVER_CURRENT_PATH}/wifi_firmware.S)
188+
189+
add_dependencies(${TARGET}_firmware_w ${TARGET}_firmware_w_blob)
190+
add_dependencies(${TARGET}_firmware_w_tbyb ${TARGET}_firmware_w_blob)
191+
add_dependencies(${TARGET}_firmware_wb ${TARGET}_firmware_wb_blob)
192+
add_dependencies(${TARGET}_firmware_wb_tbyb ${TARGET}_firmware_wb_blob)
193+
194+
target_include_directories(${TARGET}_firmware_w PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
195+
target_include_directories(${TARGET}_firmware_w_tbyb PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
196+
target_include_directories(${TARGET}_firmware_wb PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
197+
target_include_directories(${TARGET}_firmware_wb_tbyb PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
198+
199+
target_compile_definitions(${TARGET}_firmware_w PRIVATE
200+
NO_PICO_PLATFORM=1
201+
)
202+
target_compile_definitions(${TARGET}_firmware_w_tbyb PRIVATE
203+
NO_PICO_PLATFORM=1
204+
PICO_CRT0_IMAGE_TYPE_TBYB=1
205+
)
206+
target_compile_definitions(${TARGET}_firmware_wb PRIVATE
207+
NO_PICO_PLATFORM=1
208+
WB_FIRMWARE=1
209+
)
210+
target_compile_definitions(${TARGET}_firmware_wb_tbyb PRIVATE
211+
NO_PICO_PLATFORM=1
212+
PICO_CRT0_IMAGE_TYPE_TBYB=1
213+
WB_FIRMWARE=1
214+
)
215+
216+
target_link_options(${TARGET}_firmware_w PRIVATE -nostartfiles -nodefaultlibs -Ttext=0x20000000)
217+
target_link_options(${TARGET}_firmware_w_tbyb PRIVATE -nostartfiles -nodefaultlibs -Ttext=0x20000000)
218+
target_link_options(${TARGET}_firmware_wb PRIVATE -nostartfiles -nodefaultlibs -Ttext=0x20000000)
219+
target_link_options(${TARGET}_firmware_wb_tbyb PRIVATE -nostartfiles -nodefaultlibs -Ttext=0x20000000)
220+
221+
target_link_libraries(${TARGET}_firmware_w boot_picobin_headers)
222+
target_link_libraries(${TARGET}_firmware_w_tbyb boot_picobin_headers)
223+
target_link_libraries(${TARGET}_firmware_wb boot_picobin_headers)
224+
target_link_libraries(${TARGET}_firmware_wb_tbyb boot_picobin_headers)
225+
226+
get_target_property(hasSigfile ${TARGET} PICOTOOL_SIGFILE)
227+
if (hasSigfile)
228+
pico_sign_binary(${TARGET}_firmware_w ${sigfile})
229+
pico_sign_binary(${TARGET}_firmware_w_tbyb ${sigfile})
230+
pico_sign_binary(${TARGET}_firmware_wb ${sigfile})
231+
pico_sign_binary(${TARGET}_firmware_wb_tbyb ${sigfile})
232+
endif()
233+
234+
pico_hash_binary(${TARGET}_firmware_w)
235+
pico_hash_binary(${TARGET}_firmware_w_tbyb)
236+
pico_hash_binary(${TARGET}_firmware_wb)
237+
pico_hash_binary(${TARGET}_firmware_wb_tbyb)
238+
239+
pico_set_uf2_family(${TARGET}_firmware_w 0x12345678)
240+
pico_set_uf2_family(${TARGET}_firmware_w_tbyb 0x12345678)
241+
pico_set_uf2_family(${TARGET}_firmware_wb 0x12345678)
242+
pico_set_uf2_family(${TARGET}_firmware_wb_tbyb 0x12345678)
243+
244+
pico_package_uf2_output(${TARGET}_firmware_w 0x10000000)
245+
pico_package_uf2_output(${TARGET}_firmware_w_tbyb 0x10000000)
246+
pico_package_uf2_output(${TARGET}_firmware_wb 0x10000000)
247+
pico_package_uf2_output(${TARGET}_firmware_wb_tbyb 0x10000000)
248+
249+
pico_add_extra_outputs(${TARGET}_firmware_w)
250+
pico_add_extra_outputs(${TARGET}_firmware_w_tbyb)
251+
pico_add_extra_outputs(${TARGET}_firmware_wb)
252+
pico_add_extra_outputs(${TARGET}_firmware_wb_tbyb)
253+
254+
add_dependencies(${TARGET}
255+
${TARGET}_firmware_w ${TARGET}_firmware_w_tbyb
256+
${TARGET}_firmware_wb ${TARGET}_firmware_wb_tbyb)
257+
endfunction()
158258
endif()

src/rp2_common/pico_cyw43_driver/cyw43_driver.c

+87-8
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,17 @@
1919
#define CYW43_SLEEP_CHECK_MS 50
2020
#endif
2121

22-
static async_context_t *cyw43_async_context;
22+
static async_context_t *cyw43_async_context = NULL;
23+
24+
#if CYW43_USE_PARTITION_FIRMWARE
25+
#include "pico/bootrom.h"
26+
#include "boot/picobin.h"
27+
#include <stdlib.h>
28+
29+
int32_t cyw43_wifi_fw_len;
30+
int32_t cyw43_clm_len;
31+
uintptr_t fw_data;
32+
#endif
2333

2434
static void cyw43_sleep_timeout_reached(async_context_t *context, async_at_time_worker_t *worker);
2535
static void cyw43_do_poll(async_context_t *context, async_when_pending_worker_t *worker);
@@ -104,6 +114,73 @@ static void cyw43_sleep_timeout_reached(async_context_t *context, __unused async
104114
}
105115

106116
bool cyw43_driver_init(async_context_t *context) {
117+
#if CYW43_USE_PARTITION_FIRMWARE
118+
const int buf_words = (16 * 4) + 1; // maximum of 16 partitions, each with maximum of 4 words returned, plus 1
119+
uint32_t* buffer = malloc(buf_words * 4);
120+
int ret = rom_get_partition_table_info(buffer, buf_words, PT_INFO_PARTITION_LOCATION_AND_FLAGS | PT_INFO_PARTITION_ID);
121+
122+
assert(buffer[0] == (PT_INFO_PARTITION_LOCATION_AND_FLAGS | PT_INFO_PARTITION_ID));
123+
124+
if (ret > 0) {
125+
int i = 1;
126+
int p = 0;
127+
int picked_p = -1;
128+
while (i < ret) {
129+
i++;
130+
uint32_t flags_and_permissions = buffer[i++];
131+
bool has_id = (flags_and_permissions & PICOBIN_PARTITION_FLAGS_HAS_ID_BITS);
132+
if (has_id) {
133+
uint64_t id = 0;
134+
id |= buffer[i++];
135+
id |= ((uint64_t)(buffer[i++]) << 32ull);
136+
if (id == 0x123456789abcdef0) {
137+
picked_p = p;
138+
}
139+
}
140+
141+
p++;
142+
}
143+
144+
if (picked_p >= 0) {
145+
uint32_t* workarea = malloc(0x1000);
146+
picked_p = rom_pick_ab_update_partition(workarea, 0x1000, picked_p);
147+
free(workarea);
148+
149+
if (picked_p < 0) {
150+
if (picked_p == BOOTROM_ERROR_NOT_FOUND) {
151+
CYW43_DEBUG("Chosen CYW43 firmware partition was not verified\n");
152+
} else if (picked_p == BOOTROM_ERROR_NOT_PERMITTED) {
153+
CYW43_DEBUG("Too many update boots going on at once\n");
154+
}
155+
return false;
156+
}
157+
158+
CYW43_DEBUG("Chosen CYW43 firmware in partition %d\n", picked_p);
159+
int ret = rom_get_partition_table_info(buffer, buf_words, PT_INFO_PARTITION_LOCATION_AND_FLAGS | PT_INFO_SINGLE_PARTITION | (picked_p << 24));
160+
assert(buffer[0] == (PT_INFO_PARTITION_LOCATION_AND_FLAGS | PT_INFO_SINGLE_PARTITION));
161+
assert(ret == 3);
162+
163+
uint32_t location_and_permissions = buffer[1];
164+
uint32_t saddr = ((location_and_permissions >> PICOBIN_PARTITION_LOCATION_FIRST_SECTOR_LSB) & 0x1fffu) * 4096;
165+
uint32_t eaddr = (((location_and_permissions >> PICOBIN_PARTITION_LOCATION_LAST_SECTOR_LSB) & 0x1fffu) + 1) * 4096;
166+
// Starts with metadata block
167+
while(saddr < eaddr && *(uint32_t*)(XIP_NOCACHE_NOALLOC_NOTRANSLATE_BASE + saddr) != PICOBIN_BLOCK_MARKER_END) {
168+
saddr += 4;
169+
}
170+
saddr += 4;
171+
// Now onto data
172+
cyw43_wifi_fw_len = *(uint32_t*)(XIP_NOCACHE_NOALLOC_NOTRANSLATE_BASE + saddr);
173+
cyw43_clm_len = *(uint32_t*)(XIP_NOCACHE_NOALLOC_NOTRANSLATE_BASE + saddr + 4);
174+
fw_data = XIP_NOCACHE_NOALLOC_NOTRANSLATE_BASE + saddr + 8;
175+
}
176+
free(buffer);
177+
} else {
178+
free(buffer);
179+
CYW43_DEBUG("No partition table, so cannot get firmware from partition - get_partition_table_info returned %d\n", ret);
180+
return false;
181+
}
182+
183+
#endif
107184
cyw43_init(&cyw43_state);
108185
cyw43_async_context = context;
109186
// we need the IRQ to be on the same core as the context, because we need to be able to enable/disable the IRQ
@@ -114,13 +191,15 @@ bool cyw43_driver_init(async_context_t *context) {
114191
}
115192

116193
void cyw43_driver_deinit(async_context_t *context) {
117-
assert(context == cyw43_async_context);
118-
async_context_remove_at_time_worker(context, &sleep_timeout_worker);
119-
async_context_remove_when_pending_worker(context, &cyw43_poll_worker);
120-
// the IRQ IS on the same core as the context, so must be de-initialized there
121-
async_context_execute_sync(context, cyw43_irq_deinit, NULL);
122-
cyw43_deinit(&cyw43_state);
123-
cyw43_async_context = NULL;
194+
if (cyw43_async_context != NULL) {
195+
assert(context == cyw43_async_context);
196+
async_context_remove_at_time_worker(context, &sleep_timeout_worker);
197+
async_context_remove_when_pending_worker(context, &cyw43_poll_worker);
198+
// the IRQ IS on the same core as the context, so must be de-initialized there
199+
async_context_execute_sync(context, cyw43_irq_deinit, NULL);
200+
cyw43_deinit(&cyw43_state);
201+
cyw43_async_context = NULL;
202+
}
124203
}
125204

126205
// todo maybe add an #ifdef in cyw43_driver
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import sys
2+
3+
with open(sys.argv[1], "r") as f:
4+
data = f.read()
5+
lines = data.split(";")
6+
for line in lines[1].split("\n"):
7+
if "#define CYW43_WIFI_FW_LEN" in line:
8+
cyw43_wifi_fw_len = int(line.split(")")[0].split("(")[-1])
9+
if "#define CYW43_CLM_LEN" in line:
10+
cyw43_clm_len = int(line.split(")")[0].split("(")[-1])
11+
data = lines[0]
12+
bits = data.split(",")
13+
bits[0] = bits[0].split("{")[-1]
14+
bits[-1] = bits[-1].split("}")[0]
15+
for i in range(len(bits)):
16+
bits[i] = bits[i].strip()
17+
bits[i] = bits[i].strip(',')
18+
bits[i] = int(bits[i], base=0)
19+
print(f"Start {bits[4]}, end {bits[-1]}, num {len(bits)}")
20+
print(bits[:10])
21+
22+
print(f"Wifi {cyw43_wifi_fw_len}, clm {cyw43_clm_len}")
23+
24+
data = (
25+
cyw43_wifi_fw_len.to_bytes(4, 'little', signed=True) +
26+
cyw43_clm_len.to_bytes(4, 'little', signed=True) +
27+
bytearray(bits)
28+
)
29+
30+
with open(sys.argv[2], "w") as f:
31+
for b in data:
32+
f.write(f".byte 0x{b:02x}\n")

src/rp2_common/pico_cyw43_driver/include/cyw43_configport.h

+4
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,16 @@ extern "C" {
6363
#endif
6464

6565
#ifndef CYW43_CHIPSET_FIRMWARE_INCLUDE_FILE
66+
#if CYW43_USE_PARTITION_FIRMWARE
67+
#define CYW43_CHIPSET_FIRMWARE_INCLUDE_FILE "cyw43_partition_firmware.h"
68+
#else
6669
#if CYW43_ENABLE_BLUETOOTH
6770
#define CYW43_CHIPSET_FIRMWARE_INCLUDE_FILE "wb43439A0_7_95_49_00_combined.h"
6871
#else
6972
#define CYW43_CHIPSET_FIRMWARE_INCLUDE_FILE "w43439A0_7_95_49_00_combined.h"
7073
#endif
7174
#endif
75+
#endif
7276

7377
#ifndef CYW43_WIFI_NVRAM_INCLUDE_FILE
7478
#define CYW43_WIFI_NVRAM_INCLUDE_FILE "wifi_nvram_43439.h"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
extern int cyw43_wifi_fw_len;
3+
extern int cyw43_clm_len;
4+
5+
#define CYW43_WIFI_FW_LEN (cyw43_wifi_fw_len)
6+
#define CYW43_CLM_LEN (cyw43_clm_len)
7+
extern uintptr_t fw_data;
8+
9+
#include "boot/picobin.h"
10+
#include "pico/bootrom.h"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#include "boot/picobin.h"
2+
3+
#if PICO_CRT0_IMAGE_TYPE_TBYB
4+
#define CRT0_TBYB_FLAG PICOBIN_IMAGE_TYPE_EXE_TBYB_BITS
5+
#else
6+
#define CRT0_TBYB_FLAG 0
7+
#endif
8+
9+
.section .text
10+
.global _start
11+
_start:
12+
.word 0
13+
.word 0
14+
.word 0
15+
.word 0
16+
17+
.p2align 2
18+
embedded_block:
19+
.word PICOBIN_BLOCK_MARKER_START
20+
21+
.byte PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE
22+
.byte 0x1 // 1 word
23+
.hword PICOBIN_IMAGE_TYPE_IMAGE_TYPE_AS_BITS(EXE) | \
24+
PICOBIN_IMAGE_TYPE_EXE_CPU_AS_BITS(RISCV) | \
25+
PICOBIN_IMAGE_TYPE_EXE_CHIP_AS_BITS(RP2350) | \
26+
CRT0_TBYB_FLAG
27+
28+
// Entry point into SRAM
29+
.byte PICOBIN_BLOCK_ITEM_1BS_ENTRY_POINT
30+
.byte 0x3 // word size to next item
31+
.byte 0 // pad
32+
.byte 0 // pad
33+
.word _start
34+
.word 0x20082000 // stack pointer
35+
36+
_lm_item:
37+
.byte PICOBIN_BLOCK_ITEM_LOAD_MAP
38+
.byte 7
39+
.byte 0 // pad
40+
.byte 2 // 2 entries
41+
// To sign the firmware
42+
.word (_start - _lm_item)
43+
.word _start
44+
.word (firmware_end - _start)
45+
// But clear SRAM if actually running this, so it doesn't boot
46+
.word 0
47+
.word _start
48+
.word 0x00082000
49+
50+
.byte PICOBIN_BLOCK_ITEM_2BS_LAST
51+
.hword (embedded_block_end - embedded_block - 16 ) / 4 // total size of all
52+
.byte 0
53+
.word 0
54+
.word PICOBIN_BLOCK_MARKER_END
55+
embedded_block_end:
56+
57+
#if WB_FIRMWARE
58+
#include "firmware_wb_blob.S"
59+
#else
60+
#include "firmware_w_blob.S"
61+
#endif
62+
63+
firmware_end:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"version": [1, 0],
3+
"unpartitioned": {
4+
"families": ["absolute"],
5+
"permissions": {
6+
"secure": "rw",
7+
"nonsecure": "rw",
8+
"bootloader": "rw"
9+
}
10+
},
11+
"partitions": [
12+
{
13+
"name": "Main",
14+
"id": 0,
15+
"start": 0,
16+
"size": "3500K",
17+
"families": ["rp2350-arm-s", "rp2350-riscv"],
18+
"permissions": {
19+
"secure": "rw",
20+
"nonsecure": "rw",
21+
"bootloader": "rw"
22+
}
23+
},
24+
{
25+
"name": "Wi-Fi Firmware",
26+
"id": "0x123456789abcdef0",
27+
"start": "3500k",
28+
"size": "240K",
29+
"families": ["0x12345678"],
30+
"permissions": {
31+
"secure": "rw",
32+
"nonsecure": "rw",
33+
"bootloader": "rw"
34+
},
35+
"ignored_during_riscv_boot": true,
36+
"no_reboot_on_uf2_download": true
37+
},
38+
{
39+
"start": "3500k",
40+
"size": "240k",
41+
"families": ["0x12345678"],
42+
"permissions": {
43+
"secure": "rw",
44+
"nonsecure": "rw",
45+
"bootloader": "rw"
46+
},
47+
"link": ["a", 1],
48+
"ignored_during_riscv_boot": true,
49+
"no_reboot_on_uf2_download": true
50+
}
51+
]
52+
}

0 commit comments

Comments
 (0)