3434#include "block_device_ev3.h"
3535
3636#include <pbdrv/block_device.h>
37+ #include <pbdrv/cache.h>
3738#include <pbdrv/clock.h>
3839#include <pbdrv/compiler.h>
3940#include <pbdrv/gpio.h>
@@ -93,17 +94,27 @@ enum {
9394static struct {
9495 /** HAL Transfer status */
9596 volatile spi_status_t status ;
96- // This is used when SPI only needs to receive. It should always stay as 0.
97- uint8_t tx_dummy_byte ;
98- // This is used when received data is to be discarded. Its value should be ignored.
99- uint8_t rx_dummy_byte ;
97+ // This stores the RX buffer address so that we clean the cache when DMA is complete
98+ uint32_t rx_user_buf_addr ;
99+ // This stores the RX buffer size;
100+ uint32_t rx_user_buf_sz ;
101+ } spi_dev ;
102+
103+ /**
104+ * SPI small DMA buffers
105+ */
106+ static struct {
100107 // This is used when transmitting so that the last byte clears CSHOLD.
101108 uint32_t tx_last_word ;
102109 // This is used to hold the initial command to the SPI peripheral.
103110 uint8_t spi_cmd_buf_tx [SPI_CMD_BUF_SZ ];
104111 // This is used to hold the replies to commands to the SPI peripheral.
105112 uint8_t spi_cmd_buf_rx [SPI_CMD_BUF_SZ ];
106- } spi_dev ;
113+ // This is used when SPI only needs to receive. It should always stay as 0.
114+ uint8_t tx_dummy_byte ;
115+ // This is used when received data is to be discarded. Its value should be ignored.
116+ uint8_t rx_dummy_byte ;
117+ } spi_dev_bufs PBDRV_DMA_BUF ;
107118
108119static uint32_t last_spi_dma_complete_time ;
109120
@@ -114,6 +125,10 @@ static void spi_dma_complete(void) {
114125 }
115126 SPIIntDisable (SOC_SPI_0_REGS , SPI_DMA_REQUEST_ENA_INT );
116127 pbio_os_request_poll ();
128+ pbdrv_cache_prepare_after_dma (& spi_dev_bufs , sizeof (spi_dev_bufs ));
129+ if (spi_dev .rx_user_buf_addr && spi_dev .rx_user_buf_sz ) {
130+ pbdrv_cache_prepare_after_dma ((void * )spi_dev .rx_user_buf_addr , spi_dev .rx_user_buf_sz );
131+ }
117132 last_spi_dma_complete_time = pbdrv_clock_get_ms ();
118133}
119134
@@ -153,7 +168,7 @@ static void spi0_isr(void) {
153168 continue ;
154169 }
155170
156- spi_dev .spi_cmd_buf_rx [0 ] = HWREG (SOC_SPI_0_REGS + SPI_SPIBUF );
171+ spi_dev_bufs .spi_cmd_buf_rx [0 ] = HWREG (SOC_SPI_0_REGS + SPI_SPIBUF );
157172 spi_dev .status &= ~SPI_STATUS_WAIT_RX ;
158173 SPIIntDisable (SOC_SPI_0_REGS , SPI_RECV_INT );
159174 pbio_os_request_poll ();
@@ -351,19 +366,24 @@ static pbio_error_t spi_begin_for_flash(
351366
352367 spi_dev .status = SPI_STATUS_WAIT_RX ;
353368
369+ // Prevent write to spi_dev.status from being reordered
370+ pbdrv_compiler_memory_barrier ();
371+
354372 uint32_t tx = spi0_last_dat1_for_flash (cmd [0 ]);
355373 SPIIntEnable (SOC_SPI_0_REGS , SPI_RECV_INT );
356374 HWREG (SOC_SPI_0_REGS + SPI_SPIDAT1 ) = tx ;
357375 } else {
358- memcpy (& spi_dev .spi_cmd_buf_tx , cmd , cmd_len );
376+ memcpy (spi_dev_bufs .spi_cmd_buf_tx , cmd , cmd_len );
377+ spi_dev .rx_user_buf_addr = (uint32_t )user_data_rx ;
378+ spi_dev .rx_user_buf_sz = user_data_len ;
359379
360380 if (user_data_len == 0 ) {
361381 // Only a command, no user data
362382
363- spi_dev .tx_last_word = spi0_last_dat1_for_flash (cmd [cmd_len - 1 ]);
383+ spi_dev_bufs .tx_last_word = spi0_last_dat1_for_flash (cmd [cmd_len - 1 ]);
364384
365385 // TX everything except last byte
366- ps .p .srcAddr = (unsigned int )(& spi_dev .spi_cmd_buf_tx );
386+ ps .p .srcAddr = (unsigned int )(& spi_dev_bufs .spi_cmd_buf_tx );
367387 ps .p .destAddr = SOC_SPI_0_REGS + SPI_SPIDAT1 ;
368388 ps .p .aCnt = 1 ;
369389 ps .p .bCnt = cmd_len - 1 ;
@@ -378,7 +398,7 @@ static pbio_error_t spi_begin_for_flash(
378398 edma3_set_param (EDMA3_CHA_SPI0_TX , & ps );
379399
380400 // TX last byte, clearing CSHOLD
381- ps .p .srcAddr = (unsigned int )(& spi_dev .tx_last_word );
401+ ps .p .srcAddr = (unsigned int )(& spi_dev_bufs .tx_last_word );
382402 ps .p .aCnt = 4 ;
383403 ps .p .bCnt = 1 ;
384404 ps .p .linkAddr = 0xffff ;
@@ -387,7 +407,7 @@ static pbio_error_t spi_begin_for_flash(
387407
388408 // RX all bytes
389409 ps .p .srcAddr = SOC_SPI_0_REGS + SPI_SPIBUF ;
390- ps .p .destAddr = (unsigned int )(& spi_dev .spi_cmd_buf_rx );
410+ ps .p .destAddr = (unsigned int )(& spi_dev_bufs .spi_cmd_buf_rx );
391411 ps .p .aCnt = 1 ;
392412 ps .p .bCnt = cmd_len ;
393413 ps .p .cCnt = 1 ;
@@ -403,7 +423,7 @@ static pbio_error_t spi_begin_for_flash(
403423 // Command *and* user data
404424
405425 // TX the command
406- ps .p .srcAddr = (unsigned int )(& spi_dev .spi_cmd_buf_tx );
426+ ps .p .srcAddr = (unsigned int )(& spi_dev_bufs .spi_cmd_buf_tx );
407427 ps .p .destAddr = SOC_SPI_0_REGS + SPI_SPIDAT1 ;
408428 ps .p .aCnt = 1 ;
409429 ps .p .bCnt = cmd_len ;
@@ -418,7 +438,8 @@ static pbio_error_t spi_begin_for_flash(
418438 edma3_set_param (EDMA3_CHA_SPI0_TX , & ps );
419439
420440 if (user_data_tx ) {
421- spi_dev .tx_last_word = spi0_last_dat1_for_flash (user_data_tx [user_data_len - 1 ]);
441+ pbdrv_cache_prepare_before_dma (user_data_tx , user_data_len );
442+ spi_dev_bufs .tx_last_word = spi0_last_dat1_for_flash (user_data_tx [user_data_len - 1 ]);
422443
423444 // TX all but the last byte
424445 ps .p .srcAddr = (unsigned int )(user_data_tx );
@@ -427,24 +448,24 @@ static pbio_error_t spi_begin_for_flash(
427448 edma3_set_param (126 , & ps );
428449
429450 // TX the last byte, clearing CSHOLD
430- ps .p .srcAddr = (unsigned int )(& spi_dev .tx_last_word );
451+ ps .p .srcAddr = (unsigned int )(& spi_dev_bufs .tx_last_word );
431452 ps .p .aCnt = 4 ;
432453 ps .p .bCnt = 1 ;
433454 ps .p .linkAddr = 0xffff ;
434455 ps .p .opt = EDMA3CC_OPT_TCINTEN | (EDMA3_CHA_SPI0_TX << EDMA3CC_OPT_TCC_SHIFT );
435456 edma3_set_param (127 , & ps );
436457 } else {
437- spi_dev .tx_last_word = spi0_last_dat1_for_flash (0 );
458+ spi_dev_bufs .tx_last_word = spi0_last_dat1_for_flash (0 );
438459
439460 // TX all but the last byte
440- ps .p .srcAddr = (unsigned int )(& spi_dev .tx_dummy_byte );
461+ ps .p .srcAddr = (unsigned int )(& spi_dev_bufs .tx_dummy_byte );
441462 ps .p .bCnt = user_data_len - 1 ;
442463 ps .p .srcBIdx = 0 ;
443464 ps .p .linkAddr = 127 * 32 ;
444465 edma3_set_param (126 , & ps );
445466
446467 // TX the last byte, clearing CSHOLD
447- ps .p .srcAddr = (unsigned int )(& spi_dev .tx_last_word );
468+ ps .p .srcAddr = (unsigned int )(& spi_dev_bufs .tx_last_word );
448469 ps .p .aCnt = 4 ;
449470 ps .p .bCnt = 1 ;
450471 ps .p .linkAddr = 0xffff ;
@@ -454,7 +475,7 @@ static pbio_error_t spi_begin_for_flash(
454475
455476 // RX the command
456477 ps .p .srcAddr = SOC_SPI_0_REGS + SPI_SPIBUF ;
457- ps .p .destAddr = (unsigned int )(& spi_dev .spi_cmd_buf_rx );
478+ ps .p .destAddr = (unsigned int )(& spi_dev_bufs .spi_cmd_buf_rx );
458479 ps .p .aCnt = 1 ;
459480 ps .p .bCnt = cmd_len ;
460481 ps .p .cCnt = 1 ;
@@ -476,7 +497,7 @@ static pbio_error_t spi_begin_for_flash(
476497 edma3_set_param (125 , & ps );
477498 } else {
478499 // RX dummy
479- ps .p .destAddr = (unsigned int )(& spi_dev .rx_dummy_byte );
500+ ps .p .destAddr = (unsigned int )(& spi_dev_bufs .rx_dummy_byte );
480501 ps .p .bCnt = user_data_len ;
481502 ps .p .destBIdx = 0 ;
482503 ps .p .linkAddr = 0xffff ;
@@ -487,8 +508,9 @@ static pbio_error_t spi_begin_for_flash(
487508
488509 spi_dev .status = SPI_STATUS_WAIT_TX | SPI_STATUS_WAIT_RX ;
489510
490- // TODO: eventually needs DMA cache management
491- pbdrv_compiler_memory_barrier ();
511+ // Make sure writes to tx buffer leave cache
512+ // (we already flush the user buffer earlier)
513+ pbdrv_cache_prepare_before_dma (& spi_dev_bufs , sizeof (spi_dev_bufs ));
492514
493515 EDMA3EnableTransfer (SOC_EDMA30CC_0_REGS , EDMA3_CHA_SPI0_TX , EDMA3_TRIG_MODE_EVENT );
494516 EDMA3EnableTransfer (SOC_EDMA30CC_0_REGS , EDMA3_CHA_SPI0_RX , EDMA3_TRIG_MODE_EVENT );
@@ -600,7 +622,7 @@ static pbio_error_t flash_wait_write(pbio_os_state_t *state) {
600622 }
601623 PBIO_OS_AWAIT_WHILE (state , spi_dev .status & SPI_STATUS_WAIT_ANY );
602624
603- status = spi_dev .spi_cmd_buf_rx [1 ];
625+ status = spi_dev_bufs .spi_cmd_buf_rx [1 ];
604626 } while (status & FLASH_STATUS_BUSY );
605627
606628 PBIO_OS_ASYNC_END (PBIO_SUCCESS );
@@ -722,7 +744,7 @@ static const uint32_t channel_cmd[PBDRV_CONFIG_ADC_EV3_ADC_NUM_CHANNELS + PBDRV_
722744 MANUAL_ADC_CHANNEL (15 ),
723745 MANUAL_ADC_CHANNEL (15 ),
724746};
725- static volatile uint16_t channel_data [PBDRV_CONFIG_ADC_EV3_ADC_NUM_CHANNELS + PBDRV_ADC_EV3_NUM_DELAY_SAMPLES ];
747+ static volatile uint16_t channel_data [PBDRV_CONFIG_ADC_EV3_ADC_NUM_CHANNELS + PBDRV_ADC_EV3_NUM_DELAY_SAMPLES ] PBDRV_DMA_BUF ;
726748
727749pbio_error_t pbdrv_adc_get_ch (uint8_t ch , uint16_t * value ) {
728750 if (ch >= PBDRV_CONFIG_ADC_EV3_ADC_NUM_CHANNELS ) {
@@ -733,8 +755,8 @@ pbio_error_t pbdrv_adc_get_ch(uint8_t ch, uint16_t *value) {
733755 uint16_t a , b ;
734756 do {
735757 // Values for the requested channel are received several samples later.
736- a = channel_data [ch + PBDRV_ADC_EV3_NUM_DELAY_SAMPLES ];
737- b = channel_data [ch + PBDRV_ADC_EV3_NUM_DELAY_SAMPLES ];
758+ a = PBDRV_UNCACHED ( channel_data [ch + PBDRV_ADC_EV3_NUM_DELAY_SAMPLES ]) ;
759+ b = PBDRV_UNCACHED ( channel_data [ch + PBDRV_ADC_EV3_NUM_DELAY_SAMPLES ]) ;
738760 } while (a != b );
739761
740762 // Mask the data to 10 bits
@@ -804,9 +826,14 @@ static pbio_error_t pbdrv_block_device_ev3_spi_begin_for_adc(const uint32_t *cmd
804826 ps .p .opt = EDMA3CC_OPT_TCINTEN | (EDMA3_CHA_SPI0_RX << EDMA3CC_OPT_TCC_SHIFT );
805827 edma3_set_param (EDMA3_CHA_SPI0_RX , & ps );
806828
829+ // We play dangerously and don't flush the cache for the ADC.
830+ // The commands are const, and the values are read through an uncached mapping.
831+ spi_dev .rx_user_buf_addr = 0 ;
832+ spi_dev .rx_user_buf_sz = 0 ;
833+
807834 spi_dev .status = SPI_STATUS_WAIT_TX | SPI_STATUS_WAIT_RX ;
808835
809- // TODO: eventually needs DMA cache management
836+ // Prevent write to spi_dev.status from being reordered
810837 pbdrv_compiler_memory_barrier ();
811838
812839 EDMA3EnableTransfer (SOC_EDMA30CC_0_REGS , EDMA3_CHA_SPI0_TX , EDMA3_TRIG_MODE_EVENT );
@@ -836,7 +863,7 @@ static struct {
836863 pbsys_storage_data_map_t data_map ;
837864 uint8_t data [PBDRV_CONFIG_BLOCK_DEVICE_RAM_SIZE ];
838865 };
839- } ramdisk __attribute__((section (".noinit" ), used ));
866+ } ramdisk __attribute__((aligned ( PBDRV_CACHE_LINE_SZ ), section (".noinit" ), used ));
840867
841868uint32_t pbdrv_block_device_get_writable_size (void ) {
842869 return PBDRV_CONFIG_BLOCK_DEVICE_EV3_SIZE - sizeof (ramdisk .saved_size );
@@ -869,7 +896,7 @@ pbio_error_t ev3_spi_process_thread(pbio_os_state_t *state, void *context) {
869896 return err ;
870897 }
871898 PBIO_OS_AWAIT_WHILE (state , spi_dev .status & SPI_STATUS_WAIT_ANY );
872- if (memcmp (device_id , & spi_dev .spi_cmd_buf_rx [1 ], sizeof (device_id ))) {
899+ if (memcmp (device_id , spi_dev_bufs .spi_cmd_buf_rx [1 ], sizeof (device_id ))) {
873900 return PBIO_ERROR_FAILED ;
874901 }
875902
0 commit comments