@@ -401,8 +401,7 @@ void spi_deinit(const spi_t *spi_obj) {
401401 }
402402}
403403
404- STATIC HAL_StatusTypeDef spi_wait_dma_finished (const spi_t * spi , uint32_t timeout ) {
405- uint32_t start = HAL_GetTick ();
404+ STATIC HAL_StatusTypeDef spi_wait_dma_finished (const spi_t * spi , uint32_t t_start , uint32_t timeout ) {
406405 volatile HAL_SPI_StateTypeDef * state = & spi -> spi -> State ;
407406 for (;;) {
408407 // Do an atomic check of the state; WFI will exit even if IRQs are disabled
@@ -413,7 +412,7 @@ STATIC HAL_StatusTypeDef spi_wait_dma_finished(const spi_t *spi, uint32_t timeou
413412 }
414413 __WFI ();
415414 enable_irq (irq_state );
416- if (HAL_GetTick () - start >= timeout ) {
415+ if (HAL_GetTick () - t_start >= timeout ) {
417416 return HAL_TIMEOUT ;
418417 }
419418 }
@@ -430,6 +429,8 @@ STATIC void spi_transfer(const spi_t *self, size_t len, const uint8_t *src, uint
430429 // time directly after the SPI/DMA is initialised. The cause of this is
431430 // unknown but we sidestep the issue by using polling for 1 byte transfer.
432431
432+ // Note: DMA transfers are limited to 65535 bytes at a time.
433+
433434 HAL_StatusTypeDef status ;
434435
435436 if (dest == NULL ) {
@@ -442,10 +443,20 @@ STATIC void spi_transfer(const spi_t *self, size_t len, const uint8_t *src, uint
442443 self -> spi -> hdmatx = & tx_dma ;
443444 self -> spi -> hdmarx = NULL ;
444445 MP_HAL_CLEAN_DCACHE (src , len );
445- status = HAL_SPI_Transmit_DMA (self -> spi , (uint8_t * )src , len );
446- if (status == HAL_OK ) {
447- status = spi_wait_dma_finished (self , timeout );
448- }
446+ uint32_t t_start = HAL_GetTick ();
447+ do {
448+ uint32_t l = MIN (len , 65535 );
449+ status = HAL_SPI_Transmit_DMA (self -> spi , (uint8_t * )src , l );
450+ if (status != HAL_OK ) {
451+ break ;
452+ }
453+ status = spi_wait_dma_finished (self , t_start , timeout );
454+ if (status != HAL_OK ) {
455+ break ;
456+ }
457+ len -= l ;
458+ src += l ;
459+ } while (len );
449460 dma_deinit (self -> tx_dma_descr );
450461 }
451462 } else if (src == NULL ) {
@@ -464,10 +475,20 @@ STATIC void spi_transfer(const spi_t *self, size_t len, const uint8_t *src, uint
464475 dma_init (& rx_dma , self -> rx_dma_descr , self -> spi );
465476 self -> spi -> hdmarx = & rx_dma ;
466477 MP_HAL_CLEANINVALIDATE_DCACHE (dest , len );
467- status = HAL_SPI_Receive_DMA (self -> spi , dest , len );
468- if (status == HAL_OK ) {
469- status = spi_wait_dma_finished (self , timeout );
470- }
478+ uint32_t t_start = HAL_GetTick ();
479+ do {
480+ uint32_t l = MIN (len , 65535 );
481+ status = HAL_SPI_Receive_DMA (self -> spi , dest , l );
482+ if (status != HAL_OK ) {
483+ break ;
484+ }
485+ status = spi_wait_dma_finished (self , t_start , timeout );
486+ if (status != HAL_OK ) {
487+ break ;
488+ }
489+ len -= l ;
490+ dest += l ;
491+ } while (len );
471492 if (self -> spi -> hdmatx != NULL ) {
472493 dma_deinit (self -> tx_dma_descr );
473494 }
@@ -485,10 +506,21 @@ STATIC void spi_transfer(const spi_t *self, size_t len, const uint8_t *src, uint
485506 self -> spi -> hdmarx = & rx_dma ;
486507 MP_HAL_CLEAN_DCACHE (src , len );
487508 MP_HAL_CLEANINVALIDATE_DCACHE (dest , len );
488- status = HAL_SPI_TransmitReceive_DMA (self -> spi , (uint8_t * )src , dest , len );
489- if (status == HAL_OK ) {
490- status = spi_wait_dma_finished (self , timeout );
491- }
509+ uint32_t t_start = HAL_GetTick ();
510+ do {
511+ uint32_t l = MIN (len , 65535 );
512+ status = HAL_SPI_TransmitReceive_DMA (self -> spi , (uint8_t * )src , dest , l );
513+ if (status != HAL_OK ) {
514+ break ;
515+ }
516+ status = spi_wait_dma_finished (self , t_start , timeout );
517+ if (status != HAL_OK ) {
518+ break ;
519+ }
520+ len -= l ;
521+ src += l ;
522+ dest += l ;
523+ } while (len );
492524 dma_deinit (self -> tx_dma_descr );
493525 dma_deinit (self -> rx_dma_descr );
494526 }
0 commit comments