Summer brought a revision of the STM32F401RE TCD1304 driver.
In the firmware for the nucleo board the data collected by the ADC is stored in memory using DMA. Until now the ADC+DMA was turned on by an interrupt created by the timer controlling the ICG-pulses (remember that the ICG pulse moves the pixels to the shift registers on the TCD1304). The ADC and DMA are turned off again by an interrupt created by the DMA-controller once the write-buffer is full.
Enabling the DMA from a timer interrupt is painless, but disabling it using an interrupt triggered by the same DMA-stream that you want to turn off is not. The reason is that disabling the DMA-stream creates a new interrupt – the same interrupt in fact – so you can easily get stuck in the interrupt routine.
To avoid this there are several possibillities:
- You can switch the DMA-mode from circular to normal, then the DMA shuts itself down once the write-buffer is full. The downside is that that means reconfiguring the DMA-controller every time it needs restarting. But time is of the essence and there’s only 91 µs from the ICG-timer overflows until the first pixel arrives at the ADC – and I have no idea how long the interrupt latency is or how long it takes for the DMA to start.
- You can probably find a clever way to only switch off the DMA-controller once, even if the interrupt routine disabling it is also called when it’s disabled. However I couldn’t, my hangover from the day before was too severe.
- You can read the reference manual for the STM32F401RE again and realize that you don’t need to touch neither the DMA nor the ADC. You simply disable the timer that paces the ADC. With the timer disabled the ADC won’t start new conversions and won’t make new DMA-requests. So that’s how it’s handled from now on.
I thought I would be able to write a firmware with UART instead of SPI during the summer holiday, but it’s only halfway done as I ended up spending my time listening to jazz and drinking beers instead. It’s high on my autumn-todo-list though and it will enable direct communication over the nucleo’s built-in ST-link through USB.
This means saying goodbye to the raspberry pi – unless of course you stick with the SPI-version. It also means that the nucleo board will have a say in just exactly when data is transmitted – in contrast to SPI where the rpi must be master, there’s no such restriction with UART. The downside is that while SPI is fast – it takes just 4 ms to transmit all the data from the TCD1304 – UART is not. The transmission time is around 320 ms with a baud-rate of 230400 bps (the highest I’ve been able to achieve) with UART.