11#include "spi.h"
22
3+ #include "FreeRTOS.h"
4+ #include "task.h"
5+
36#include "debug.h"
7+ #include "main.h"
48#include "pinout.h"
59
610#include "ch32v30x_dma.h"
11+ #include "ch32v30x_misc.h"
712#include "ch32v30x_rcc.h"
813#include "ch32v30x_spi.h"
914
10- #define SPI3_TX_DMA_CHANNEL DMA2_Channel2
11- #define SPI3_TX_DMA_FLAG_GL DMA2_FLAG_GL2
12- #define SPI3_TX_DMA_FLAG_TC DMA2_FLAG_TC2
13- #define SPI3_TX_DMA_FLAG_TE DMA2_FLAG_TE2
14- #define SPI3_TX_DMA_MAX_LEN 65535U
15+ #define SPI3_TX_DMA_CHANNEL DMA2_Channel2
16+ #define SPI3_TX_DMA_IRQn DMA2_Channel2_IRQn
17+ #define SPI3_TX_DMA_FLAG_GL DMA2_FLAG_GL2
18+ #define SPI3_TX_DMA_FLAG_TC DMA2_FLAG_TC2
19+ #define SPI3_TX_DMA_FLAG_TE DMA2_FLAG_TE2
20+ #define SPI3_TX_DMA_IT_GL DMA2_IT_GL2
21+ #define SPI3_TX_DMA_IT_TC DMA2_IT_TC2
22+ #define SPI3_TX_DMA_IT_TE DMA2_IT_TE2
23+ #define SPI3_TX_DMA_MAX_LEN 65535U
1524
1625static uint16_t s_spi3_data_size = SPI_DataSize_8b ;
1726static uint16_t s_spi3_tx_repeat_word = 0U ;
1827
28+ void DMA2_Channel2_IRQHandler (void ) __attribute__((interrupt ));
29+
1930static void spi_hw_set_data_size (uint16_t data_size )
2031{
2132 if (s_spi3_data_size == data_size )
@@ -35,16 +46,27 @@ static void spi_hw_set_data_size(uint16_t data_size)
3546
3647void spi_hw_wait_dma (void )
3748{
38- while (SPI_I2S_GetFlagStatus (SPI3 , SPI_I2S_FLAG_BSY ) != RESET )
49+
50+ bool const dma_in_progress =
51+ ((SPI3_TX_DMA_CHANNEL -> CFGR & DMA_CFGR1_EN ) != 0U ) &&
52+ (DMA_GetCurrDataCounter (SPI3_TX_DMA_CHANNEL ) > 0U );
53+
54+ if (dma_in_progress )
3955 {
56+ (void )ulTaskNotifyTake (pdTRUE , portMAX_DELAY );
4057 }
4158
42- while (DMA_GetCurrDataCounter (SPI3_TX_DMA_CHANNEL ) > 0 )
59+ /* DMA completion means the last word reached DATAR, not necessarily the
60+ * wire. The remaining BSY interval is at most one SPI frame. */
61+ while (SPI_I2S_GetFlagStatus (SPI3 , SPI_I2S_FLAG_BSY ) != RESET )
4362 {
4463 }
45- DMA_Cmd ( SPI3_TX_DMA_CHANNEL , DISABLE );
64+
4665 SPI_I2S_DMACmd (SPI3 , SPI_I2S_DMAReq_Tx , DISABLE );
66+ DMA_ITConfig (SPI3_TX_DMA_CHANNEL , DMA_IT_TC | DMA_IT_TE , DISABLE );
67+ DMA_Cmd (SPI3_TX_DMA_CHANNEL , DISABLE );
4768 DMA_ClearFlag (SPI3_TX_DMA_FLAG_GL | SPI3_TX_DMA_FLAG_TC | SPI3_TX_DMA_FLAG_TE );
69+ NVIC_ClearPendingIRQ (SPI3_TX_DMA_IRQn );
4870}
4971
5072void spi_hw_init (void )
@@ -82,6 +104,15 @@ void spi_hw_init(void)
82104 DMA_Cmd (SPI3_TX_DMA_CHANNEL , DISABLE );
83105 DMA_DeInit (SPI3_TX_DMA_CHANNEL );
84106 DMA_ClearFlag (SPI3_TX_DMA_FLAG_GL | SPI3_TX_DMA_FLAG_TC | SPI3_TX_DMA_FLAG_TE );
107+ NVIC_ClearPendingIRQ (SPI3_TX_DMA_IRQn );
108+
109+ NVIC_InitTypeDef dma_irq = {0 };
110+ dma_irq .NVIC_IRQChannel = SPI3_TX_DMA_IRQn ;
111+ dma_irq .NVIC_IRQChannelPreemptionPriority = 2U ;
112+ dma_irq .NVIC_IRQChannelSubPriority = 0U ;
113+ dma_irq .NVIC_IRQChannelCmd = ENABLE ;
114+ NVIC_Init (& dma_irq );
115+
85116 s_spi3_data_size = SPI_DataSize_8b ;
86117}
87118
@@ -125,6 +156,7 @@ static void spi_hw_transfer_dma_chunk(const uint8_t *tx_buf, uint16_t len)
125156 dma_init .DMA_M2M = DMA_M2M_Disable ;
126157 DMA_Init (SPI3_TX_DMA_CHANNEL , & dma_init );
127158
159+ DMA_ITConfig (SPI3_TX_DMA_CHANNEL , DMA_IT_TC | DMA_IT_TE , ENABLE );
128160 DMA_Cmd (SPI3_TX_DMA_CHANNEL , ENABLE );
129161 SPI_I2S_DMACmd (SPI3 , SPI_I2S_DMAReq_Tx , ENABLE );
130162}
@@ -157,6 +189,7 @@ static void spi_hw_transfer_dma_repeat_u16_chunk(uint16_t tx_word, uint16_t coun
157189 dma_init .DMA_M2M = DMA_M2M_Disable ;
158190 DMA_Init (SPI3_TX_DMA_CHANNEL , & dma_init );
159191
192+ DMA_ITConfig (SPI3_TX_DMA_CHANNEL , DMA_IT_TC | DMA_IT_TE , ENABLE );
160193 DMA_Cmd (SPI3_TX_DMA_CHANNEL , ENABLE );
161194 SPI_I2S_DMACmd (SPI3 , SPI_I2S_DMAReq_Tx , ENABLE );
162195}
@@ -188,10 +221,31 @@ static void spi_hw_transfer_dma_u16_chunk(const uint16_t *tx_buf, uint16_t count
188221 dma_init .DMA_M2M = DMA_M2M_Disable ;
189222 DMA_Init (SPI3_TX_DMA_CHANNEL , & dma_init );
190223
224+ DMA_ITConfig (SPI3_TX_DMA_CHANNEL , DMA_IT_TC | DMA_IT_TE , ENABLE );
191225 DMA_Cmd (SPI3_TX_DMA_CHANNEL , ENABLE );
192226 SPI_I2S_DMACmd (SPI3 , SPI_I2S_DMAReq_Tx , ENABLE );
193227}
194228
229+ void DMA2_Channel2_IRQHandler (void )
230+ {
231+ BaseType_t higher_priority_task_woken = pdFALSE ;
232+ bool const transfer_ended =
233+ (DMA_GetITStatus (SPI3_TX_DMA_IT_TC ) != RESET ) ||
234+ (DMA_GetITStatus (SPI3_TX_DMA_IT_TE ) != RESET );
235+
236+ DMA_ClearITPendingBit (SPI3_TX_DMA_IT_GL |
237+ SPI3_TX_DMA_IT_TC |
238+ SPI3_TX_DMA_IT_TE );
239+
240+ if (transfer_ended )
241+ {
242+ vTaskNotifyGiveFromISR (g_application_task_handle ,
243+ & higher_priority_task_woken );
244+ }
245+
246+ portYIELD_FROM_ISR (higher_priority_task_woken );
247+ }
248+
195249void spi_hw_transfer_dma (const uint8_t * tx_buf , size_t len )
196250{
197251 if ((tx_buf == NULL ) || (len == 0U ))
0 commit comments