diff --git a/platforms/pico/drivers/serial.c b/platforms/pico/drivers/serial.c index 15e71c5215..116dc6f5dc 100644 --- a/platforms/pico/drivers/serial.c +++ b/platforms/pico/drivers/serial.c @@ -68,7 +68,7 @@ inline static bool serial_read_pin(void) { return readPin(SOFT_SERIAL_PIN); } inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); } inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); } -void interrupt_handler(uint gpio, uint32_t events); +static void interrupt_handler(uint gpio, uint32_t events); static PIO pio = pio0; static uint sm_tx, sm_rx; @@ -144,7 +144,7 @@ void soft_serial_target_init(void) { } // Used by the master to synchronize timing with the slave. -static int __attribute__((noinline)) sync_recv(void) { +static int __no_inline_not_in_flash_func(sync_recv)(void) { serial_input(); volatile uint64_t timeout = time_us_64() + 10000; @@ -180,7 +180,7 @@ static int __attribute__((noinline)) sync_recv(void) { } // Used by the slave to send a synchronization signal to the master. -static void __attribute__((noinline)) sync_send(void) { +static void __no_inline_not_in_flash_func(sync_send)(void) { serial_output(); serial_low(); @@ -220,7 +220,7 @@ static void serial_wait_send_complete(void) { } // interrupt handle to be used by the slave device -void interrupt_handler(uint gpio, uint32_t events) { +static void __no_inline_not_in_flash_func(interrupt_handler)(uint gpio, uint32_t events) { if (gpio != SOFT_SERIAL_PIN || events != GPIO_IRQ_EDGE_FALL) { return; } @@ -339,7 +339,7 @@ void interrupt_handler(uint gpio, uint32_t events) { // TRANSACTION_NO_RESPONSE // TRANSACTION_DATA_ERROR // this code is very time dependent, so we need to disable interrupts -int soft_serial_transaction(int sstd_index) { +int __no_inline_not_in_flash_func(soft_serial_transaction)(int sstd_index) { if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR; split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered diff --git a/platforms/pico/drivers/ws2812.c b/platforms/pico/drivers/ws2812.c index 3eea6092ae..91eb8eadc5 100644 --- a/platforms/pico/drivers/ws2812.c +++ b/platforms/pico/drivers/ws2812.c @@ -1,16 +1,21 @@ +// Copyright 2022 sekigon-gonnoc +// SPDX-License-Identifier: GPL-2.0-or-later #include #include "ws2812.h" #include "ws2812.pio.h" +#include "atomic_util.h" #include "pio_manager.h" #include "boards/pico_boards.h" #include "pico/stdlib.h" +#include "hardware/dma.h" -static PIO pio = pio0; -static int sm = 0; +static PIO pio = pio0; +static int sm = 0; +static int dma_ch = 1; static int ws2812_init(void) { sm = pio_manager_get_empty_sm(pio); @@ -27,6 +32,15 @@ static int ws2812_init(void) { ws2812_program_init(pio, sm, offset, RGB_DI_PIN, 800000, false); + dma_channel_config conf = dma_channel_get_default_config(dma_ch); + + channel_config_set_read_increment(&conf, true); + channel_config_set_write_increment(&conf, false); + channel_config_set_transfer_data_size(&conf, DMA_SIZE_32); + channel_config_set_dreq(&conf, pio_get_dreq(pio, sm, true)); + + dma_channel_set_config(dma_ch, &conf, false); + dma_channel_set_write_addr(dma_ch, &pio->txf[sm], false); return 0; } @@ -40,12 +54,13 @@ void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) { } } - printf("led %d %d %d\n", ledarray[0].r, ledarray[0].g, ledarray[0].b); - + uint32_t leddata[RGBLED_NUM]; for (int i = 0; i < number_of_leds; i++) { - pio_sm_put_blocking(pio, sm, - (((uint32_t)ledarray[i].r) << 16) | - (((uint32_t)ledarray[i].g) << 24) | - ((uint32_t)ledarray[i].b << 8)); + leddata[i] = (((uint32_t)ledarray[i].g) << 24) | + (((uint32_t)ledarray[i].r) << 16) | + ((uint32_t)ledarray[i].b << 8); } + + dma_channel_transfer_from_buffer_now(dma_ch, leddata, number_of_leds); + dma_channel_wait_for_finish_blocking(dma_ch); }