From 90d785bb5ba6bc1887f313b2c497123707fb4d2b Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Thu, 28 Jan 2021 16:05:03 +0000 Subject: [PATCH 01/30] Standardise start/end comment tags (to our internal format) (#20) --- divider/hello_divider.c | 4 ++-- flash/cache_perfctr/flash_cache_perfctr.c | 4 ++-- flash/xip_stream/flash_xip_stream.c | 10 +++++----- gpio/hello_7segment/hello_7segment.c | 4 ++-- multicore/hello_multicore/multicore.c | 6 +++--- multicore/multicore_fifo_irqs/multicore_fifo_irqs.c | 4 ++-- multicore/multicore_runner/multicore_runner.c | 4 ++-- pwm/hello_pwm/hello_pwm.c | 4 ++-- usb/device/dev_lowlevel/dev_lowlevel.c | 6 +++--- 9 files changed, 23 insertions(+), 23 deletions(-) diff --git a/divider/hello_divider.c b/divider/hello_divider.c index 5f934a7..95c16e9 100644 --- a/divider/hello_divider.c +++ b/divider/hello_divider.c @@ -8,7 +8,7 @@ #include "pico/stdlib.h" #include "hardware/divider.h" -// tag::hello_divider[] +/// \tag::hello_divider[] int main() { stdio_init_all(); printf("Hello, divider!\n"); @@ -72,4 +72,4 @@ int main() { printf("outer divide %d / %d = %d\n", dividend, divisor, tmp); return 0; } -// end::hello_divider[] +/// \end::hello_divider[] diff --git a/flash/cache_perfctr/flash_cache_perfctr.c b/flash/cache_perfctr/flash_cache_perfctr.c index 910dfbd..03b5d61 100644 --- a/flash/cache_perfctr/flash_cache_perfctr.c +++ b/flash/cache_perfctr/flash_cache_perfctr.c @@ -26,7 +26,7 @@ void __no_inline_not_in_flash_func(check)(bool cond, const char *msg) { void __no_inline_not_in_flash_func(check_hit_miss_invalidate)() { io_rw_32 *test_data_ptr = (io_rw_32 *) test_data; - //tag::check_hit_miss_invalidate[] + /// \tag::check_hit_miss_invalidate[] // Flush cache to make sure we miss the first time we access test_data xip_ctrl_hw->flush = 1; while (!(xip_ctrl_hw->stat & XIP_STAT_FLUSH_READY_BITS)) @@ -53,7 +53,7 @@ void __no_inline_not_in_flash_func(check_hit_miss_invalidate)() { (void) *test_data_ptr; check(xip_ctrl_hw->ctr_hit == 2 && xip_ctrl_hw->ctr_acc == 4, "Second access after invalidation should hit again"); - //end::check_hit_miss_invalidate[] + /// \end::check_hit_miss_invalidate[] } // Some code which achieves a very high cache hit rate: diff --git a/flash/xip_stream/flash_xip_stream.c b/flash/xip_stream/flash_xip_stream.c index dfe33af..51ef7ef 100644 --- a/flash/xip_stream/flash_xip_stream.c +++ b/flash/xip_stream/flash_xip_stream.c @@ -41,12 +41,12 @@ int main() { // writing 0 to stream_ctr. // It's a good idea to drain the FIFO first! printf("Starting stream from %p\n", random_test_data); - //tag::start_stream[] + /// \tag::start_stream[] while (!(xip_ctrl_hw->stat & XIP_STAT_FIFO_EMPTY)) (void) xip_ctrl_hw->stream_fifo; xip_ctrl_hw->stream_addr = (uint32_t) &random_test_data[0]; xip_ctrl_hw->stream_ctr = count_of(random_test_data); - //end::start_stream[] + /// \end::start_stream[] // Start DMA transfer from XIP stream FIFO to our buffer in memory. Use // the auxiliary bus slave for the DMA<-FIFO accesses, to avoid stalling @@ -54,7 +54,7 @@ int main() { // example, but it can have a huge effect on DMA throughput. printf("Starting DMA\n"); - //tag::start_dma[] + /// \tag::start_dma[] const uint dma_chan = 0; dma_channel_config cfg = dma_channel_get_default_config(dma_chan); channel_config_set_read_increment(&cfg, false); @@ -68,7 +68,7 @@ int main() { count_of(random_test_data), // Transfer count true // Start immediately! ); - //end::start_dma[] + /// \end::start_dma[] dma_channel_wait_for_finish_blocking(dma_chan); @@ -85,4 +85,4 @@ int main() { } if (!mismatch) printf("Data check OK\n"); -} \ No newline at end of file +} diff --git a/gpio/hello_7segment/hello_7segment.c b/gpio/hello_7segment/hello_7segment.c index 2f375be..a10c8e2 100644 --- a/gpio/hello_7segment/hello_7segment.c +++ b/gpio/hello_7segment/hello_7segment.c @@ -42,7 +42,7 @@ int bits[10] = { 0x67 // 9 }; -// tag::hello_gpio[] +/// \tag::hello_gpio[] int main() { stdio_init_all(); printf("Hello, 7segment - press button to count down!\n"); @@ -92,4 +92,4 @@ int main() { return 0; } -// end::hello_gpio[] +/// \end::hello_gpio[] diff --git a/multicore/hello_multicore/multicore.c b/multicore/hello_multicore/multicore.c index db4360c..7ad036c 100644 --- a/multicore/hello_multicore/multicore.c +++ b/multicore/hello_multicore/multicore.c @@ -29,7 +29,7 @@ int main() { stdio_init_all(); printf("Hello, multicore!\n"); - ///tag::setup_multicore[] + /// \tag::setup_multicore[] multicore_launch_core1(core1_entry); @@ -44,5 +44,5 @@ int main() { printf("It's all gone well on core 0!"); } - ///end::setup_multicore[] -} \ No newline at end of file + /// \end::setup_multicore[] +} diff --git a/multicore/multicore_fifo_irqs/multicore_fifo_irqs.c b/multicore/multicore_fifo_irqs/multicore_fifo_irqs.c index d295435..fe5ab57 100644 --- a/multicore/multicore_fifo_irqs/multicore_fifo_irqs.c +++ b/multicore/multicore_fifo_irqs/multicore_fifo_irqs.c @@ -9,7 +9,7 @@ #include "pico/multicore.h" #include "hardware/irq.h" -///tag::multicore_fifo_irqs[] +/// \tag::multicore_fifo_irqs[] #define FLAG_VALUE1 123 #define FLAG_VALUE2 321 @@ -73,4 +73,4 @@ int main() { tight_loop_contents(); } -///end::multicore_fifo_irqs[] +/// \end::multicore_fifo_irqs[] diff --git a/multicore/multicore_runner/multicore_runner.c b/multicore/multicore_runner/multicore_runner.c index 624128a..9a5ec93 100644 --- a/multicore/multicore_runner/multicore_runner.c +++ b/multicore/multicore_runner/multicore_runner.c @@ -8,7 +8,7 @@ #include "pico/stdlib.h" #include "pico/multicore.h" -///tag::multicore_dispatch[] +/// \tag::multicore_dispatch[] #define FLAG_VALUE 123 @@ -80,4 +80,4 @@ int main() { } -///end::multicore_dispatch[] +/// \end::multicore_dispatch[] diff --git a/pwm/hello_pwm/hello_pwm.c b/pwm/hello_pwm/hello_pwm.c index bfce35e..83965bf 100644 --- a/pwm/hello_pwm/hello_pwm.c +++ b/pwm/hello_pwm/hello_pwm.c @@ -10,7 +10,7 @@ #include "hardware/pwm.h" int main() { - ///tag::setup_pwm[] + /// \tag::setup_pwm[] // Tell GPIO 0 and 1 they are allocated to the PWM gpio_set_function(0, GPIO_FUNC_PWM); @@ -27,7 +27,7 @@ int main() { pwm_set_chan_level(slice_num, PWM_CHAN_B, 3); // Set the PWM running pwm_set_enabled(slice_num, true); - ///end::setup_pwm[] + /// \end::setup_pwm[] // Note we could also use pwm_set_gpio_level(gpio, x) which looks up the // correct slice and channel for a given GPIO. diff --git a/usb/device/dev_lowlevel/dev_lowlevel.c b/usb/device/dev_lowlevel/dev_lowlevel.c index 9115914..cf53170 100644 --- a/usb/device/dev_lowlevel/dev_lowlevel.c +++ b/usb/device/dev_lowlevel/dev_lowlevel.c @@ -480,7 +480,7 @@ static void usb_handle_buff_status() { * @brief USB interrupt handler * */ -// tag::isr_setup_packet[] +/// \tag::isr_setup_packet[] void isr_usbctrl(void) { // USB interrupt handler uint32_t status = usb_hw->ints; @@ -492,7 +492,7 @@ void isr_usbctrl(void) { usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS; usb_handle_setup_packet(); } -// end::isr_setup_packet[] +/// \end::isr_setup_packet[] // Buffer status, one or more buffers have completed if (status & USB_INTS_BUFF_STATUS_BITS) { @@ -569,4 +569,4 @@ int main(void) { } return 0; -} \ No newline at end of file +} From 312dda472618ff87b1f9a94bf6e28227d3db318b Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Sat, 30 Jan 2021 17:16:32 +0000 Subject: [PATCH 02/30] Standardise references to Raspberry Pi Pico SDK (#21) --- CMakeLists.txt | 2 +- README.md | 6 +++--- pico_sdk_import.cmake | 14 ++++++-------- pio/st7789_lcd/st7789_lcd.c | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 82ea832..735cf22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.12) -# Pull in PICO SDK (must be before project) +# Pull in SDK (must be before project) include(pico_sdk_import.cmake) project(pico_examples C CXX ASM) diff --git a/README.md b/README.md index 33ae265..1c88458 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# PICO SDK Examples +# Raspberry Pi Pico SDK Examples ## Getting started @@ -7,9 +7,9 @@ on getting up and running. ### First Examples -App | Description | Link to prebuilt UF2 +App|Description | Link to prebuilt UF2 ---|---|--- -[hello_serial](hello_world/serial) | The obligatory Hello World program for Pico (Output over serial version) | https://rptl.io/pico-hello-serial +[hello_serial](hello_world/serial) | The obligatory Hello World program for Pico (Output over serial version) | [hello_usb](hello_world/usb) | The obligatory Hello World program for Pico (Output over USB version) | https://rptl.io/pico-hello-usb [blink](blink) | Blink an LED on and off. | https://rptl.io/pico-blink diff --git a/pico_sdk_import.cmake b/pico_sdk_import.cmake index f63ee3f..28efe9e 100644 --- a/pico_sdk_import.cmake +++ b/pico_sdk_import.cmake @@ -3,8 +3,6 @@ # This can be dropped into an external project to help locate this SDK # It should be include()ed prior to project() -# todo document - if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") @@ -20,8 +18,8 @@ if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_P message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") endif () -set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the PICO SDK") -set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of PICO SDK from git if not otherwise locatable") +set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") +set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") if (NOT PICO_SDK_PATH) @@ -37,14 +35,14 @@ if (NOT PICO_SDK_PATH) GIT_TAG master ) if (NOT pico_sdk) - message("Downloading PICO SDK") + message("Downloading Raspberry Pi Pico SDK") FetchContent_Populate(pico_sdk) set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) endif () set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) else () message(FATAL_ERROR - "PICO SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." + "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." ) endif () endif () @@ -56,9 +54,9 @@ endif () set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) - message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the PICO SDK") + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") endif () -set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the PICO SDK" FORCE) +set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) include(${PICO_SDK_INIT_CMAKE_FILE}) diff --git a/pio/st7789_lcd/st7789_lcd.c b/pio/st7789_lcd/st7789_lcd.c index f191557..dde9efe 100644 --- a/pio/st7789_lcd/st7789_lcd.c +++ b/pio/st7789_lcd/st7789_lcd.c @@ -102,7 +102,7 @@ int main() { gpio_put(PIN_BL, 1); // Other SDKs: static image on screen, lame, boring - // Pico SDK: spinning image on screen, bold, exciting + // Raspberry Pi Pico SDK: spinning image on screen, bold, exciting // Lane 0 will be u coords (bits 8:1 of addr offset), lane 1 will be v // coords (bits 16:9 of addr offset), and we'll represent coords with From 2cbea72cd33f378caf643c0c7bef7caba3a64660 Mon Sep 17 00:00:00 2001 From: Graham Sanderson Date: Sun, 31 Jan 2021 17:02:04 -0600 Subject: [PATCH 03/30] Add system/unique_board_id (#25) Co-authored-by: Luke Wren --- README.md | 2 +- system/CMakeLists.txt | 1 + system/unique_board_id/CMakeLists.txt | 14 +++++++++++ system/unique_board_id/unique_board_id.c | 32 ++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 system/unique_board_id/CMakeLists.txt create mode 100644 system/unique_board_id/unique_board_id.c diff --git a/README.md b/README.md index 1c88458..d1231a8 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ App|Description ---|--- [hello_double_tap](system/hello_double_tap) | On dev boards with a reset button (but no BOOTSEL), a magic number in RAM can be used to enter the USB bootloader, when the reset button is pressed twice quickly. [narrow_io_write](system/narrow_io_write) | Demonstrate the effects of 8-bit and 16-bit writes on a 32-bit IO register. - +[unique_board_id](system/unique_board_id) | Read the 64 bit unique ID from external flash, which serves as a unique identifier for the board. ### Timer App|Description diff --git a/system/CMakeLists.txt b/system/CMakeLists.txt index b11455b..05bc089 100644 --- a/system/CMakeLists.txt +++ b/system/CMakeLists.txt @@ -2,4 +2,5 @@ if (NOT PICO_NO_HARDWARE) add_subdirectory(double_tap_usb_boot) add_subdirectory(narrow_io_write) add_subdirectory(hello_double_tap) + add_subdirectory(unique_board_id) endif () diff --git a/system/unique_board_id/CMakeLists.txt b/system/unique_board_id/CMakeLists.txt new file mode 100644 index 0000000..1a5b1f9 --- /dev/null +++ b/system/unique_board_id/CMakeLists.txt @@ -0,0 +1,14 @@ +add_executable(unique_board_id + unique_board_id.c + ) + +target_link_libraries(unique_board_id + pico_stdlib + pico_unique_id + ) + +# create map/bin/hex file etc. +pico_add_extra_outputs(unique_board_id) + +# add url via pico_set_program_url +example_auto_set_url(unique_board_id) diff --git a/system/unique_board_id/unique_board_id.c b/system/unique_board_id/unique_board_id.c new file mode 100644 index 0000000..6fb06c7 --- /dev/null +++ b/system/unique_board_id/unique_board_id.c @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "pico/stdlib.h" +#include "pico/unique_id.h" + +// RP2040 does not have a unique on-board ID, but this is a standard feature +// on the NOR flash it boots from. There is a 1:1 association between RP2040 +// and the flash, so this can be used to get a 64 bit globally unique board ID +// for an RP2040-based board, including Pico. +// +// The pico_unique_id library retrieves this unique identifier during boot and +// stores it in memory, where it can be accessed at any time without +// disturbing the flash XIP hardware. + +int main() { + stdio_init_all(); + + pico_unique_board_id_t board_id; + pico_get_unique_board_id(&board_id); + + printf("Unique identifier:"); + for (int i = 0; i < PICO_UNIQUE_BOARD_ID_SIZE_BYTES; ++i) { + printf(" %02x", board_id.id[i]); + } + printf("\n"); +} From 33854562cd08398c4b48bb1ed7fa022c2177076d Mon Sep 17 00:00:00 2001 From: Graham Sanderson Date: Mon, 1 Feb 2021 08:03:14 -0600 Subject: [PATCH 04/30] Remove incorrect inverted dependency on Pioasm which broke Ninja build (#24) --- pio/squarewave/CMakeLists.txt | 1 - pio/ws2812/CMakeLists.txt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pio/squarewave/CMakeLists.txt b/pio/squarewave/CMakeLists.txt index ac86771..fd095e2 100644 --- a/pio/squarewave/CMakeLists.txt +++ b/pio/squarewave/CMakeLists.txt @@ -15,7 +15,6 @@ example_auto_set_url(pio_squarewave) # generate .hex file and .pio.h file for the RP2040 datasheet (to make sure # the datasheet always shows the output of the latest pioasm version) add_custom_target(pio_squarewave_datasheet DEPENDS - Pioasm ${CMAKE_CURRENT_LIST_DIR}/generated/squarewave.hex ${CMAKE_CURRENT_LIST_DIR}/generated/squarewave.pio.h ${CMAKE_CURRENT_LIST_DIR}/generated/squarewave_wrap.pio.h diff --git a/pio/ws2812/CMakeLists.txt b/pio/ws2812/CMakeLists.txt index f8cd57f..c17552d 100644 --- a/pio/ws2812/CMakeLists.txt +++ b/pio/ws2812/CMakeLists.txt @@ -27,7 +27,7 @@ pico_add_extra_outputs(pio_ws2812_parallel) example_auto_set_url(pio_ws2812_parallel) # Additionally generate python and hex pioasm outputs for inclusion in the RP2040 datasheet -add_custom_target(pio_ws2812_datasheet DEPENDS Pioasm ${CMAKE_CURRENT_LIST_DIR}/generated/ws2812.py) +add_custom_target(pio_ws2812_datasheet DEPENDS ${CMAKE_CURRENT_LIST_DIR}/generated/ws2812.py) add_custom_command(OUTPUT ${CMAKE_CURRENT_LIST_DIR}/generated/ws2812.py DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ws2812.pio COMMAND Pioasm -o python ${CMAKE_CURRENT_LIST_DIR}/ws2812.pio ${CMAKE_CURRENT_LIST_DIR}/generated/ws2812.py From 3617ade198cfdfca24c047f02a0d6948c1c8fdbf Mon Sep 17 00:00:00 2001 From: Mohammed Aslam Date: Fri, 5 Feb 2021 21:47:13 +0530 Subject: [PATCH 05/30] Fixed typo (#30) * Fixed typo * Typo, "execellent" -> "excellent" --- usb/device/dev_hid_generic_inout/dev_hid_generic_inout.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usb/device/dev_hid_generic_inout/dev_hid_generic_inout.c b/usb/device/dev_hid_generic_inout/dev_hid_generic_inout.c index 780b50f..c345f5b 100644 --- a/usb/device/dev_hid_generic_inout/dev_hid_generic_inout.c +++ b/usb/device/dev_hid_generic_inout/dev_hid_generic_inout.c @@ -36,8 +36,8 @@ * * There are 2 ways to test the sketch * 1. Using nodejs - * - Install nodejs and nmp to your PC - * - Install execellent node-hid (https://github.com/node-hid/node-hid) by + * - Install nodejs and npm to your PC + * - Install excellent node-hid (https://github.com/node-hid/node-hid) by * $ npm install node-hid * - Run provided hid test script * $ node hid_test.js From c63ef7cba79997e283a1d09b458d171e94838d49 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Thu, 11 Feb 2021 09:09:09 -0800 Subject: [PATCH 06/30] Fix #41 - Remove debug pin per @kilograham (#47) --- pio/ws2812/ws2812_parallel.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/pio/ws2812/ws2812_parallel.c b/pio/ws2812/ws2812_parallel.c index 441e571..5000656 100644 --- a/pio/ws2812/ws2812_parallel.c +++ b/pio/ws2812/ws2812_parallel.c @@ -18,9 +18,6 @@ #define FRAC_BITS 4 #define PIN_TX 0 -CU_REGISTER_DEBUG_PINS(timing) -CU_SELECT_DEBUG_PINS(timing) - // horrible temporary hack to avoid changing pattern code static uint8_t *current_string_out; static bool current_string_4color; @@ -235,7 +232,6 @@ void __isr dma_complete_handler() { // clear IRQ dma_hw->ints0 = DMA_CHANNEL_MASK; // when the dma is complete we start the reset delay timer - DEBUG_PINS_SET(timing, 4); if (reset_delay_alarm_id) cancel_alarm(reset_delay_alarm_id); reset_delay_alarm_id = add_alarm_in_us(400, reset_delay_complete, NULL, true); } @@ -272,13 +268,11 @@ void dma_init(PIO pio, uint sm) { } void output_strings_dma(value_bits_t *bits, uint value_length) { - DEBUG_PINS_SET(timing, 3); for (uint i = 0; i < value_length; i++) { fragment_start[i] = (uintptr_t) bits[i].planes; // MSB first } fragment_start[value_length] = 0; dma_channel_hw_addr(DMA_CB_CHANNEL)->al3_read_addr_trig = (uintptr_t) fragment_start; - DEBUG_PINS_CLR(timing, 3); } @@ -286,9 +280,7 @@ int main() { //set_sys_clock_48(); stdio_init_all(); puts("WS2812 parallel"); -#if PIN_TX != 3 - gpio_debug_pins_init(); -#endif + // todo get free sm PIO pio = pio0; int sm = 0; @@ -309,26 +301,17 @@ int main() { uint current = 0; for (int i = 0; i < 1000; ++i) { int n = 64; - DEBUG_PINS_SET(timing, 1); + current_string_out = string0.data; current_string_4color = false; pattern_table[pat].pat(n, t); current_string_out = string1.data; current_string_4color = true; pattern_table[pat].pat(n, t); - DEBUG_PINS_CLR(timing, 1); - DEBUG_PINS_SET(timing, 2); transform_strings(strings, count_of(strings), colors, n * 4, brightness); - DEBUG_PINS_CLR(timing, 2); - - DEBUG_PINS_SET(timing, 1); dither_values(colors, states[current], states[current ^ 1], n * 4); - DEBUG_PINS_CLR(timing, 1); - sem_acquire_blocking(&reset_delay_complete_sem); - DEBUG_PINS_CLR(timing, 4); - output_strings_dma(states[current], n * 4); current ^= 1; From d9caecb9f456ba34b48aa19427d9ee728c3b016f Mon Sep 17 00:00:00 2001 From: James Hughes Date: Wed, 3 Feb 2021 15:02:59 +0000 Subject: [PATCH 07/30] Add a multicore_runner example that uses queues --- multicore/CMakeLists.txt | 1 + .../multicore_runner_queue/CMakeLists.txt | 13 +++ .../multicore_runner_queue.c | 97 +++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 multicore/multicore_runner_queue/CMakeLists.txt create mode 100644 multicore/multicore_runner_queue/multicore_runner_queue.c diff --git a/multicore/CMakeLists.txt b/multicore/CMakeLists.txt index ea7420d..c19e40b 100644 --- a/multicore/CMakeLists.txt +++ b/multicore/CMakeLists.txt @@ -1,5 +1,6 @@ if (NOT PICO_NO_HARDWARE) add_subdirectory(hello_multicore) add_subdirectory(multicore_runner) + add_subdirectory(multicore_runner_queue) add_subdirectory(multicore_fifo_irqs) endif () \ No newline at end of file diff --git a/multicore/multicore_runner_queue/CMakeLists.txt b/multicore/multicore_runner_queue/CMakeLists.txt new file mode 100644 index 0000000..c35368a --- /dev/null +++ b/multicore/multicore_runner_queue/CMakeLists.txt @@ -0,0 +1,13 @@ +add_executable(multicore_runner_queue + multicore_runner_queue.c + ) + +target_link_libraries(multicore_runner_queue + pico_multicore + pico_stdlib) + +# create map/bin/hex file etc. +pico_add_extra_outputs(multicore_runner_queue) + +# add url via pico_set_program_url +example_auto_set_url(multicore_runner_queue) \ No newline at end of file diff --git a/multicore/multicore_runner_queue/multicore_runner_queue.c b/multicore/multicore_runner_queue/multicore_runner_queue.c new file mode 100644 index 0000000..b0e2ec6 --- /dev/null +++ b/multicore/multicore_runner_queue/multicore_runner_queue.c @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "pico/stdlib.h" +#include "pico/util/queue.h" +#include "pico/multicore.h" + +#define FLAG_VALUE 123 + +typedef struct +{ + void *func; + int32_t data; +} queue_entry_t; + +queue_t call_queue; +queue_t results_queue; + +void core1_entry() { + while (1) { + // Function pointer is passed to us via the queue_entry_t which also + // contains the function parameter. + // We provide an int32_t return value by simply pushing it back on the + // return queue which also indicates the result is ready. + + queue_entry_t entry; + + queue_remove_blocking(&call_queue, &entry); + + int32_t (*func)() = (int32_t(*)())(entry.func); + int32_t result = (*func)(entry.data); + + queue_add_blocking(&results_queue, &result); + } +} + +int32_t factorial(int32_t n) { + int32_t f = 1; + for (int i = 2; i <= n; i++) { + f *= i; + } + return f; +} + +int32_t fibonacci(int32_t n) { + if (n == 0) return 0; + if (n == 1) return 1; + + int n1 = 0, n2 = 1, n3; + + for (int i = 2; i <= n; i++) { + n3 = n1 + n2; + n1 = n2; + n2 = n3; + } + return n3; +} + +#define TEST_NUM 10 + +int main() { + int32_t res; + + stdio_init_all(); + printf("Hello, multicore_runner using queues!\n"); + + // This example dispatches arbitrary functions to run on the second core + // To do this we run a dispatcher on the second core that accepts a function + // pointer and runs it. The data is passed over using the queue library from + // pico_utils + + queue_init(&call_queue, sizeof(queue_entry_t), 2); + queue_init(&results_queue, sizeof(int32_t), 2); + + multicore_launch_core1(core1_entry); + + queue_entry_t entry = {&factorial, TEST_NUM}; + queue_add_blocking(&call_queue, &entry); + + // We could now do a load of stuff on core 0 and get our result later + + queue_remove_blocking(&results_queue, &res); + + printf("Factorial %d is %d\n", TEST_NUM, res); + + // Now try a different function + entry.func = &fibonacci; + queue_add_blocking(&call_queue, &entry); + + queue_remove_blocking(&results_queue, &res); + + printf("Fibonacci %d is %d\n", TEST_NUM, res); +} From e81e0a022a82286a8ae0f73f832e0d6864f9a726 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Fri, 5 Feb 2021 11:25:26 +0000 Subject: [PATCH 08/30] Add pio_clocked_input example --- pio/CMakeLists.txt | 1 + pio/clocked_input/CMakeLists.txt | 16 +++++++ pio/clocked_input/clocked_input.c | 71 +++++++++++++++++++++++++++++ pio/clocked_input/clocked_input.pio | 51 +++++++++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 pio/clocked_input/CMakeLists.txt create mode 100644 pio/clocked_input/clocked_input.c create mode 100644 pio/clocked_input/clocked_input.pio diff --git a/pio/CMakeLists.txt b/pio/CMakeLists.txt index ff56da3..8855161 100644 --- a/pio/CMakeLists.txt +++ b/pio/CMakeLists.txt @@ -1,6 +1,7 @@ if (NOT PICO_NO_HARDWARE) add_subdirectory(addition) add_subdirectory(apa102) + add_subdirectory(clocked_input) add_subdirectory(differential_manchester) add_subdirectory(hello_pio) add_subdirectory(hub75) diff --git a/pio/clocked_input/CMakeLists.txt b/pio/clocked_input/CMakeLists.txt new file mode 100644 index 0000000..cd71408 --- /dev/null +++ b/pio/clocked_input/CMakeLists.txt @@ -0,0 +1,16 @@ +add_executable(pio_clocked_input) + +pico_generate_pio_header(pio_clocked_input ${CMAKE_CURRENT_LIST_DIR}/clocked_input.pio) + +target_sources(pio_clocked_input PRIVATE clocked_input.c) + +target_link_libraries(pio_clocked_input PRIVATE + pico_stdlib + hardware_pio + hardware_spi + ) + +pico_add_extra_outputs(pio_clocked_input) + +# add url via pico_set_program_url +example_auto_set_url(pio_clocked_input) diff --git a/pio/clocked_input/clocked_input.c b/pio/clocked_input/clocked_input.c new file mode 100644 index 0000000..5175b36 --- /dev/null +++ b/pio/clocked_input/clocked_input.c @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "pico/stdlib.h" +#include "hardware/clocks.h" +#include "hardware/pio.h" +#include "hardware/spi.h" +#include "clocked_input.pio.h" + +// Set up a PIO state machine to shift in serial data, sampling with an +// external clock, and push the data to the RX FIFO, 8 bits at a time. +// +// Use one of the hard SPI peripherals to drive data into the SM through a +// pair of external jumper wires, then read back and print out the data from +// the SM to confirm everything worked ok. +// +// On your Pico you need to connect jumper wires to these pins: +// - GPIO 2 -> GPIO 5 (clock output to clock input) +// - GPIO 3 -> GPIO 4 (data output to data input) + +#define SPI_SCK_PIN 2 +#define SPI_TX_PIN 3 +// GPIO 4 for PIO data input, GPIO 5 for clock input: +#define PIO_INPUT_PIN_BASE 4 + +#define BUF_SIZE 8 + +int main() { + stdio_init_all(); + + // Configure the SPI before PIO to avoid driving any glitches into the + // state machine. + spi_init(spi0, 1000 * 1000); + uint actual_freq_hz = spi_set_baudrate(spi0, clock_get_hz(clk_sys) / 6); + printf("SPI running at %u Hz\n", actual_freq_hz); + gpio_set_function(SPI_TX_PIN, GPIO_FUNC_SPI); + gpio_set_function(SPI_SCK_PIN, GPIO_FUNC_SPI); + + // Load the clocked_input program, and configure a free state machine + // to run the program. + PIO pio = pio0; + uint offset = pio_add_program(pio, &clocked_input_program); + uint sm = pio_claim_unused_sm(pio, true); + clocked_input_program_init(pio, sm, offset, PIO_INPUT_PIN_BASE); + + // Make up some random data to send. + static uint8_t txbuf[BUF_SIZE]; + puts("Data to transmit:"); + for (int i = 0; i < BUF_SIZE; ++i) { + txbuf[i] = rand() >> 16; + printf("%02x\n", txbuf[i]); + } + + // The "blocking" write function will send all the data in one go, and not + // return until the full transmission is finished. + spi_write_blocking(spi0, (const uint8_t*)txbuf, BUF_SIZE); + + // The data we just sent should now be present in the state machine's FIFO. + puts("Reading back from RX FIFO:"); + for (int i = 0; i < BUF_SIZE; ++i) { + uint8_t rxdata = pio_sm_get_blocking(pio, sm); + printf("%02x %s\n", rxdata, rxdata == txbuf[i] ? "OK" : "FAIL"); + } + puts("Done."); +} diff --git a/pio/clocked_input/clocked_input.pio b/pio/clocked_input/clocked_input.pio new file mode 100644 index 0000000..51fa54c --- /dev/null +++ b/pio/clocked_input/clocked_input.pio @@ -0,0 +1,51 @@ +; +; Copyright (c) 2021 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program clocked_input + +; Sample bits using an external clock, and push groups of bits into the RX FIFO. +; - IN pin 0 is the data pin +; - IN pin 1 is the clock pin +; - Autopush is enabled, threshold 8 +; +; This program samples data with each rising clock edge (like mode 0 or mode 3 +; SPI). The data is actually sampled one system clock cycle after the rising +; edge is observed, so a clock ratio of at least input_clk < clk_sys / 6 is +; recommended for good sampling alignment. + + wait 0 pin 1 + wait 1 pin 1 + in pins, 1 + +% c-sdk { +static inline void clocked_input_program_init(PIO pio, uint sm, uint offset, uint pin) { + pio_sm_config c = clocked_input_program_get_default_config(offset); + + // Set the IN base pin to the provided `pin` parameter. This is the data + // pin, and the next-numbered GPIO is used as the clock pin. + sm_config_set_in_pins(&c, pin); + // Set the pin directions to input at the PIO + pio_sm_set_consecutive_pindirs(pio, sm, pin, 2, false); + // Connect these GPIOs to this PIO block + pio_gpio_init(pio, pin); + pio_gpio_init(pio, pin + 1); + + // Shifting to left matches the customary MSB-first ordering of SPI. + sm_config_set_in_shift( + &c, + false, // Shift-to-right = false (i.e. shift to left) + true, // Autopush enabled + 8 // Autopush threshold = 8 + ); + + // We only receive, so disable the TX FIFO to make the RX FIFO deeper. + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); + + // Load our configuration, and start the program from the beginning + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +%} From 6724968c8dca4f6f75fe54589002699a9214241d Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Mon, 8 Feb 2021 13:41:02 +0000 Subject: [PATCH 09/30] Fix copyright date, add comment clarifying FIFO behaviour --- pio/clocked_input/clocked_input.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pio/clocked_input/clocked_input.c b/pio/clocked_input/clocked_input.c index 5175b36..acb7497 100644 --- a/pio/clocked_input/clocked_input.c +++ b/pio/clocked_input/clocked_input.c @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -61,7 +61,11 @@ int main() { // return until the full transmission is finished. spi_write_blocking(spi0, (const uint8_t*)txbuf, BUF_SIZE); - // The data we just sent should now be present in the state machine's FIFO. + // The data we just sent should now be present in the state machine's + // FIFO. We only sent 8 bytes, so all the data received by the state + // machine will fit into the FIFO. Generally you want to be continuously + // reading data out as it appears in the FIFO -- either with polling, FIFO + // interrupts, or DMA. puts("Reading back from RX FIFO:"); for (int i = 0; i < BUF_SIZE; ++i) { uint8_t rxdata = pio_sm_get_blocking(pio, sm); From 475a726c0d80fa49a025d7fe7fc9fa2bb554a1d5 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Mon, 8 Feb 2021 13:37:34 +0000 Subject: [PATCH 10/30] Fix logic analyser for non-power-of-2 sample widths, and clean and comment. --- pio/logic_analyser/logic_analyser.c | 45 ++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/pio/logic_analyser/logic_analyser.c b/pio/logic_analyser/logic_analyser.c index faf9809..a0d9db4 100644 --- a/pio/logic_analyser/logic_analyser.c +++ b/pio/logic_analyser/logic_analyser.c @@ -14,10 +14,12 @@ // frequency. #include +#include #include "pico/stdlib.h" #include "hardware/pio.h" #include "hardware/dma.h" +#include "hardware/structs/bus_ctrl.h" // Some logic to analyse: #include "hardware/structs/pwm.h" @@ -26,6 +28,15 @@ const uint CAPTURE_PIN_BASE = 16; const uint CAPTURE_PIN_COUNT = 2; const uint CAPTURE_N_SAMPLES = 96; +static inline uint bits_packed_per_word(uint pin_count) { + // If the number of pins to be sampled divides the shift register size, we + // can use the full SR and FIFO width, and push when the input shift count + // exactly reaches 32. If not, we have to push earlier, so we use the FIFO + // a little less efficiently. + const uint SHIFT_REG_WIDTH = 32; + return SHIFT_REG_WIDTH - (SHIFT_REG_WIDTH % pin_count); +} + void logic_analyser_init(PIO pio, uint sm, uint pin_base, uint pin_count, float div) { // Load a program to capture n pins. This is just a single `in pins, n` // instruction with a wrap. @@ -43,7 +54,10 @@ void logic_analyser_init(PIO pio, uint sm, uint pin_base, uint pin_count, float sm_config_set_in_pins(&c, pin_base); sm_config_set_wrap(&c, offset, offset); sm_config_set_clkdiv(&c, div); - sm_config_set_in_shift(&c, true, true, 32); + // Note that we may push at a < 32 bit threshold if pin_count does not + // divide 32. We are using shift-to-right, so the sample data ends up + // left-justified in the FIFO in this case, with some zeroes at the LSBs. + sm_config_set_in_shift(&c, true, true, bits_packed_per_word(pin_count)); sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); pio_sm_init(pio, sm, offset, &c); } @@ -74,12 +88,17 @@ void print_capture_buf(const uint32_t *buf, uint pin_base, uint pin_count, uint3 // 00: __--__--__--__--__--__-- // 01: ____----____----____---- printf("Capture:\n"); + // Each FIFO record may be only partially filled with bits, depending on + // whether pin_count is a factor of 32. + uint record_size_bits = bits_packed_per_word(pin_count); for (int pin = 0; pin < pin_count; ++pin) { printf("%02d: ", pin + pin_base); for (int sample = 0; sample < n_samples; ++sample) { uint bit_index = pin + sample * pin_count; - bool level = !!(buf[bit_index / 32] & 1u << (bit_index % 32)); - printf(level ? "-" : "_"); + uint word_index = bit_index / record_size_bits; + // Data is left-justified in each FIFO entry, hence the (32 - record_size_bits) offset + uint word_mask = 1u << (bit_index % record_size_bits + 32 - record_size_bits); + printf(buf[word_index] & word_mask ? "-" : "_"); } printf("\n"); } @@ -89,7 +108,19 @@ int main() { stdio_init_all(); printf("PIO logic analyser example\n"); - uint32_t capture_buf[(CAPTURE_PIN_COUNT * CAPTURE_N_SAMPLES + 31) / 32]; + // We're going to capture into a u32 buffer, for best DMA efficiency. Need + // to be careful of rounding in case the number of pins being sampled + // isn't a power of 2. + uint total_sample_bits = CAPTURE_N_SAMPLES * CAPTURE_PIN_COUNT; + total_sample_bits += bits_packed_per_word(CAPTURE_PIN_COUNT) - 1; + uint buf_size_words = total_sample_bits / bits_packed_per_word(CAPTURE_PIN_COUNT); + uint32_t *capture_buf = malloc(buf_size_words * sizeof(uint32_t)); + hard_assert(capture_buf); + + // Grant high bus priority to the DMA, so it can shove the processors out + // of the way. This should only be needed if you are pushing things up to + // >16bits/clk here, i.e. if you need to saturate the bus completely. + bus_ctrl_hw->priority = BUSCTRL_BUS_PRIORITY_DMA_W_BITS | BUSCTRL_BUS_PRIORITY_DMA_R_BITS; PIO pio = pio0; uint sm = 0; @@ -98,9 +129,7 @@ int main() { logic_analyser_init(pio, sm, CAPTURE_PIN_BASE, CAPTURE_PIN_COUNT, 1.f); printf("Arming trigger\n"); - logic_analyser_arm(pio, sm, dma_chan, capture_buf, //; - (CAPTURE_PIN_COUNT * CAPTURE_N_SAMPLES + 31) / 32, - CAPTURE_PIN_BASE, true); + logic_analyser_arm(pio, sm, dma_chan, capture_buf, buf_size_words, CAPTURE_PIN_BASE, true); printf("Starting PWM example\n"); // PWM example: ----------------------------------------------------------- @@ -119,6 +148,8 @@ int main() { pwm_hw->slice[0].csr = PWM_CH0_CSR_EN_BITS; // ------------------------------------------------------------------------ + // The logic analyser should have started capturing as soon as it saw the + // first transition. Wait until the last sample comes in from the DMA. dma_channel_wait_for_finish_blocking(dma_chan); print_capture_buf(capture_buf, CAPTURE_PIN_BASE, CAPTURE_PIN_COUNT, CAPTURE_N_SAMPLES); From 98422e1afc9c74a3f86c0925db38e424820f6264 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Thu, 11 Feb 2021 12:24:19 +0000 Subject: [PATCH 11/30] Fix garbage at start when doing repeated capture with non-po2 sample size --- pio/logic_analyser/logic_analyser.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pio/logic_analyser/logic_analyser.c b/pio/logic_analyser/logic_analyser.c index a0d9db4..d6801d8 100644 --- a/pio/logic_analyser/logic_analyser.c +++ b/pio/logic_analyser/logic_analyser.c @@ -65,7 +65,10 @@ void logic_analyser_init(PIO pio, uint sm, uint pin_base, uint pin_count, float void logic_analyser_arm(PIO pio, uint sm, uint dma_chan, uint32_t *capture_buf, size_t capture_size_words, uint trigger_pin, bool trigger_level) { pio_sm_set_enabled(pio, sm, false); + // Need to clear _input shift counter_, as well as FIFO, because there may be + // partial ISR contents left over from a prevoius run. sm_restart does this. pio_sm_clear_fifos(pio, sm); + pio_sm_restart(pio, sm); dma_channel_config c = dma_channel_get_default_config(dma_chan); channel_config_set_read_increment(&c, false); @@ -73,7 +76,7 @@ void logic_analyser_arm(PIO pio, uint sm, uint dma_chan, uint32_t *capture_buf, channel_config_set_dreq(&c, pio_get_dreq(pio, sm, false)); dma_channel_configure(dma_chan, &c, - capture_buf, // Destinatinon pointer + capture_buf, // Destination pointer &pio->rxf[sm], // Source pointer capture_size_words, // Number of transfers true // Start immediately From cad9225899cab698f5160a567b3b7a2306bb60ed Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Thu, 11 Feb 2021 16:56:53 +0000 Subject: [PATCH 12/30] typo in comment --- pio/logic_analyser/logic_analyser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pio/logic_analyser/logic_analyser.c b/pio/logic_analyser/logic_analyser.c index d6801d8..c3bd573 100644 --- a/pio/logic_analyser/logic_analyser.c +++ b/pio/logic_analyser/logic_analyser.c @@ -66,7 +66,7 @@ void logic_analyser_arm(PIO pio, uint sm, uint dma_chan, uint32_t *capture_buf, uint trigger_pin, bool trigger_level) { pio_sm_set_enabled(pio, sm, false); // Need to clear _input shift counter_, as well as FIFO, because there may be - // partial ISR contents left over from a prevoius run. sm_restart does this. + // partial ISR contents left over from a previous run. sm_restart does this. pio_sm_clear_fifos(pio, sm); pio_sm_restart(pio, sm); From 6cc888c255c781a7a9b5a299f30456219b943074 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Tue, 16 Feb 2021 13:53:27 +0000 Subject: [PATCH 13/30] hello_double_tap: use pico_bootsel_via_double_reset from SDK --- system/CMakeLists.txt | 1 - system/double_tap_usb_boot/CMakeLists.txt | 13 ------- .../double_tap_usb_boot/double_tap_usb_boot.c | 36 ------------------- system/hello_double_tap/CMakeLists.txt | 11 ++++-- system/hello_double_tap/hello_double_tap.c | 10 ++++-- 5 files changed, 16 insertions(+), 55 deletions(-) delete mode 100644 system/double_tap_usb_boot/CMakeLists.txt delete mode 100644 system/double_tap_usb_boot/double_tap_usb_boot.c diff --git a/system/CMakeLists.txt b/system/CMakeLists.txt index 05bc089..514c984 100644 --- a/system/CMakeLists.txt +++ b/system/CMakeLists.txt @@ -1,5 +1,4 @@ if (NOT PICO_NO_HARDWARE) - add_subdirectory(double_tap_usb_boot) add_subdirectory(narrow_io_write) add_subdirectory(hello_double_tap) add_subdirectory(unique_board_id) diff --git a/system/double_tap_usb_boot/CMakeLists.txt b/system/double_tap_usb_boot/CMakeLists.txt deleted file mode 100644 index 2d72a27..0000000 --- a/system/double_tap_usb_boot/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_library(double_tap_usb_boot INTERFACE) - -# inclusion of this library will allow you to double tap reset within 100ms to launch into bootrom USB bootloader -if (PICO_ON_DEVICE) - target_sources(double_tap_usb_boot INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/double_tap_usb_boot.c - ) - - target_link_libraries(double_tap_usb_boot INTERFACE - pico_bootrom - pico_time - ) -endif () \ No newline at end of file diff --git a/system/double_tap_usb_boot/double_tap_usb_boot.c b/system/double_tap_usb_boot/double_tap_usb_boot.c deleted file mode 100644 index 72afe7b..0000000 --- a/system/double_tap_usb_boot/double_tap_usb_boot.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "pico.h" -#include "pico/time.h" -#include "pico/bootrom.h" - -// Allow user override of the LED mask -#ifndef USB_BOOT_LED_ACTIVITY_MASK -#define USB_BOOT_LED_ACTIVITY_MASK 0 -#endif - -// Doesn't make any sense for a RAM only binary -#if !PICO_NO_FLASH -static const uint32_t magic_token[] = { - 0xf01681de, 0xbd729b29, 0xd359be7a, -}; - -static uint32_t __uninitialized_ram(magic_location)[count_of(magic_token)]; - -// run at initialization time -static void __attribute__((constructor)) boot_double_tap_check() { - for (uint i = 0; i < count_of(magic_token); i++) { - if (magic_location[i] != magic_token[i]) { - // Arm for 100 ms then disarm and continue booting - for (i = 0; i < count_of(magic_token); i++) { - magic_location[i] = magic_token[i]; - } - busy_wait_us(100000); - magic_location[0] = 0; - return; - } - } - - magic_location[0] = 0; - reset_usb_boot(USB_BOOT_LED_ACTIVITY_MASK, 0); -} - -#endif \ No newline at end of file diff --git a/system/hello_double_tap/CMakeLists.txt b/system/hello_double_tap/CMakeLists.txt index a4344ae..30a9e12 100644 --- a/system/hello_double_tap/CMakeLists.txt +++ b/system/hello_double_tap/CMakeLists.txt @@ -2,12 +2,19 @@ add_executable(hello_double_tap hello_double_tap.c ) -# Double tap reset into bootrom is injected by linking with the double_tap_usb_boot library +# Double tap reset into bootrom is injected by linking with the +# pico_bootsel_via_double_reset library target_link_libraries(hello_double_tap pico_stdlib - double_tap_usb_boot + pico_bootsel_via_double_reset ) +# Entering the bootloader in this way also lets us specify a GPIO to be used +# as a bootloader activity LED: +target_compile_definitions(hello_double_tap PRIVATE + PICO_BOOTSEL_VIA_DOUBLE_RESET_ACTIVITY_LED=25 + ) + pico_add_extra_outputs(hello_double_tap) # add url via pico_set_program_url diff --git a/system/hello_double_tap/hello_double_tap.c b/system/hello_double_tap/hello_double_tap.c index 6d0ba7f..e64e8ae 100644 --- a/system/hello_double_tap/hello_double_tap.c +++ b/system/hello_double_tap/hello_double_tap.c @@ -6,10 +6,14 @@ #include "pico/stdlib.h" -// This is a regular old LED blinking example, however it is linked with double_tap_usb_boot -// so pressing reset quickly twice, will reset into USB bootloader +// This is a regular old LED blinking example, however it is linked with the +// `pico_bootsel_via_double_reset` library, so resetting the board twice +// quickly will enter the USB bootloader. This is useful for boards which have +// a reset button but no BOOTSEL, as long as you remember to always link the +// `pico_bootsel_via_double_reset` library! + int main() { - const uint LED_PIN = 21; + const uint LED_PIN = PICO_DEFAULT_LED_PIN; gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); while (true) { From fb68d2810e6e947520592d9a2bdb607d1eaace65 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Tue, 16 Feb 2021 14:00:13 +0000 Subject: [PATCH 14/30] Also update readme for pico_bootsel_via_double_reset --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d1231a8..2409848 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ App|Description App|Description ---|--- -[hello_double_tap](system/hello_double_tap) | On dev boards with a reset button (but no BOOTSEL), a magic number in RAM can be used to enter the USB bootloader, when the reset button is pressed twice quickly. +[hello_double_tap](system/hello_double_tap) | An LED blink with the `pico_bootsel_via_double_reset` library linked. This enters the USB bootloader when it detects the system being reset twice in quick succession, which is useful for boards with a reset button but no BOOTSEL button. [narrow_io_write](system/narrow_io_write) | Demonstrate the effects of 8-bit and 16-bit writes on a 32-bit IO register. [unique_board_id](system/unique_board_id) | Read the 64 bit unique ID from external flash, which serves as a unique identifier for the board. ### Timer From e77a4a84d1ab1056cf60845be44cbffc1b929e95 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Thu, 4 Feb 2021 17:46:53 +0000 Subject: [PATCH 15/30] Add example of detaching peripheral clock and varying system clock --- clocks/CMakeLists.txt | 1 + clocks/detached_clk_peri/CMakeLists.txt | 12 +++ clocks/detached_clk_peri/detached_clk_peri.c | 86 ++++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 clocks/detached_clk_peri/CMakeLists.txt create mode 100644 clocks/detached_clk_peri/detached_clk_peri.c diff --git a/clocks/CMakeLists.txt b/clocks/CMakeLists.txt index 927a8c0..69ba68c 100644 --- a/clocks/CMakeLists.txt +++ b/clocks/CMakeLists.txt @@ -1,4 +1,5 @@ if (NOT PICO_NO_HARDWARE) + add_subdirectory(detached_clk_peri) add_subdirectory(hello_48MHz) add_subdirectory(hello_gpout) add_subdirectory(hello_resus) diff --git a/clocks/detached_clk_peri/CMakeLists.txt b/clocks/detached_clk_peri/CMakeLists.txt new file mode 100644 index 0000000..009643e --- /dev/null +++ b/clocks/detached_clk_peri/CMakeLists.txt @@ -0,0 +1,12 @@ +add_executable(clocks_detached_clk_peri + detached_clk_peri.c + ) + +# Pull in our pico_stdlib which pulls in commonly used features +target_link_libraries(clocks_detached_clk_peri pico_stdlib) + +# create map/bin/hex file etc. +pico_add_extra_outputs(clocks_detached_clk_peri) + +# add url via pico_set_program_url +example_auto_set_url(clocks_detached_clk_peri) \ No newline at end of file diff --git a/clocks/detached_clk_peri/detached_clk_peri.c b/clocks/detached_clk_peri/detached_clk_peri.c new file mode 100644 index 0000000..f6e1411 --- /dev/null +++ b/clocks/detached_clk_peri/detached_clk_peri.c @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +// By default, clk_peri (which drives the serial parts of SPI and UART) is +// attached directly to clk_sys, so varies if the system clock is scaled up +// and down. clk_peri has a multiplexer (though no divider) which allows it to +// be attached to other sources. +// +// If set_sys_clock_khz is called (here setting the system clock to 133 MHz), +// this automatically attaches clk_peri to the USB PLL, which by default we run +// at 48 MHz. As long as you call this *before* configuring your UART etc, the +// UART baud rate will then not be affected by subsequent changes to clk_sys. +// +// However, dropping clk_peri to 48 MHz limits the maximum serial frequencies +// that can be attained by UART and particularly SPI. This example shows how +// clk_peri can be attached directly to the system PLL, and the clk_sys +// divider can then be varied to scale the system (CPUs, DMA, bus fabric etc) +// frequency up and down whilst keeping clk_peri at a constant 133 MHz. +// +// The complete list of clock sources available on clk_peri can be found in +// hardware/regs/clocks.h: +// +// Field : CLOCKS_CLK_PERI_CTRL_AUXSRC +// 0x0 -> clk_sys +// 0x1 -> clksrc_pll_sys +// 0x2 -> clksrc_pll_usb +// 0x3 -> rosc_clksrc_ph +// 0x4 -> xosc_clksrc +// 0x5 -> clksrc_gpin0 +// 0x6 -> clksrc_gpin1 + +#include +#include "pico/stdlib.h" +#include "hardware/clocks.h" + +#define PLL_SYS_KHZ (133 * 1000) + +int main() { + // Set the system frequency to 133 MHz. vco_calc.py from the SDK tells us + // this is exactly attainable at the PLL from a 12 MHz crystal: FBDIV = + // 133 (so VCO of 1596 MHz), PD1 = 6, PD2 = 2. This function will set the + // system PLL to 133 MHz and set the clk_sys divisor to 1. + set_sys_clock_khz(PLL_SYS_KHZ, true); + + // The previous line automatically detached clk_peri from clk_sys, and + // attached it to pll_usb, so that clk_peri won't be disturbed by future + // changes to system clock or system PLL. If we need higher clk_peri + // frequencies, we can attach clk_peri directly back to system PLL (no + // divider available) and then use the clk_sys divider to scale clk_sys + // independently of clk_peri. + clock_configure( + clk_peri, + 0, // No glitchless mux + CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, // System PLL on AUX mux + PLL_SYS_KHZ * 1000, // Input frequency + PLL_SYS_KHZ * 1000 // Output (must be same as no divider) + ); + + // The serial clock won't vary from this point onward, so we can configure + // the UART etc. + stdio_init_all(); + + puts("Peripheral clock is attached directly to system PLL."); + puts("We can vary the system clock divisor while printing from the UART:"); + + for (uint div = 1; div <= 10; ++div) { + printf("Setting system clock divisor to %u\n", div); + clock_configure( + clk_sys, + CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX, + CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, + PLL_SYS_KHZ, + PLL_SYS_KHZ / div + ); + printf("Measuring system clock with frequency counter:"); + // Note that the numbering of frequency counter sources is not the + // same as the numbering of clock slice register blocks. (If we passed + // the clk_sys enum here we would actually end up measuring XOSC.) + printf("%u kHz\n", frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_SYS)); + } + return 0; +} + From 86ca3fec6ce317c7af62cd79275543fd86ac867c Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Mon, 22 Feb 2021 22:08:12 +0700 Subject: [PATCH 16/30] change blink to use PICO_DEFAULT_LED_PIN to support other boards (#57) * change blink to use PICO_DEFAULT_LED_PIN to support other boards * also update pio/pwm and picoboard/blinky system/hello_double_tap --- blink/blink.c | 2 +- picoboard/blinky/blinky.c | 2 +- pio/pwm/pwm.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/blink/blink.c b/blink/blink.c index c6367f2..f413d50 100644 --- a/blink/blink.c +++ b/blink/blink.c @@ -7,7 +7,7 @@ #include "pico/stdlib.h" int main() { - const uint LED_PIN = 25; + const uint LED_PIN = PICO_DEFAULT_LED_PIN; gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); while (true) { diff --git a/picoboard/blinky/blinky.c b/picoboard/blinky/blinky.c index f9cafcd..eb2c545 100644 --- a/picoboard/blinky/blinky.c +++ b/picoboard/blinky/blinky.c @@ -8,7 +8,7 @@ #include "pico/stdlib.h" #include "hardware/gpio.h" -const uint LED_PIN = 25; +const uint LED_PIN = PICO_DEFAULT_LED_PIN; const uint DOT_PERIOD_MS = 100; const char *morse_letters[] = { diff --git a/pio/pwm/pwm.c b/pio/pwm/pwm.c index 0eef2e0..f1cc46d 100644 --- a/pio/pwm/pwm.c +++ b/pio/pwm/pwm.c @@ -33,7 +33,7 @@ int main() { uint offset = pio_add_program(pio, &pwm_program); printf("Loaded program at %d\n", offset); - pwm_program_init(pio, sm, offset, 25); + pwm_program_init(pio, sm, offset, PICO_DEFAULT_LED_PIN); pio_pwm_set_period(pio, sm, (1u << 16) - 1); int level = 0; From 396ca36dc1d7de632b79db43f5a54a037f998c97 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Sun, 28 Feb 2021 09:19:52 -0600 Subject: [PATCH 17/30] make pio-blink use correct sys clock value --- pio/pio_blink/blink.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pio/pio_blink/blink.c b/pio/pio_blink/blink.c index e9427ea..4be445c 100644 --- a/pio/pio_blink/blink.c +++ b/pio/pio_blink/blink.c @@ -8,6 +8,7 @@ #include "pico/stdlib.h" #include "hardware/pio.h" +#include "hardware/clocks.h" #include "blink.pio.h" void blink_pin_forever(PIO pio, uint sm, uint offset, uint pin, uint freq); @@ -29,6 +30,6 @@ void blink_pin_forever(PIO pio, uint sm, uint offset, uint pin, uint freq) { blink_program_init(pio, sm, offset, pin); pio_sm_set_enabled(pio, sm, true); - printf("Blinking pin %d at freq %d\n", pin, freq); - pio->txf[sm] = 24000000 / freq; + printf("Blinking pin %d at %d Hz\n", pin, freq); + pio->txf[sm] = clock_get_hz(clk_sys) / 2 * freq; } From 9c7e31b8e700e1137b49aeb643d03d37a58bed93 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Sun, 28 Feb 2021 09:02:37 -0600 Subject: [PATCH 18/30] hello_world: fix build guards to allow host build, and improve missing tinyusb message --- hello_world/CMakeLists.txt | 6 ++---- hello_world/usb/CMakeLists.txt | 28 ++++++++++++++++------------ 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/hello_world/CMakeLists.txt b/hello_world/CMakeLists.txt index ca3f6a5..b1e0a1a 100644 --- a/hello_world/CMakeLists.txt +++ b/hello_world/CMakeLists.txt @@ -1,4 +1,2 @@ -if (NOT PICO_NO_HARDWARE) - add_subdirectory(usb) - add_subdirectory(serial) -endif () +add_subdirectory(serial) +add_subdirectory(usb) diff --git a/hello_world/usb/CMakeLists.txt b/hello_world/usb/CMakeLists.txt index dbe031a..7368c3d 100644 --- a/hello_world/usb/CMakeLists.txt +++ b/hello_world/usb/CMakeLists.txt @@ -1,16 +1,20 @@ -add_executable(hello_usb - hello_usb.c - ) +if (TARGET tinyusb_device) + add_executable(hello_usb + hello_usb.c + ) -# Pull in our pico_stdlib which aggregates commonly used features -target_link_libraries(hello_usb pico_stdlib) + # Pull in our pico_stdlib which aggregates commonly used features + target_link_libraries(hello_usb pico_stdlib) -# enable usb output, disable uart output -pico_enable_stdio_usb(hello_usb 1) -pico_enable_stdio_uart(hello_usb 0) + # enable usb output, disable uart output + pico_enable_stdio_usb(hello_usb 1) + pico_enable_stdio_uart(hello_usb 0) -# create map/bin/hex/uf2 file etc. -pico_add_extra_outputs(hello_usb) + # create map/bin/hex/uf2 file etc. + pico_add_extra_outputs(hello_usb) -# add url via pico_set_program_url -example_auto_set_url(hello_usb) + # add url via pico_set_program_url + example_auto_set_url(hello_usb) +elseif(PICO_ON_DEVICE) + message(WARNING "not building hello_usb because TinyUSB submodule is not initialized in the SDK") +endif() From 82b6dc0576919aafb79ee836ed6e53d02eb12ec7 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Sun, 28 Feb 2021 09:00:36 -0600 Subject: [PATCH 19/30] fixup examples based on default pin #define-s and also support them being undefined --- dma/channel_irq/channel_irq.c | 5 +++- dma/control_blocks/control_blocks.c | 8 ++++-- flash/nuke/nuke.c | 11 +++++++- gpio/dht_sensor/dht.c | 13 +++++++-- i2c/bus_scan/bus_scan.c | 21 +++++++++----- i2c/lcd_1602_i2c/lcd_1602_i2c.c | 23 +++++++++------ i2c/mpu6050_i2c/mpu6050_i2c.c | 43 +++++++++++++++++------------ picoboard/button/button.c | 10 +++++-- pio/hello_pio/hello.c | 4 +++ pwm/led_fade/pwm_led_fade.c | 6 ++++ 10 files changed, 101 insertions(+), 43 deletions(-) diff --git a/dma/channel_irq/channel_irq.c b/dma/channel_irq/channel_irq.c index bbb2ecb..c06c31a 100644 --- a/dma/channel_irq/channel_irq.c +++ b/dma/channel_irq/channel_irq.c @@ -52,6 +52,9 @@ void dma_handler() { } int main() { +#ifndef PICO_DEFAULT_LED_PIN +#warning dma/channel_irq example requires a board with a regular LED +#else // Set up a PIO state machine to serialise our bits uint offset = pio_add_program(pio0, &pio_serialiser_program); pio_serialiser_program_init(pio0, 0, offset, PICO_DEFAULT_LED_PIN, PIO_SERIAL_CLKDIV); @@ -87,5 +90,5 @@ int main() { // time to sit and think about its early retirement -- maybe open a bakery? while (true) tight_loop_contents(); - +#endif } diff --git a/dma/control_blocks/control_blocks.c b/dma/control_blocks/control_blocks.c index cdeacfd..432d4a7 100644 --- a/dma/control_blocks/control_blocks.c +++ b/dma/control_blocks/control_blocks.c @@ -47,6 +47,9 @@ const struct {uint32_t len; const char *data;} control_blocks[] = { }; int main() { +#ifndef uart_default +#warning dma/control_blocks example requires a UART +#else stdio_init_all(); puts("DMA control block example:"); @@ -81,7 +84,7 @@ int main() { c = dma_channel_get_default_config(data_chan); channel_config_set_transfer_data_size(&c, DMA_SIZE_8); - channel_config_set_dreq(&c, DREQ_UART0_TX + 2 * PICO_DEFAULT_UART); + channel_config_set_dreq(&c, DREQ_UART0_TX + 2 * uart_get_index(uart_default)); // Trigger ctrl_chan when data_chan completes channel_config_set_chain_to(&c, ctrl_chan); // Raise the IRQ flag when 0 is written to a trigger register (end of chain): @@ -90,7 +93,7 @@ int main() { dma_channel_configure( data_chan, &c, - &(PICO_DEFAULT_UART ? uart1_hw : uart0_hw)->dr, + &uart_get_hw(uart_default)->dr, NULL, // Initial read address and transfer count are unimportant; 0, // the control channel will reprogram them each time. false // Don't start yet. @@ -108,4 +111,5 @@ int main() { dma_hw->ints0 = 1u << data_chan; puts("DMA finished."); +#endif } diff --git a/flash/nuke/nuke.c b/flash/nuke/nuke.c index d4637b1..4666b9d 100644 --- a/flash/nuke/nuke.c +++ b/flash/nuke/nuke.c @@ -26,12 +26,20 @@ #include "pico/bootrom.h" int main() { - flash_range_erase(0, PICO_FLASH_SIZE_BYTES); + uint flash_size_bytes; +#ifndef PICO_FLASH_SIZE_BYTES +#warning PICO_FLASH_SIZE_BYTES not set, assuming 16M + flash_size_bytes = 16 * 1024 * 1024; +#else + flash_size_bytes = PICO_FLASH_SIZE_BYTES; +#endif + flash_range_erase(0, flash_size_bytes); // Leave an eyecatcher pattern in the first page of flash so picotool can // more easily check the size: static const uint8_t eyecatcher[FLASH_PAGE_SIZE] = "NUKE"; flash_range_program(0, eyecatcher, FLASH_PAGE_SIZE); +#ifdef PICO_DEFAULT_LED_PIN // Flash LED for success gpio_init(PICO_DEFAULT_LED_PIN); gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); @@ -41,6 +49,7 @@ int main() { gpio_put(PICO_DEFAULT_LED_PIN, 0); sleep_ms(100); } +#endif // Pop back up as an MSD drive reset_usb_boot(0, 0); diff --git a/gpio/dht_sensor/dht.c b/gpio/dht_sensor/dht.c index 84a7836..c9ce874 100644 --- a/gpio/dht_sensor/dht.c +++ b/gpio/dht_sensor/dht.c @@ -9,7 +9,10 @@ #include "pico/stdlib.h" #include "hardware/gpio.h" -const uint LED_PIN = PICO_DEFAULT_LED_PIN; +#ifdef PICO_DEFAULT_LED_PIN +#define LED_PIN PICO_DEFAULT_LED_PIN +#endif + const uint DHT_PIN = 15; const uint MAX_TIMINGS = 85; @@ -22,9 +25,11 @@ void read_from_dht(dht_reading *result); int main() { stdio_init_all(); - gpio_init(LED_PIN); gpio_init(DHT_PIN); +#ifdef LED_PIN + gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); +#endif while (1) { dht_reading reading; read_from_dht(&reading); @@ -46,7 +51,9 @@ void read_from_dht(dht_reading *result) { sleep_ms(20); gpio_set_dir(DHT_PIN, GPIO_IN); +#ifdef LED_PIN gpio_put(LED_PIN, 1); +#endif for (uint i = 0; i < MAX_TIMINGS; i++) { uint count = 0; while (gpio_get(DHT_PIN) == last) { @@ -63,7 +70,9 @@ void read_from_dht(dht_reading *result) { j++; } } +#ifdef LED_PIN gpio_put(LED_PIN, 0); +#endif if ((j >= 40) && (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF))) { result->humidity = (float) ((data[0] << 8) + data[1]) / 10; diff --git a/i2c/bus_scan/bus_scan.c b/i2c/bus_scan/bus_scan.c index 326ca2d..e0c8b5e 100644 --- a/i2c/bus_scan/bus_scan.c +++ b/i2c/bus_scan/bus_scan.c @@ -22,6 +22,7 @@ #include #include "pico/stdlib.h" +#include "pico/binary_info.h" #include "hardware/i2c.h" // I2C reserves some addresses for special purposes. We exclude these from the scan. @@ -33,13 +34,18 @@ bool reserved_addr(uint8_t addr) { int main() { // Enable UART so we can print status output stdio_init_all(); - - // This example will use I2C0 on GPIO4 (SDA) and GPIO5 (SCL) - i2c_init(i2c0, 100 * 1000); - gpio_set_function(4, GPIO_FUNC_I2C); - gpio_set_function(5, GPIO_FUNC_I2C); - gpio_pull_up(4); - gpio_pull_up(5); +#if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN) +#warning i2c/bus_scane example requires a board with I2C pins + puts("Default I2C pins were not defined"); +#else + // This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico) + i2c_init(i2c_default, 100 * 1000); + gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C); + gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C); + gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN); + gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN); + // Make the I2C pins available to picotool + bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C)); printf("\nI2C Bus Scan\n"); printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n"); @@ -67,4 +73,5 @@ int main() { } printf("Done.\n"); return 0; +#endif } diff --git a/i2c/lcd_1602_i2c/lcd_1602_i2c.c b/i2c/lcd_1602_i2c/lcd_1602_i2c.c index 268d6c4..44ca9d8 100644 --- a/i2c/lcd_1602_i2c/lcd_1602_i2c.c +++ b/i2c/lcd_1602_i2c/lcd_1602_i2c.c @@ -58,7 +58,6 @@ const int LCD_BACKLIGHT = 0x08; const int LCD_ENABLE_BIT = 0x04; -#define I2C_PORT i2c0 // By default these LCD display drivers are on bus address 0x27 static int addr = 0x27; @@ -71,7 +70,9 @@ static int addr = 0x27; /* Quick helper function for single byte transfers */ void i2c_write_byte(uint8_t val) { - i2c_write_blocking(I2C_PORT, addr, &val, 1, false); +#ifdef i2c_default + i2c_write_blocking(i2c_default, addr, &val, 1, false); +#endif } void lcd_toggle_enable(uint8_t val) { @@ -129,14 +130,17 @@ void lcd_init() { } int main() { - // This example will use I2C0 on GPIO4 (SDA) and GPIO5 (SCL) - i2c_init(I2C_PORT, 100 * 1000); - gpio_set_function(4, GPIO_FUNC_I2C); - gpio_set_function(5, GPIO_FUNC_I2C); - gpio_pull_up(4); - gpio_pull_up(5); +#if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN) + #warning i2c/bus_scane example requires a board with I2C pins +#else + // This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico) + i2c_init(i2c_default, 100 * 1000); + gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C); + gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C); + gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN); + gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN); // Make the I2C pins available to picotool - bi_decl( bi_2pins_with_func(4, 5, GPIO_FUNC_I2C)); + bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C)); lcd_init(); @@ -161,4 +165,5 @@ int main() { } return 0; +#endif } diff --git a/i2c/mpu6050_i2c/mpu6050_i2c.c b/i2c/mpu6050_i2c/mpu6050_i2c.c index f47a0a1..5a2953c 100644 --- a/i2c/mpu6050_i2c/mpu6050_i2c.c +++ b/i2c/mpu6050_i2c/mpu6050_i2c.c @@ -7,6 +7,7 @@ #include #include #include "pico/stdlib.h" +#include "pico/binary_info.h" #include "hardware/i2c.h" /* Example code to talk to a MPU6050 MEMS accelerometer and gyroscope @@ -23,8 +24,8 @@ Connections on Raspberry Pi Pico board, other boards may vary. - GPIO 4 (pin 6)-> SDA on MPU6050 board - GPIO 5 (pin 7)-> SCL on MPU6050 board + GPIO PICO_DEFAULT_I2C_SDA_PIN (On Pico this is 4 (pin 6)) -> SDA on MPU6050 board + GPIO PICO_DEFAULT_I2C_SCK_PIN (On Pico this is 5 (pin 7)) -> SCL on MPU6050 board 3.3v (pin 36) -> VCC on MPU6050 board GND (pin 38) -> GND on MPU6050 board */ @@ -32,13 +33,12 @@ // By default these devices are on bus address 0x68 static int addr = 0x68; -#define I2C_PORT i2c0 - +#ifdef i2c_default static void mpu6050_reset() { // Two byte reset. First byte register, second byte data // There are a load more options to set up the device in different ways that could be added here uint8_t buf[] = {0x6B, 0x00}; - i2c_write_blocking(I2C_PORT, addr, buf, 2, false); + i2c_write_blocking(i2c_default, addr, buf, 2, false); } static void mpu6050_read_raw(int16_t accel[3], int16_t gyro[3], int16_t *temp) { @@ -50,8 +50,8 @@ static void mpu6050_read_raw(int16_t accel[3], int16_t gyro[3], int16_t *temp) { // Start reading acceleration registers from register 0x3B for 6 bytes uint8_t val = 0x3B; - i2c_write_blocking(I2C_PORT, addr, &val, 1, true); // true to keep master control of bus - i2c_read_blocking(I2C_PORT, addr, buffer, 6, false); + i2c_write_blocking(i2c_default, addr, &val, 1, true); // true to keep master control of bus + i2c_read_blocking(i2c_default, addr, buffer, 6, false); for (int i = 0; i < 3; i++) { accel[i] = (buffer[i * 2] << 8 | buffer[(i * 2) + 1]); @@ -60,8 +60,8 @@ static void mpu6050_read_raw(int16_t accel[3], int16_t gyro[3], int16_t *temp) { // Now gyro data from reg 0x43 for 6 bytes // The register is auto incrementing on each read val = 0x43; - i2c_write_blocking(I2C_PORT, addr, &val, 1, true); - i2c_read_blocking(I2C_PORT, addr, buffer, 6, false); // False - finished with bus + i2c_write_blocking(i2c_default, addr, &val, 1, true); + i2c_read_blocking(i2c_default, addr, buffer, 6, false); // False - finished with bus for (int i = 0; i < 3; i++) { gyro[i] = (buffer[i * 2] << 8 | buffer[(i * 2) + 1]);; @@ -70,23 +70,29 @@ static void mpu6050_read_raw(int16_t accel[3], int16_t gyro[3], int16_t *temp) { // Now temperature from reg 0x41 for 2 bytes // The register is auto incrementing on each read val = 0x41; - i2c_write_blocking(I2C_PORT, addr, &val, 1, true); - i2c_read_blocking(I2C_PORT, addr, buffer, 2, false); // False - finished with bus + i2c_write_blocking(i2c_default, addr, &val, 1, true); + i2c_read_blocking(i2c_default, addr, buffer, 2, false); // False - finished with bus *temp = buffer[0] << 8 | buffer[1]; } +#endif int main() { stdio_init_all(); - +#if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN) + #warning i2c/bus_scane example requires a board with I2C pins + puts("Default I2C pins were not defined'); +#else printf("Hello, MPU6050! Reading raw data from registers...\n"); - // This example will use I2C0 on GPIO4 (SDA) and GPIO5 (SCL) running at 400kHz. - i2c_init(I2C_PORT, 400 * 1000); - gpio_set_function(4, GPIO_FUNC_I2C); - gpio_set_function(5, GPIO_FUNC_I2C); - gpio_pull_up(4); - gpio_pull_up(5); + // This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico) + i2c_init(i2c_default, 400 * 1000); + gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C); + gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C); + gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN); + gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN); + // Make the I2C pins available to picotool + bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C)); mpu6050_reset(); @@ -106,5 +112,6 @@ int main() { sleep_ms(100); } +#endif return 0; } diff --git a/picoboard/button/button.c b/picoboard/button/button.c index dfa8a05..b113533 100644 --- a/picoboard/button/button.c +++ b/picoboard/button/button.c @@ -11,7 +11,7 @@ #include "hardware/structs/ioqspi.h" #include "hardware/structs/sio.h" -// This example blinks the Picoboard LED when the BOOTSEL button is pressed. +// This example blinks the Pico LED when the BOOTSEL button is pressed. // // Picoboard has a button attached to the flash CS pin, which the bootrom // checks, and jumps straight to the USB bootcode if the button is pressed @@ -53,10 +53,14 @@ bool __no_inline_not_in_flash_func(get_bootsel_button)() { } int main() { +#ifndef PICO_DEFAULT_LED_PIN +#warning picobooard/button example requires a board with a regular LED +#else gpio_init(PICO_DEFAULT_LED_PIN); gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); while (true) { - gpio_put(PICO_DEFAULT_LED_PIN, get_bootsel_button()); + gpio_put(PICO_DEFAULT_LED_PIN, get_bootsel_button() ^ PICO_DEFAULT_LED_PIN_INVERTED); sleep_ms(10); } -} \ No newline at end of file +#endif +} diff --git a/pio/hello_pio/hello.c b/pio/hello_pio/hello.c index 456ac56..2af0d05 100644 --- a/pio/hello_pio/hello.c +++ b/pio/hello_pio/hello.c @@ -10,6 +10,9 @@ #include "hello.pio.h" int main() { +#ifndef PICO_DEFAULT_LED_PIN +#warning pio/hello_pio example requires a board with a regular LED +#else // Choose which PIO instance to use (there are two instances) PIO pio = pio0; @@ -35,4 +38,5 @@ int main() { pio_sm_put_blocking(pio, sm, 0); sleep_ms(500); } +#endif } diff --git a/pwm/led_fade/pwm_led_fade.c b/pwm/led_fade/pwm_led_fade.c index 522ab92..1b35827 100644 --- a/pwm/led_fade/pwm_led_fade.c +++ b/pwm/led_fade/pwm_led_fade.c @@ -13,6 +13,7 @@ #include "hardware/irq.h" #include "hardware/pwm.h" +#ifdef PICO_DEFAULT_LED_PIN void on_pwm_wrap() { static int fade = 0; static bool going_up = true; @@ -36,8 +37,12 @@ void on_pwm_wrap() { // Note this range matches with the wrap value pwm_set_gpio_level(PICO_DEFAULT_LED_PIN, fade * fade); } +#endif int main() { +#ifndef PICO_DEFAULT_LED_PIN +#warning pwm/led_fade example requires a board with a regular LED +#else // Tell the LED pin that the PWM is in charge of its value. gpio_set_function(PICO_DEFAULT_LED_PIN, GPIO_FUNC_PWM); // Figure out which slice we just connected to the LED pin @@ -62,4 +67,5 @@ int main() { // can twiddle our thumbs while (1) tight_loop_contents(); +#endif } From f8933bd5d265a084ae7bfa868aa4c796e0174383 Mon Sep 17 00:00:00 2001 From: "graham.sanderson@raspberrypi.com" Date: Mon, 1 Mar 2021 09:30:55 -0600 Subject: [PATCH 20/30] fixup typos --- i2c/bus_scan/bus_scan.c | 2 +- i2c/lcd_1602_i2c/lcd_1602_i2c.c | 2 +- i2c/mpu6050_i2c/mpu6050_i2c.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/i2c/bus_scan/bus_scan.c b/i2c/bus_scan/bus_scan.c index e0c8b5e..774594e 100644 --- a/i2c/bus_scan/bus_scan.c +++ b/i2c/bus_scan/bus_scan.c @@ -35,7 +35,7 @@ int main() { // Enable UART so we can print status output stdio_init_all(); #if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN) -#warning i2c/bus_scane example requires a board with I2C pins +#warning i2c/bus_scan example requires a board with I2C pins puts("Default I2C pins were not defined"); #else // This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico) diff --git a/i2c/lcd_1602_i2c/lcd_1602_i2c.c b/i2c/lcd_1602_i2c/lcd_1602_i2c.c index 44ca9d8..4cea8ce 100644 --- a/i2c/lcd_1602_i2c/lcd_1602_i2c.c +++ b/i2c/lcd_1602_i2c/lcd_1602_i2c.c @@ -131,7 +131,7 @@ void lcd_init() { int main() { #if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN) - #warning i2c/bus_scane example requires a board with I2C pins + #warning i2c/bus_scan example requires a board with I2C pins #else // This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico) i2c_init(i2c_default, 100 * 1000); diff --git a/i2c/mpu6050_i2c/mpu6050_i2c.c b/i2c/mpu6050_i2c/mpu6050_i2c.c index 5a2953c..8114923 100644 --- a/i2c/mpu6050_i2c/mpu6050_i2c.c +++ b/i2c/mpu6050_i2c/mpu6050_i2c.c @@ -80,7 +80,7 @@ static void mpu6050_read_raw(int16_t accel[3], int16_t gyro[3], int16_t *temp) { int main() { stdio_init_all(); #if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN) - #warning i2c/bus_scane example requires a board with I2C pins + #warning i2c/bus_scan example requires a board with I2C pins puts("Default I2C pins were not defined'); #else printf("Hello, MPU6050! Reading raw data from registers...\n"); From a1fe323927fddd0687199873ee49ccce78c5ea2f Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Mon, 1 Mar 2021 15:55:40 +0000 Subject: [PATCH 21/30] Typo mismatched closing-quote --- i2c/mpu6050_i2c/mpu6050_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i2c/mpu6050_i2c/mpu6050_i2c.c b/i2c/mpu6050_i2c/mpu6050_i2c.c index 8114923..de1b39e 100644 --- a/i2c/mpu6050_i2c/mpu6050_i2c.c +++ b/i2c/mpu6050_i2c/mpu6050_i2c.c @@ -81,7 +81,7 @@ int main() { stdio_init_all(); #if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN) #warning i2c/bus_scan example requires a board with I2C pins - puts("Default I2C pins were not defined'); + puts("Default I2C pins were not defined"); #else printf("Hello, MPU6050! Reading raw data from registers...\n"); From 68a18659dace7c86418aac2e3fcc3d7416641374 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Mon, 1 Mar 2021 10:13:13 -0600 Subject: [PATCH 22/30] generated python is changed --- pio/ws2812/generated/ws2812.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pio/ws2812/generated/ws2812.py b/pio/ws2812/generated/ws2812.py index e05d82b..57b3e94 100644 --- a/pio/ws2812/generated/ws2812.py +++ b/pio/ws2812/generated/ws2812.py @@ -37,7 +37,7 @@ ws2812_parallel_T3 = 3 def ws2812_parallel(): wrap_target() out(x, 32) # 0 - mov(pins, not null) [1] # 1 + mov(pins, invert(null)) [1] # 1 mov(pins, x) [4] # 2 mov(pins, null) [1] # 3 wrap() From df23bb6dede505698579740fb72bcbe3ac23e94f Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Mon, 1 Mar 2021 16:11:42 +0000 Subject: [PATCH 23/30] Fix example-names mentioned in warning messages --- i2c/lcd_1602_i2c/lcd_1602_i2c.c | 2 +- i2c/mpu6050_i2c/mpu6050_i2c.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/i2c/lcd_1602_i2c/lcd_1602_i2c.c b/i2c/lcd_1602_i2c/lcd_1602_i2c.c index 4cea8ce..c23a77f 100644 --- a/i2c/lcd_1602_i2c/lcd_1602_i2c.c +++ b/i2c/lcd_1602_i2c/lcd_1602_i2c.c @@ -131,7 +131,7 @@ void lcd_init() { int main() { #if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN) - #warning i2c/bus_scan example requires a board with I2C pins + #warning i2c/lcd_1602_i2c example requires a board with I2C pins #else // This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico) i2c_init(i2c_default, 100 * 1000); diff --git a/i2c/mpu6050_i2c/mpu6050_i2c.c b/i2c/mpu6050_i2c/mpu6050_i2c.c index de1b39e..9bb8815 100644 --- a/i2c/mpu6050_i2c/mpu6050_i2c.c +++ b/i2c/mpu6050_i2c/mpu6050_i2c.c @@ -80,7 +80,7 @@ static void mpu6050_read_raw(int16_t accel[3], int16_t gyro[3], int16_t *temp) { int main() { stdio_init_all(); #if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN) - #warning i2c/bus_scan example requires a board with I2C pins + #warning i2c/mpu6050_i2c example requires a board with I2C pins puts("Default I2C pins were not defined"); #else printf("Hello, MPU6050! Reading raw data from registers...\n"); From 188f5be9cf6d9d7e78584f8cd40fc377e48bb6b4 Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Thu, 4 Mar 2021 11:53:48 +0000 Subject: [PATCH 24/30] Update some of the SPI examples to use PICO_DEFAULT_SPI and binary_info --- pio/spi/spi_flash.c | 30 ++++++++++++++---------- spi/bme280_spi/bme280_spi.c | 44 +++++++++++++++++++++-------------- spi/mpu9250_spi/mpu9250_spi.c | 5 ++++ spi/spi_dma/spi_dma.c | 37 +++++++++++++++-------------- spi/spi_flash/spi_flash.c | 41 ++++++++++++++++++-------------- 5 files changed, 92 insertions(+), 65 deletions(-) diff --git a/pio/spi/spi_flash.c b/pio/spi/spi_flash.c index bc9192e..1f2fdec 100644 --- a/pio/spi/spi_flash.c +++ b/pio/spi/spi_flash.c @@ -7,16 +7,12 @@ #include #include "pico/stdlib.h" +#include "pico/binary_info.h" #include "pio_spi.h" // This example uses PIO to erase, program and read back a SPI serial flash // memory. -#define PIN_MISO 16 -#define PIN_MOSI 17 -#define PIN_SCK 18 -#define PIN_CS 19 - // ---------------------------------------------------------------------------- // Generic serial flash code @@ -102,17 +98,24 @@ void printbuf(const uint8_t buf[FLASH_PAGE_SIZE]) { int main() { stdio_init_all(); +#if !defined(PICO_DEFAULT_SPI_SCK_PIN) || !defined(PICO_DEFAULT_SPI_TX_PIN) || !defined(PICO_DEFAULT_SPI_RX_PIN) || !defined(PICO_DEFAULT_SPI_CSN_PIN) +#warning pio/spi/spi_flash example requires a board with SPI pins + puts("Default SPI pins were not defined"); +#else + puts("PIO SPI Example"); pio_spi_inst_t spi = { .pio = pio0, .sm = 0, - .cs_pin = PIN_CS + .cs_pin = PICO_DEFAULT_SPI_CSN_PIN }; - gpio_init(PIN_CS); - gpio_put(PIN_CS, 1); - gpio_set_dir(PIN_CS, GPIO_OUT); + gpio_init(PICO_DEFAULT_SPI_CSN_PIN); + gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 1); + gpio_set_dir(PICO_DEFAULT_SPI_CSN_PIN, GPIO_OUT); + // Make the CS pin available to picotool + bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "CS")); uint offset = pio_add_program(spi.pio, &spi_cpha0_program); printf("Loaded program at %d\n", offset); @@ -122,10 +125,12 @@ int main() { 31.25f, // 1 MHz @ 125 clk_sys false, // CPHA = 0 false, // CPOL = 0 - PIN_SCK, - PIN_MOSI, - PIN_MISO + PICO_DEFAULT_SPI_SCK_PIN, + PICO_DEFAULT_SPI_TX_PIN, + PICO_DEFAULT_SPI_RX_PIN ); + // Make the SPI pins available to picotool + bi_decl(bi_3pins_with_func(PICO_DEFAULT_SPI_RX_PIN, PICO_DEFAULT_SPI_TX_PIN, PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_PIO0)); uint8_t page_buf[FLASH_PAGE_SIZE]; @@ -152,4 +157,5 @@ int main() { printbuf(page_buf); return 0; +#endif } diff --git a/spi/bme280_spi/bme280_spi.c b/spi/bme280_spi/bme280_spi.c index 9eff1c2..69ad74a 100644 --- a/spi/bme280_spi/bme280_spi.c +++ b/spi/bme280_spi/bme280_spi.c @@ -7,6 +7,7 @@ #include #include #include "pico/stdlib.h" +#include "pico/binary_info.h" #include "hardware/spi.h" /* Example code to talk to a bme280 humidity/temperature/pressure sensor. @@ -36,12 +37,6 @@ https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme280-ds002.pdf */ -#define PIN_MISO 16 -#define PIN_CS 17 -#define PIN_SCK 18 -#define PIN_MOSI 19 - -#define SPI_PORT spi0 #define READ_BIT 0x80 int32_t t_fine; @@ -110,24 +105,27 @@ uint32_t compensate_humidity(int32_t adc_H) { return (uint32_t) (v_x1_u32r >> 12); } +#ifdef PICO_DEFAULT_SPI_CSN_PIN static inline void cs_select() { asm volatile("nop \n nop \n nop"); - gpio_put(PIN_CS, 0); // Active low + gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 0); // Active low asm volatile("nop \n nop \n nop"); } static inline void cs_deselect() { asm volatile("nop \n nop \n nop"); - gpio_put(PIN_CS, 1); + gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 1); asm volatile("nop \n nop \n nop"); } +#endif +#if defined(spi_default) && defined(PICO_DEFAULT_SPI_CSN_PIN) static void write_register(uint8_t reg, uint8_t data) { uint8_t buf[2]; buf[0] = reg & 0x7f; // remove read bit as this is a write buf[1] = data; cs_select(); - spi_write_blocking(SPI_PORT, buf, 2); + spi_write_blocking(spi_default, buf, 2); cs_deselect(); sleep_ms(10); } @@ -138,9 +136,9 @@ static void read_registers(uint8_t reg, uint8_t *buf, uint16_t len) { // so we don't need to keep sending the register we want, just the first. reg |= READ_BIT; cs_select(); - spi_write_blocking(SPI_PORT, ®, 1); + spi_write_blocking(spi_default, ®, 1); sleep_ms(10); - spi_read_blocking(SPI_PORT, 0, buf, len); + spi_read_blocking(spi_default, 0, buf, len); cs_deselect(); sleep_ms(10); } @@ -184,22 +182,31 @@ static void bme280_read_raw(int32_t *humidity, int32_t *pressure, int32_t *tempe *temperature = ((uint32_t) buffer[3] << 12) | ((uint32_t) buffer[4] << 4) | (buffer[5] >> 4); *humidity = (uint32_t) buffer[6] << 8 | buffer[7]; } +#endif int main() { stdio_init_all(); +#if !defined(spi_default) || !defined(PICO_DEFAULT_SPI_SCK_PIN) || !defined(PICO_DEFAULT_SPI_TX_PIN) || !defined(PICO_DEFAULT_SPI_RX_PIN) || !defined(PICO_DEFAULT_SPI_CSN_PIN) +#warning spi/bme280_spi example requires a board with SPI pins + puts("Default SPI pins were not defined"); +#else printf("Hello, bme280! Reading raw data from registers via SPI...\n"); // This example will use SPI0 at 0.5MHz. - spi_init(SPI_PORT, 500 * 1000); - gpio_set_function(PIN_MISO, GPIO_FUNC_SPI); - gpio_set_function(PIN_SCK, GPIO_FUNC_SPI); - gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI); + spi_init(spi_default, 500 * 1000); + gpio_set_function(PICO_DEFAULT_SPI_RX_PIN, GPIO_FUNC_SPI); + gpio_set_function(PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_SPI); + gpio_set_function(PICO_DEFAULT_SPI_TX_PIN, GPIO_FUNC_SPI); + // Make the SPI pins available to picotool + bi_decl(bi_3pins_with_func(PICO_DEFAULT_SPI_RX_PIN, PICO_DEFAULT_SPI_TX_PIN, PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_SPI)); // Chip select is active-low, so we'll initialise it to a driven-high state - gpio_init(PIN_CS); - gpio_set_dir(PIN_CS, GPIO_OUT); - gpio_put(PIN_CS, 1); + gpio_init(PICO_DEFAULT_SPI_CSN_PIN); + gpio_set_dir(PICO_DEFAULT_SPI_CSN_PIN, GPIO_OUT); + gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 1); + // Make the CS pin available to picotool + bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "CS")); // See if SPI is working - interrograte the device for its I2C ID number, should be 0x60 uint8_t id; @@ -230,4 +237,5 @@ int main() { } return 0; +#endif } diff --git a/spi/mpu9250_spi/mpu9250_spi.c b/spi/mpu9250_spi/mpu9250_spi.c index 97e221c..5714cb7 100644 --- a/spi/mpu9250_spi/mpu9250_spi.c +++ b/spi/mpu9250_spi/mpu9250_spi.c @@ -7,6 +7,7 @@ #include #include #include "pico/stdlib.h" +#include "pico/binary_info.h" #include "hardware/spi.h" /* Example code to talk to a MPU9250 MEMS accelerometer and gyroscope. @@ -117,11 +118,15 @@ int main() { gpio_set_function(PIN_MISO, GPIO_FUNC_SPI); gpio_set_function(PIN_SCK, GPIO_FUNC_SPI); gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI); + // Make the SPI pins available to picotool + bi_decl(bi_3pins_with_func(PIN_MISO, PIN_MOSI, PIN_SCK, GPIO_FUNC_SPI)); // Chip select is active-low, so we'll initialise it to a driven-high state gpio_init(PIN_CS); gpio_set_dir(PIN_CS, GPIO_OUT); gpio_put(PIN_CS, 1); + // Make the CS pin available to picotool + bi_decl(bi_1pin_with_name(PIN_CS, "CS")); mpu9250_reset(); diff --git a/spi/spi_dma/spi_dma.c b/spi/spi_dma/spi_dma.c index 2ee2af3..1354b34 100644 --- a/spi/spi_dma/spi_dma.c +++ b/spi/spi_dma/spi_dma.c @@ -9,37 +9,39 @@ #include #include #include "pico/stdlib.h" +#include "pico/binary_info.h" #include "hardware/spi.h" #include "hardware/dma.h" -#define PIN_MISO 16 -#define PIN_CS 17 -#define PIN_SCK 18 -#define PIN_MOSI 19 - -#define SPI_INST spi0 - #define TEST_SIZE 1024 int main() { // Enable UART so we can print status output stdio_init_all(); +#if !defined(spi_default) || !defined(PICO_DEFAULT_SPI_SCK_PIN) || !defined(PICO_DEFAULT_SPI_TX_PIN) || !defined(PICO_DEFAULT_SPI_RX_PIN) || !defined(PICO_DEFAULT_SPI_CSN_PIN) +#warning spi/spi_dma example requires a board with SPI pins + puts("Default SPI pins were not defined"); +#else printf("SPI DMA example\n"); // Enable SPI at 1 MHz and connect to GPIOs - spi_init(SPI_INST, 1000 * 1000); - gpio_set_function(PIN_MISO, GPIO_FUNC_SPI); - gpio_init(PIN_CS); - gpio_set_function(PIN_SCK, GPIO_FUNC_SPI); - gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI); + spi_init(spi_default, 1000 * 1000); + gpio_set_function(PICO_DEFAULT_SPI_RX_PIN, GPIO_FUNC_SPI); + gpio_init(PICO_DEFAULT_SPI_CSN_PIN); + gpio_set_function(PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_SPI); + gpio_set_function(PICO_DEFAULT_SPI_TX_PIN, GPIO_FUNC_SPI); + // Make the SPI pins available to picotool + bi_decl(bi_3pins_with_func(PICO_DEFAULT_SPI_RX_PIN, PICO_DEFAULT_SPI_TX_PIN, PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_SPI)); + // Make the CS pin available to picotool + bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "CS")); // Grab some unused dma channels const uint dma_tx = dma_claim_unused_channel(true); const uint dma_rx = dma_claim_unused_channel(true); // Force loopback for testing (I don't have an SPI device handy) - hw_set_bits(&spi_get_hw(SPI_INST)->cr1, SPI_SSPCR1_LBM_BITS); + hw_set_bits(&spi_get_hw(spi_default)->cr1, SPI_SSPCR1_LBM_BITS); static uint8_t txbuf[TEST_SIZE]; static uint8_t rxbuf[TEST_SIZE]; @@ -54,9 +56,9 @@ int main() { printf("Configure TX DMA\n"); dma_channel_config c = dma_channel_get_default_config(dma_tx); channel_config_set_transfer_data_size(&c, DMA_SIZE_8); - channel_config_set_dreq(&c, spi_get_index(SPI_INST) ? DREQ_SPI1_TX : DREQ_SPI0_TX); + channel_config_set_dreq(&c, spi_get_index(spi_default) ? DREQ_SPI1_TX : DREQ_SPI0_TX); dma_channel_configure(dma_tx, &c, - &spi_get_hw(SPI_INST)->dr, // write address + &spi_get_hw(spi_default)->dr, // write address txbuf, // read address TEST_SIZE, // element count (each element is of size transfer_data_size) false); // don't start yet @@ -68,12 +70,12 @@ int main() { // address to increment (so data is written throughout the buffer) c = dma_channel_get_default_config(dma_rx); channel_config_set_transfer_data_size(&c, DMA_SIZE_8); - channel_config_set_dreq(&c, spi_get_index(SPI_INST) ? DREQ_SPI1_RX : DREQ_SPI0_RX); + channel_config_set_dreq(&c, spi_get_index(spi_default) ? DREQ_SPI1_RX : DREQ_SPI0_RX); channel_config_set_read_increment(&c, false); channel_config_set_write_increment(&c, true); dma_channel_configure(dma_rx, &c, rxbuf, // write address - &spi_get_hw(SPI_INST)->dr, // read address + &spi_get_hw(spi_default)->dr, // read address TEST_SIZE, // element count (each element is of size transfer_data_size) false); // don't start yet @@ -100,4 +102,5 @@ int main() { dma_channel_unclaim(dma_tx); dma_channel_unclaim(dma_rx); return 0; +#endif } diff --git a/spi/spi_flash/spi_flash.c b/spi/spi_flash/spi_flash.c index e3df7e8..4e214f5 100644 --- a/spi/spi_flash/spi_flash.c +++ b/spi/spi_flash/spi_flash.c @@ -8,6 +8,7 @@ #include #include "pico/stdlib.h" +#include "pico/binary_info.h" #include "hardware/spi.h" #define FLASH_PAGE_SIZE 256 @@ -21,11 +22,6 @@ #define FLASH_STATUS_BUSY_MASK 0x01 -#define PIN_MISO 4 -#define PIN_CS 5 -#define PIN_SCK 6 -#define PIN_MOSI 7 - static inline void cs_select(uint cs_pin) { asm volatile("nop \n nop \n nop"); // FIXME gpio_put(cs_pin, 0); @@ -110,19 +106,27 @@ void printbuf(uint8_t buf[FLASH_PAGE_SIZE]) { int main() { // Enable UART so we can print status output stdio_init_all(); +#if !defined(spi_default) || !defined(PICO_DEFAULT_SPI_SCK_PIN) || !defined(PICO_DEFAULT_SPI_TX_PIN) || !defined(PICO_DEFAULT_SPI_RX_PIN) || !defined(PICO_DEFAULT_SPI_CSN_PIN) +#warning spi/spi_flash example requires a board with SPI pins + puts("Default SPI pins were not defined"); +#else printf("SPI flash example\n"); // Enable SPI 0 at 1 MHz and connect to GPIOs - spi_init(spi0, 1000 * 1000); - gpio_set_function(PIN_MISO, GPIO_FUNC_SPI); - gpio_set_function(PIN_SCK, GPIO_FUNC_SPI); - gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI); + spi_init(spi_default, 1000 * 1000); + gpio_set_function(PICO_DEFAULT_SPI_RX_PIN, GPIO_FUNC_SPI); + gpio_set_function(PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_SPI); + gpio_set_function(PICO_DEFAULT_SPI_TX_PIN, GPIO_FUNC_SPI); + // Make the SPI pins available to picotool + bi_decl(bi_3pins_with_func(PICO_DEFAULT_SPI_RX_PIN, PICO_DEFAULT_SPI_TX_PIN, PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_SPI)); // Chip select is active-low, so we'll initialise it to a driven-high state - gpio_init(PIN_CS); - gpio_put(PIN_CS, 1); - gpio_set_dir(PIN_CS, GPIO_OUT); + gpio_init(PICO_DEFAULT_SPI_CSN_PIN); + gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 1); + gpio_set_dir(PICO_DEFAULT_SPI_CSN_PIN, GPIO_OUT); + // Make the CS pin available to picotool + bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "CS")); printf("SPI initialised, let's goooooo\n"); @@ -130,25 +134,26 @@ int main() { const uint32_t target_addr = 0; - flash_sector_erase(spi0, PIN_CS, target_addr); - flash_read(spi0, PIN_CS, target_addr, page_buf, FLASH_PAGE_SIZE); + flash_sector_erase(spi_default, PICO_DEFAULT_SPI_CSN_PIN, target_addr); + flash_read(spi_default, PICO_DEFAULT_SPI_CSN_PIN, target_addr, page_buf, FLASH_PAGE_SIZE); printf("After erase:\n"); printbuf(page_buf); for (int i = 0; i < FLASH_PAGE_SIZE; ++i) page_buf[i] = i; - flash_page_program(spi0, PIN_CS, target_addr, page_buf); - flash_read(spi0, PIN_CS, target_addr, page_buf, FLASH_PAGE_SIZE); + flash_page_program(spi_default, PICO_DEFAULT_SPI_CSN_PIN, target_addr, page_buf); + flash_read(spi_default, PICO_DEFAULT_SPI_CSN_PIN, target_addr, page_buf, FLASH_PAGE_SIZE); printf("After program:\n"); printbuf(page_buf); - flash_sector_erase(spi0, PIN_CS, target_addr); - flash_read(spi0, PIN_CS, target_addr, page_buf, FLASH_PAGE_SIZE); + flash_sector_erase(spi_default, PICO_DEFAULT_SPI_CSN_PIN, target_addr); + flash_read(spi_default, PICO_DEFAULT_SPI_CSN_PIN, target_addr, page_buf, FLASH_PAGE_SIZE); printf("Erase again:\n"); printbuf(page_buf); return 0; +#endif } From 13a84b8f63e2be8246d99cad47e3bdeb6f869af7 Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Thu, 4 Mar 2021 14:05:37 +0000 Subject: [PATCH 25/30] Fix typo from #64 --- spi/bme280_spi/bme280_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spi/bme280_spi/bme280_spi.c b/spi/bme280_spi/bme280_spi.c index 69ad74a..488ed91 100644 --- a/spi/bme280_spi/bme280_spi.c +++ b/spi/bme280_spi/bme280_spi.c @@ -25,7 +25,7 @@ GPIO 17 (pin 22) Chip select -> CSB/!CS on bme280 board GPIO 18 (pin 24) SCK/spi0_sclk -> SCL/SCK on bme280 board GPIO 19 (pin 25) MOSI/spi0_tx -> SDA/SDI on bme280 board - 3.3v (pin 3;6) -> VCC on bme280 board + 3.3v (pin 36) -> VCC on bme280 board GND (pin 38) -> GND on bme280 board Note: SPI devices can have a number of different naming schemes for pins. See From ecd79e945618bcc5505cf2eb5de92f592eafa821 Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Thu, 4 Mar 2021 17:58:13 +0000 Subject: [PATCH 26/30] Small changes to the binary_info pin names --- pio/spi/spi_flash.c | 6 ++---- spi/bme280_spi/bme280_spi.c | 2 +- spi/mpu9250_spi/mpu9250_spi.c | 2 +- spi/spi_dma/spi_dma.c | 2 +- spi/spi_flash/spi_flash.c | 2 +- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/pio/spi/spi_flash.c b/pio/spi/spi_flash.c index 1f2fdec..fd97f17 100644 --- a/pio/spi/spi_flash.c +++ b/pio/spi/spi_flash.c @@ -114,8 +114,6 @@ int main() { gpio_init(PICO_DEFAULT_SPI_CSN_PIN); gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 1); gpio_set_dir(PICO_DEFAULT_SPI_CSN_PIN, GPIO_OUT); - // Make the CS pin available to picotool - bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "CS")); uint offset = pio_add_program(spi.pio, &spi_cpha0_program); printf("Loaded program at %d\n", offset); @@ -129,8 +127,8 @@ int main() { PICO_DEFAULT_SPI_TX_PIN, PICO_DEFAULT_SPI_RX_PIN ); - // Make the SPI pins available to picotool - bi_decl(bi_3pins_with_func(PICO_DEFAULT_SPI_RX_PIN, PICO_DEFAULT_SPI_TX_PIN, PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_PIO0)); + // Make the 'SPI' pins available to picotool + bi_decl(bi_4pins_with_names(PICO_DEFAULT_SPI_RX_PIN, "SPI RX", PICO_DEFAULT_SPI_TX_PIN, "SPI TX", PICO_DEFAULT_SPI_SCK_PIN, "SPI SCK", PICO_DEFAULT_SPI_CSN_PIN, "SPI CS")); uint8_t page_buf[FLASH_PAGE_SIZE]; diff --git a/spi/bme280_spi/bme280_spi.c b/spi/bme280_spi/bme280_spi.c index 488ed91..bee24c2 100644 --- a/spi/bme280_spi/bme280_spi.c +++ b/spi/bme280_spi/bme280_spi.c @@ -206,7 +206,7 @@ int main() { gpio_set_dir(PICO_DEFAULT_SPI_CSN_PIN, GPIO_OUT); gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 1); // Make the CS pin available to picotool - bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "CS")); + bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "SPI CS")); // See if SPI is working - interrograte the device for its I2C ID number, should be 0x60 uint8_t id; diff --git a/spi/mpu9250_spi/mpu9250_spi.c b/spi/mpu9250_spi/mpu9250_spi.c index 5714cb7..aab48ca 100644 --- a/spi/mpu9250_spi/mpu9250_spi.c +++ b/spi/mpu9250_spi/mpu9250_spi.c @@ -126,7 +126,7 @@ int main() { gpio_set_dir(PIN_CS, GPIO_OUT); gpio_put(PIN_CS, 1); // Make the CS pin available to picotool - bi_decl(bi_1pin_with_name(PIN_CS, "CS")); + bi_decl(bi_1pin_with_name(PIN_CS, "SPI CS")); mpu9250_reset(); diff --git a/spi/spi_dma/spi_dma.c b/spi/spi_dma/spi_dma.c index 1354b34..9a9b8b3 100644 --- a/spi/spi_dma/spi_dma.c +++ b/spi/spi_dma/spi_dma.c @@ -34,7 +34,7 @@ int main() { // Make the SPI pins available to picotool bi_decl(bi_3pins_with_func(PICO_DEFAULT_SPI_RX_PIN, PICO_DEFAULT_SPI_TX_PIN, PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_SPI)); // Make the CS pin available to picotool - bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "CS")); + bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "SPI CS")); // Grab some unused dma channels const uint dma_tx = dma_claim_unused_channel(true); diff --git a/spi/spi_flash/spi_flash.c b/spi/spi_flash/spi_flash.c index 4e214f5..156a992 100644 --- a/spi/spi_flash/spi_flash.c +++ b/spi/spi_flash/spi_flash.c @@ -126,7 +126,7 @@ int main() { gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 1); gpio_set_dir(PICO_DEFAULT_SPI_CSN_PIN, GPIO_OUT); // Make the CS pin available to picotool - bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "CS")); + bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "SPI CS")); printf("SPI initialised, let's goooooo\n"); From b14e0f3ab0e88004f4584b1a3533a0f960c0fc92 Mon Sep 17 00:00:00 2001 From: Liam Fraser Date: Mon, 1 Mar 2021 16:27:12 +0000 Subject: [PATCH 27/30] Add github actions --- .github/workflows/cmake.yml | 59 +++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 .github/workflows/cmake.yml diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml new file mode 100644 index 0000000..23f0e1a --- /dev/null +++ b/.github/workflows/cmake.yml @@ -0,0 +1,59 @@ +name: CMake +on: [push] + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Release + +jobs: + build: + runs-on: [self-hosted, Linux, X64] + + steps: + - name: Clean workspace + run: | + echo "Cleaning up previous run" + rm -rf "${{ github.workspace }}" + mkdir -p "${{ github.workspace }}" + + - name: Checkout pico-examples + uses: actions/checkout@v2 + with: + path: pico-examples + + - name: Checkout pico-sdk/develop + uses: actions/checkout@v2 + with: + repository: raspberrypi/pico-sdk + ref: develop + path: pico-sdk + + - name: Checkout pico-sdk submodules + working-directory: ${{github.workspace}}/pico-sdk + run: git submodule update --init + + - name: Create Build Environment + # Some projects don't allow in-source building, so create a separate build directory + # We'll use this as our working directory for all subsequent commands + working-directory: ${{github.workspace}}/pico-examples + run: cmake -E make_directory ${{github.workspace}}/pico-examples/build + + - name: Configure CMake + # Use a bash shell so we can use the same syntax for environment variable + # access regardless of the host operating system + shell: bash + working-directory: ${{github.workspace}}/pico-examples/build + # Note the current convention is to use the -S and -B options here to specify source + # and build directories, but this is only available with CMake 3.13 and higher. + # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 + run: PICO_SDK_PATH=../../pico-sdk cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE + + - name: Get core count + id: core_count + run : cat /proc/cpuinfo | grep processor | wc -l + + - name: Build + working-directory: ${{github.workspace}}/pico-examples/build + shell: bash + # Execute the build. You can specify a specific target with "--target " + run: cmake --build . --config $BUILD_TYPE --parallel ${{steps.core_count.outputs.output}} \ No newline at end of file From a68688f1912b98bd5043898251f358d4d7dc3746 Mon Sep 17 00:00:00 2001 From: Liam Fraser Date: Wed, 3 Mar 2021 16:38:57 +0000 Subject: [PATCH 28/30] Update cmake workflow to trigger on push + pull request. Only run in raspberry pi repo (not on forks) --- .github/workflows/cmake.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 23f0e1a..b683d93 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -1,5 +1,5 @@ name: CMake -on: [push] +on: [push, pull_request] env: # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) @@ -7,6 +7,7 @@ env: jobs: build: + if: github.repository_owner == 'raspberrypi' runs-on: [self-hosted, Linux, X64] steps: From 7915827d7a9c920e8196937e7c3c5838c9ea2747 Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Thu, 4 Mar 2021 11:32:56 +0000 Subject: [PATCH 29/30] Fix examples to build cleanly if PICO_DEFAULT_LED_PIN isn't defined --- blink/blink.c | 4 ++++ picoboard/blinky/blinky.c | 20 ++++++++++++-------- picoboard/button/button.c | 2 +- pio/pwm/pwm.c | 5 +++++ system/hello_double_tap/hello_double_tap.c | 4 ++++ 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/blink/blink.c b/blink/blink.c index f413d50..d478d78 100644 --- a/blink/blink.c +++ b/blink/blink.c @@ -7,6 +7,9 @@ #include "pico/stdlib.h" int main() { +#ifndef PICO_DEFAULT_LED_PIN +#warning blink example requires a board with a regular LED +#else const uint LED_PIN = PICO_DEFAULT_LED_PIN; gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); @@ -16,4 +19,5 @@ int main() { gpio_put(LED_PIN, 0); sleep_ms(250); } +#endif } diff --git a/picoboard/blinky/blinky.c b/picoboard/blinky/blinky.c index eb2c545..6d51aaf 100644 --- a/picoboard/blinky/blinky.c +++ b/picoboard/blinky/blinky.c @@ -8,7 +8,6 @@ #include "pico/stdlib.h" #include "hardware/gpio.h" -const uint LED_PIN = PICO_DEFAULT_LED_PIN; const uint DOT_PERIOD_MS = 100; const char *morse_letters[] = { @@ -40,25 +39,25 @@ const char *morse_letters[] = { "--.." // Z }; -void put_morse_letter(const char *pattern) { +void put_morse_letter(uint led_pin, const char *pattern) { for (; *pattern; ++pattern) { - gpio_put(LED_PIN, 1); + gpio_put(led_pin, 1); if (*pattern == '.') sleep_ms(DOT_PERIOD_MS); else sleep_ms(DOT_PERIOD_MS * 3); - gpio_put(LED_PIN, 0); + gpio_put(led_pin, 0); sleep_ms(DOT_PERIOD_MS * 1); } sleep_ms(DOT_PERIOD_MS * 2); } -void put_morse_str(const char *str) { +void put_morse_str(uint led_pin, const char *str) { for (; *str; ++str) { if (*str >= 'A' && *str < 'Z') { - put_morse_letter(morse_letters[*str - 'A']); + put_morse_letter(led_pin, morse_letters[*str - 'A']); } else if (*str >= 'a' && *str < 'z') { - put_morse_letter(morse_letters[*str - 'a']); + put_morse_letter(led_pin, morse_letters[*str - 'a']); } else if (*str == ' ') { sleep_ms(DOT_PERIOD_MS * 4); } @@ -66,10 +65,15 @@ void put_morse_str(const char *str) { } int main() { +#ifndef PICO_DEFAULT_LED_PIN +#warning picoboard/blinky example requires a board with a regular LED +#else + const uint LED_PIN = PICO_DEFAULT_LED_PIN; gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); while (true) { - put_morse_str("Hello world"); + put_morse_str(LED_PIN, "Hello world"); sleep_ms(1000); } +#endif } diff --git a/picoboard/button/button.c b/picoboard/button/button.c index b113533..6a5a5dd 100644 --- a/picoboard/button/button.c +++ b/picoboard/button/button.c @@ -54,7 +54,7 @@ bool __no_inline_not_in_flash_func(get_bootsel_button)() { int main() { #ifndef PICO_DEFAULT_LED_PIN -#warning picobooard/button example requires a board with a regular LED +#warning picoboard/button example requires a board with a regular LED #else gpio_init(PICO_DEFAULT_LED_PIN); gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); diff --git a/pio/pwm/pwm.c b/pio/pwm/pwm.c index f1cc46d..c3148a6 100644 --- a/pio/pwm/pwm.c +++ b/pio/pwm/pwm.c @@ -26,6 +26,10 @@ void pio_pwm_set_level(PIO pio, uint sm, uint32_t level) { int main() { stdio_init_all(); +#ifndef PICO_DEFAULT_LED_PIN +#warning pio/pwm example requires a board with a regular LED + puts("Default LED pin was not defined"); +#else // todo get free sm PIO pio = pio0; @@ -43,4 +47,5 @@ int main() { level = (level + 1) % 256; sleep_ms(10); } +#endif } diff --git a/system/hello_double_tap/hello_double_tap.c b/system/hello_double_tap/hello_double_tap.c index e64e8ae..bc06bf6 100644 --- a/system/hello_double_tap/hello_double_tap.c +++ b/system/hello_double_tap/hello_double_tap.c @@ -13,6 +13,9 @@ // `pico_bootsel_via_double_reset` library! int main() { +#ifndef PICO_DEFAULT_LED_PIN +#warning system/hello_double_tap example requires a board with a regular LED +#else const uint LED_PIN = PICO_DEFAULT_LED_PIN; gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); @@ -22,4 +25,5 @@ int main() { gpio_put(LED_PIN, 0); sleep_ms(250); } +#endif } From 2fb08a028f886624ebc9c938775e054860549159 Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Fri, 5 Mar 2021 02:13:59 +0000 Subject: [PATCH 30/30] Let hello_double_tap run without an LED defined --- system/hello_double_tap/hello_double_tap.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/system/hello_double_tap/hello_double_tap.c b/system/hello_double_tap/hello_double_tap.c index bc06bf6..2af0f85 100644 --- a/system/hello_double_tap/hello_double_tap.c +++ b/system/hello_double_tap/hello_double_tap.c @@ -13,9 +13,7 @@ // `pico_bootsel_via_double_reset` library! int main() { -#ifndef PICO_DEFAULT_LED_PIN -#warning system/hello_double_tap example requires a board with a regular LED -#else +#ifdef PICO_DEFAULT_LED_PIN const uint LED_PIN = PICO_DEFAULT_LED_PIN; gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); @@ -25,5 +23,9 @@ int main() { gpio_put(LED_PIN, 0); sleep_ms(250); } +#else + while (true) { + sleep_ms(250); + } #endif }