-
Notifications
You must be signed in to change notification settings - Fork 878
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The sample binary flashes the LED and prints Hello, world back over the UART interface
- Loading branch information
Showing
6 changed files
with
275 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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 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 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,32 @@ | ||
add_executable(uart_boot | ||
uart_boot.c | ||
) | ||
|
||
# pull in common dependencies | ||
target_link_libraries(uart_boot pico_stdlib hardware_flash) | ||
|
||
pico_embed_pt_in_binary(uart_boot ${CMAKE_CURRENT_LIST_DIR}/uart-pt.json) | ||
pico_set_uf2_family(uart_boot "absolute") | ||
|
||
# create map/bin/hex file etc. | ||
pico_add_extra_outputs(uart_boot) | ||
|
||
# add url via pico_set_program_url | ||
example_auto_set_url(uart_boot) | ||
|
||
|
||
add_executable(uart_binary | ||
uart_binary.c | ||
) | ||
|
||
# pull in common dependencies | ||
target_link_libraries(uart_binary pico_stdlib) | ||
|
||
pico_set_binary_type(uart_binary no_flash) | ||
pico_package_uf2_output(uart_binary 0x10000000) | ||
|
||
# create map/bin/hex/uf2 file etc. | ||
pico_add_extra_outputs(uart_binary) | ||
|
||
# call pico_set_program_url to set path to example on github, so users can find the source for an example via picotool | ||
example_auto_set_url(uart_binary) |
This file contains 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,23 @@ | ||
{ | ||
"version": [1, 0], | ||
"unpartitioned": { | ||
"families": ["absolute"], | ||
"permissions": { | ||
"secure": "rw", | ||
"nonsecure": "rw", | ||
"bootloader": "rw" | ||
} | ||
}, | ||
"partitions": [ | ||
{ | ||
"start": "128K", | ||
"size": "32K", | ||
"families": ["rp2350-arm-s"], | ||
"permissions": { | ||
"secure": "rw", | ||
"nonsecure": "rw", | ||
"bootloader": "rw" | ||
} | ||
} | ||
] | ||
} |
This file contains 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,65 @@ | ||
/** | ||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd. | ||
* | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
#include "pico/stdlib.h" | ||
#include "hardware/uart.h" | ||
#include "hardware/structs/pads_qspi.h" | ||
#include "hardware/structs/io_qspi.h" | ||
|
||
#ifndef LED_DELAY_MS | ||
#define LED_DELAY_MS 500 | ||
#endif | ||
|
||
// Initialize the GPIO for the LED | ||
void pico_led_init(void) { | ||
#ifdef PICO_DEFAULT_LED_PIN | ||
// 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); | ||
#endif | ||
} | ||
|
||
// Turn the LED on or off | ||
void pico_set_led(bool led_on) { | ||
#if defined(PICO_DEFAULT_LED_PIN) | ||
// Just set the GPIO on or off | ||
gpio_put(PICO_DEFAULT_LED_PIN, led_on); | ||
#endif | ||
} | ||
|
||
// Set function for QSPI GPIO pin | ||
void qspi_gpio_set_function(uint gpio, gpio_function_t fn) { | ||
// Set input enable on, output disable off | ||
hw_write_masked(&pads_qspi_hw->io[gpio], | ||
PADS_QSPI_GPIO_QSPI_SD2_IE_BITS, | ||
PADS_QSPI_GPIO_QSPI_SD2_IE_BITS | PADS_QSPI_GPIO_QSPI_SD2_OD_BITS | ||
); | ||
// Zero all fields apart from fsel; we want this IO to do what the peripheral tells it. | ||
// This doesn't affect e.g. pullup/pulldown, as these are in pad controls. | ||
io_qspi_hw->io[gpio].ctrl = fn << IO_QSPI_GPIO_QSPI_SD2_CTRL_FUNCSEL_LSB; | ||
|
||
// Remove pad isolation now that the correct peripheral is in control of the pad | ||
hw_clear_bits(&pads_qspi_hw->io[gpio], PADS_QSPI_GPIO_QSPI_SD2_ISO_BITS); | ||
} | ||
|
||
int main() { | ||
pico_led_init(); | ||
|
||
// SD2 is QSPI GPIO 3, SD3 is QSPI GPIO 4 | ||
qspi_gpio_set_function(3, GPIO_FUNC_UART_AUX); | ||
qspi_gpio_set_function(4, GPIO_FUNC_UART_AUX); | ||
|
||
uart_init(uart0, 1000000); | ||
|
||
while (true) { | ||
uart_puts(uart0, "Hello, world\n"); | ||
pico_set_led(true); | ||
sleep_ms(LED_DELAY_MS); | ||
pico_set_led(false); | ||
sleep_ms(LED_DELAY_MS); | ||
} | ||
} |
This file contains 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,152 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include "pico/stdlib.h" | ||
#include "hardware/uart.h" | ||
#include "pico/bootrom.h" | ||
#include "boot/picobin.h" | ||
#include "hardware/flash.h" | ||
|
||
// UART defines for uart boot | ||
#define UART_ID uart1 | ||
#define BAUD_RATE 1000000 | ||
|
||
// Use pins 4 and 5 for uart boot | ||
#define UART_TX_PIN 4 | ||
#define UART_RX_PIN 5 | ||
|
||
// Use pin 3 for the RUN pin on the other chip | ||
#define RUN_PIN 3 | ||
|
||
|
||
void reset_chip() { | ||
// Toggle run pin | ||
gpio_put(RUN_PIN, false); | ||
sleep_ms(1); | ||
gpio_put(RUN_PIN, true); | ||
} | ||
|
||
|
||
void uart_boot() { | ||
uint knocks = 0; | ||
while (true) { | ||
// Send the knock sequence | ||
uart_putc_raw(UART_ID, 0x56); | ||
uart_putc_raw(UART_ID, 0xff); | ||
uart_putc_raw(UART_ID, 0x8b); | ||
uart_putc_raw(UART_ID, 0xe4); | ||
uart_putc_raw(UART_ID, 'n'); | ||
|
||
if (uart_is_readable_within_us(UART_ID, 1000)) { | ||
char in = uart_getc(UART_ID); | ||
printf("%c\n", in); | ||
break; | ||
} else { | ||
if (knocks > 10) { | ||
printf("No response - resetting\n"); | ||
reset_chip(); | ||
return; | ||
} | ||
printf("No response - knocking again\n"); | ||
knocks++; | ||
} | ||
} | ||
|
||
printf("Boot starting\n"); | ||
|
||
// Get partition location in flash | ||
const int buf_words = (16 * 4) + 1; // maximum of 16 partitions, each with maximum of 4 words returned, plus 1 | ||
uint32_t* buffer = malloc(buf_words * 4); | ||
|
||
int ret = rom_get_partition_table_info(buffer, buf_words, PT_INFO_PARTITION_LOCATION_AND_FLAGS | PT_INFO_SINGLE_PARTITION | (0 << 24)); | ||
assert(buffer[0] == (PT_INFO_PARTITION_LOCATION_AND_FLAGS | PT_INFO_SINGLE_PARTITION)); | ||
assert(ret == 3); | ||
|
||
uint32_t location_and_permissions = buffer[1]; | ||
uint32_t saddr = XIP_BASE + ((location_and_permissions >> PICOBIN_PARTITION_LOCATION_FIRST_SECTOR_LSB) & 0x1fffu) * FLASH_SECTOR_SIZE; | ||
uint32_t eaddr = XIP_BASE + (((location_and_permissions >> PICOBIN_PARTITION_LOCATION_LAST_SECTOR_LSB) & 0x1fffu) + 1) * FLASH_SECTOR_SIZE; | ||
printf("Start %08x, end %08x\n", saddr, eaddr); | ||
|
||
free(buffer); | ||
|
||
printf("Writing binary\n"); | ||
uint32_t tstart = time_us_32(); | ||
uint32_t caddr = saddr; | ||
while (caddr < eaddr) { | ||
uart_putc_raw(UART_ID, 'w'); | ||
char *buf = (char*)caddr; | ||
for (int i=0; i < 32; i++) { | ||
uart_putc_raw(UART_ID, buf[i]); | ||
} | ||
if (!uart_is_readable_within_us(UART_ID, 500)) { | ||
// Detect hangs and reset the chip | ||
printf("Write has hung - resetting\n"); | ||
reset_chip(); | ||
return; | ||
} | ||
char in = uart_getc(UART_ID); | ||
printf("%c\n", in); | ||
caddr += 32; | ||
} | ||
|
||
uint32_t tend = time_us_32(); | ||
printf("Write took %dus\n", tend - tstart); | ||
printf("Write complete - executing\n"); | ||
uart_putc_raw(UART_ID, 'x'); | ||
if (!uart_is_readable_within_us(UART_ID, 500)) { | ||
// Detect hangs and reset the chip | ||
printf("Execute has hung - resetting\n"); | ||
reset_chip(); | ||
return; | ||
} | ||
char in = uart_getc(UART_ID); | ||
printf("%c\n", in); | ||
} | ||
|
||
|
||
int main() | ||
{ | ||
stdio_init_all(); | ||
|
||
// Set up our UART for booting the other device | ||
uart_init(UART_ID, BAUD_RATE); | ||
gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART); | ||
gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART); | ||
|
||
// Set up run pin | ||
gpio_init(RUN_PIN); | ||
gpio_set_dir(RUN_PIN, GPIO_OUT); | ||
|
||
// Reset chip | ||
reset_chip(); | ||
|
||
|
||
while (true) { | ||
char splash[] = "RP2350"; | ||
char hello[] = "Hello"; | ||
char buf[500] = {0}; | ||
int i = 0; | ||
while (uart_is_readable(UART_ID) && i < sizeof(buf)) { | ||
char in = uart_getc(UART_ID); | ||
printf("%c", in); | ||
buf[i] = in; | ||
i++; | ||
} | ||
if (i > 0) { | ||
printf(" ...Read done\n"); | ||
} | ||
char *ptr = memchr(buf, 'R', sizeof(buf)); | ||
if (ptr && strncmp(ptr, splash, sizeof(splash) - 1) == 0) { | ||
printf("Splash found\n"); | ||
uart_boot(); | ||
} else { | ||
ptr = memchr(buf, 'H', sizeof(buf)); | ||
if (ptr && strncmp(ptr, hello, sizeof(hello) - 1) == 0) { | ||
printf("Device is running\n"); | ||
} else { | ||
printf("Device not running - attempting reset\n"); | ||
reset_chip(); | ||
} | ||
} | ||
sleep_ms(1000); | ||
} | ||
} |