pico-sdk
pico-sdk copied to clipboard
SPI transfer without CS/SS on Raspberry Pi Pico
I´m operating with a Master SPI device, that sends Serial Data via SPI, but there is no ChipSelect / SlaveSelect available. The input Data has to go from the device to my raspby pico to the PC Com Port. My idea was to work with either DMA or SPI interrupts, because the data words are always 16 bits long. I could not get the SPI interrupts working without a chip select, because it seems to look like that the SPI interrupts are getting triggerd by the CS signal. So I tried to rout the SPI receive register to the DMA input register and get an interrupt after every 16 bits / when the DMA register is filled up. For some reason the DMA interrupt is getting triggerd permanently, even when my SPI input is not connected. I guess the routing did not work properly or the DMA Fifo is full all the time for some reason. I´m working on a Raspberry Pi Pico (Slave) and writing in C (Arduino IDE). Any ideas or suggestions? When I run the Code i´m getting
Interrupt 0000
printed on the console at max. Speed of the Raspberry - as if I had dma_handler() in the void loop.
This is the code:
*#include "pico/stdlib.h" #include "hardware/spi.h" #include "hardware/dma.h" #define BUF_LEN 2 uint16_t spi1out_buf[BUF_LEN]; int chan = dma_claim_unused_channel(true); dma_channel_config c = dma_channel_get_default_config(chan); int i = 0;
void setup() {
//SPI Init gpio_set_function(12, GPIO_FUNC_SPI); gpio_set_function(13, GPIO_FUNC_SPI); gpio_set_function(14, GPIO_FUNC_SPI);
spi_init(spi1, 1000 * 1000); spi_set_format(spi1,16,SPI_CPOL_0,SPI_CPHA_0,SPI_MSB_FIRST); spi_set_slave(spi1, 1); spi_get_hw(spi1)->dmacr = SPI_SSPDMACR_RXDMAE_BITS;
//DMA init channel_config_set_transfer_data_size(&c, DMA_SIZE_16); channel_config_set_dreq(&c, spi_get_dreq(spi1, true)); channel_config_set_read_increment(&c, true); channel_config_set_write_increment(&c, false);
dma_channel_configure(chan,&c,spi1out_buf, NULL,BUF_LEN, false); dma_channel_set_irq0_enabled(chan, true); irq_set_exclusive_handler(DMA_IRQ_0, dma_handler); irq_set_enabled(DMA_IRQ_0, true);
dma_start_channel_mask(1u << chan);
dma_handler();
}
// Interrupt handler
void dma_handler(){ Serial.println("Interrupt"); Serial.printf("%04x\r\n",spi1out_buf[i]); dma_hw->ints0 = 1u << chan; dma_channel_set_read_addr(chan, &spi_get_hw(spi1)->dr, true); }
// MAIN Loop
void loop() { }*
Is there a reason you need to try and use interrupts and/or DMA? My suggestion would be that you try and get it working using a simple polling loop first, and only try switching to interrupts at a later stage, after you've got the simple version working? :shrug:
@lurch I did a simpler version with an Arduino as Master and with Chip Select. That was working. But do you have an idea why the dma interrupt is not triggerd correctly?
Nope, that's not my area of knowledge, so I'll keep quiet in the hope that somebody with more knowledge does answer. But as I've told you before, I think you're probably more likely to get help if you just use the "raw" pico-sdk rather than using any kind of Arduino wrapper / IDE? :man_shrugging: