-
Notifications
You must be signed in to change notification settings - Fork 998
Make universal blink example work with W boards #746
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
will-v-pi
wants to merge
4
commits into
develop
Choose a base branch
from
universal-w-blink
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
c364b94
Make universal blink example work with W boards
will-v-pi ab408f8
Reduce size by making it only a universal UF2
will-v-pi 00af391
Add function docs, add separate universal README, and fixup main README
will-v-pi bd98af8
Apply suggestions from code review
will-v-pi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| # Universal Examples | ||
|
|
||
| These examples show ways to load the same code onto different chips, and package | ||
| it in such a way that the bootrom only executes the code compatible with that chip. | ||
|
|
||
| ## Universal Binary vs Universal UF2 | ||
|
|
||
| There is a difference between a **Universal Binary** and a **Universal UF2**, | ||
| for the purposes of these examples: | ||
| - A **Universal Binary** is a `.bin` file that can be loaded into flash (or sram) and executed, | ||
| allowing RP2040 and RP2350 (Arm & RISC-V) to run from identical flash contents. | ||
| - A **Universal UF2** is multiple individual `.uf2` files with different family IDs | ||
| concatenated together to create a single `.uf2` file. When dragged & dropped onto a device, | ||
| only the portion of the file with a family ID corresponding to that device will be processed, and the | ||
| rest of the file will be ignored. | ||
|
|
||
| A **Universal Binary** can be packaged into a UF2 file for loading onto a device. However, | ||
| as there isn't a common family ID between RP2040 and RP2350, you would have to package it into a **Universal UF2** with two copies (using `rp2040` and `absolute` family IDs), thus creating a **Universal UF2** of a **Universal Binary**. | ||
|
|
||
| ## How Universal Binaries work | ||
|
|
||
| Universal binaries must be recognised by both the RP2040 and RP2350 bootroms. Therefore, they need the following structure for flash binaries: | ||
| - RP2040 boot2 | ||
| - Required by the RP2040 bootrom | ||
| - RP2040 binary containing an embedded block | ||
| - The embedded block contains an `IGNORED` item due to RP2350-E13, but you can use an RP2040 | ||
| `IMAGE_DEF` item instead if not using RP2350-A2 chips | ||
| - RP2350 Arm binary containing an embedded block | ||
| - In addition to the RP2350 `IMAGE_DEF` item, this embedded block contains a | ||
| `ROLLING_WINDOW_DELTA` item to translate this binary to the start of flash for execution | ||
| - RP2350 RISC-V binary containing an embedded block | ||
| - Ditto | ||
|
|
||
| All of the embedded blocks are linked into one big block loop. | ||
|
|
||
| These are then booted by the respective bootroms: | ||
| - **RP2040** - sees the boot2 at the start and uses that to execute the RP2040 binary, as | ||
| RP2040 has no support for embedded blocks. | ||
| - **RP2350** - sees the block loop and parses it to find the correct embedded block to boot | ||
| from (Arm vs RISC-V). It then translates the flash address according to the | ||
| `ROLLING_WINDOW_DELTA` so that the binary containing that embedded block appears at the start of the | ||
| flash address space, and executes from there. | ||
|
|
||
| For no_flash binaries the RP2040 boot2 is omitted as the RP2040 bootrom just executes from the start | ||
| of SRAM, and instead of `ROLLING_WINDOW_DELTA` items the RP2350 binaries use `LOAD_MAP` items, | ||
| to copy the code in SRAM to the correct location for execution rather than using address | ||
| translation. | ||
|
|
||
| ## How you should use them | ||
|
|
||
| For most use cases, **Universal UF2s** are the best option to use. They will only load the | ||
| code that runs on that device into flash. The [blink_universal](blink_universal) example uses a | ||
| Universal UF2 for that reason, as the Wi-Fi firmware is quite large. **Universal Binaries** | ||
lurch marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| are only currently useful when the commonality of having a single `.bin` file for programming | ||
| outweighs the disadvantage of the extra flash usage. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| if (NOT PICO_BOARD STREQUAL "universal") | ||
| message(FATAL_ERROR "PICO_BOARD for blink_universal must be set to 'universal', not '${PICO_BOARD}'") | ||
| return() | ||
| endif() | ||
|
|
||
| add_executable(blink_universal | ||
| blink_universal.c | ||
| ) | ||
|
|
||
| # pull in common dependencies | ||
| target_link_libraries(blink_universal pico_stdlib hardware_adc) | ||
| target_link_libraries(blink_universal pico_cyw43_arch_none) | ||
|
|
||
| # create map/bin/hex file etc. | ||
| pico_add_extra_outputs(blink_universal) | ||
|
|
||
| # add url via pico_set_program_url | ||
| example_auto_set_url(blink_universal) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| /** | ||
| * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. | ||
| * | ||
| * SPDX-License-Identifier: BSD-3-Clause | ||
| */ | ||
|
|
||
| #include "pico/stdlib.h" | ||
| #include "pico/cyw43_arch.h" | ||
| #include "hardware/adc.h" | ||
|
|
||
| #ifndef LED_DELAY_MS | ||
| #define LED_DELAY_MS 250 | ||
| #endif | ||
|
|
||
| enum BOARD_TYPE { | ||
| BOARD_TYPE_PICO, // Pico-series board | ||
| BOARD_TYPE_PICO_W, // Pico W-series board | ||
| BOARD_TYPE_UNKNOWN, | ||
| }; | ||
will-v-pi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Detects if PICO_VSYS_PIN is actually connected to the VSYS voltage divider, | ||
| // to determine the board type. | ||
| // Also checks that the LED pin is low, which should be the case for both | ||
| // Pico-series and Pico W-series boards. | ||
| // This will work provided that the board is being powered from VSYS (i.e. it | ||
| // is using the onboard voltage regulator). | ||
| // This method is documented in section 2.4 of Connecting to the Internet with | ||
| // Raspberry Pi Pico W-series (https://pip.raspberrypi.com/documents/RP-008257-DS). | ||
| enum BOARD_TYPE detect_board_type(void) { | ||
| adc_init(); | ||
| adc_gpio_init(PICO_VSYS_PIN); | ||
| adc_select_input(PICO_VSYS_PIN - ADC_BASE_PIN); | ||
| const float conversion_factor = 3.3f / (1 << 12); | ||
| uint16_t result = adc_read(); | ||
| float voltage = result * conversion_factor; | ||
|
|
||
| gpio_init(PICO_DEFAULT_LED_PIN); | ||
| gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_IN); | ||
| bool value = gpio_get(PICO_DEFAULT_LED_PIN); | ||
|
|
||
| if (value == 0 && voltage < 0.1) { | ||
| // Pico W-series board | ||
| return BOARD_TYPE_PICO_W; | ||
| } else if (value == 0) { | ||
| // Pico-series board | ||
| return BOARD_TYPE_PICO; | ||
| } else { | ||
| // Unknown board | ||
| return BOARD_TYPE_UNKNOWN; | ||
lurch marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
|
|
||
| // Perform initialisation | ||
| int pico_led_init(enum BOARD_TYPE board_type) { | ||
| if (board_type == BOARD_TYPE_PICO_W) { | ||
| return cyw43_arch_init(); | ||
| } else { | ||
| // A device like Pico that uses a GPIO for the LED will define PICO_DEFAULT_LED_PIN | ||
| // so we can use normal GPIO functionality to turn the led on and off | ||
| gpio_init(PICO_DEFAULT_LED_PIN); | ||
| gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); | ||
| return PICO_OK; | ||
| } | ||
| } | ||
|
|
||
| // Turn the led on or off | ||
| void pico_set_led(bool led_on, enum BOARD_TYPE board_type) { | ||
| if (board_type == BOARD_TYPE_PICO_W) { | ||
| cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, led_on); | ||
| } else { | ||
| gpio_put(PICO_DEFAULT_LED_PIN, led_on); | ||
| } | ||
| } | ||
lurch marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| int main() { | ||
| enum BOARD_TYPE board_type = detect_board_type(); | ||
| int rc = pico_led_init(board_type); | ||
| hard_assert(rc == PICO_OK); | ||
| while (true) { | ||
| pico_set_led(true, board_type); | ||
| sleep_ms(LED_DELAY_MS); | ||
| pico_set_led(false, board_type); | ||
| sleep_ms(LED_DELAY_MS); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.