From fe16f91cf14df47b5be561d8e77d3822ad30ae1e Mon Sep 17 00:00:00 2001 From: "Aubr.Cool" Date: Wed, 26 Jul 2017 08:27:38 +0800 Subject: [PATCH] [Bsp] stm32f107 spi drv : dma add irq --- bsp/stm32f107/drivers/rt_stm32f10x_spi.c | 273 +++++++++++++++++------ bsp/stm32f107/drivers/rt_stm32f10x_spi.h | 32 ++- 2 files changed, 234 insertions(+), 71 deletions(-) diff --git a/bsp/stm32f107/drivers/rt_stm32f10x_spi.c b/bsp/stm32f107/drivers/rt_stm32f10x_spi.c index 26d623535..124c41945 100644 --- a/bsp/stm32f107/drivers/rt_stm32f10x_spi.c +++ b/bsp/stm32f107/drivers/rt_stm32f10x_spi.c @@ -9,35 +9,28 @@ static struct rt_spi_ops stm32_spi_ops = xfer }; -#ifdef USING_SPI1 -static struct stm32_spi_bus stm32_spi_bus_1; -#endif /* #ifdef USING_SPI1 */ - -#ifdef USING_SPI2 -static struct stm32_spi_bus stm32_spi_bus_2; -#endif /* #ifdef USING_SPI2 */ - -#ifdef USING_SPI3 -static struct stm32_spi_bus stm32_spi_bus_3; -#endif /* #ifdef USING_SPI3 */ - //------------------ DMA ------------------ #ifdef SPI_USE_DMA static uint8_t dummy = 0xFF; -#endif +#endif /*SPI_USE_DMA*/ #ifdef SPI_USE_DMA static void DMA_Configuration(struct stm32_spi_bus * stm32_spi_bus, const void * send_addr, void * recv_addr, rt_size_t size) { DMA_InitTypeDef DMA_InitStructure; - DMA_ClearFlag(stm32_spi_bus->DMA_Channel_RX_FLAG_TC - | stm32_spi_bus->DMA_Channel_RX_FLAG_TE - | stm32_spi_bus->DMA_Channel_TX_FLAG_TC - | stm32_spi_bus->DMA_Channel_TX_FLAG_TE); + if(!stm32_spi_bus->dma) + { + return; + } + + DMA_ClearFlag(stm32_spi_bus->dma->priv_data->DMA_Channel_RX_FLAG_TC + | stm32_spi_bus->dma->priv_data->DMA_Channel_RX_FLAG_TE + | stm32_spi_bus->dma->priv_data->DMA_Channel_TX_FLAG_TC + | stm32_spi_bus->dma->priv_data->DMA_Channel_TX_FLAG_TE); /* RX channel configuration */ - DMA_Cmd(stm32_spi_bus->DMA_Channel_RX, DISABLE); + DMA_Cmd(stm32_spi_bus->dma->priv_data->DMA_Channel_RX, DISABLE); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(stm32_spi_bus->SPI->DR)); DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; @@ -60,12 +53,13 @@ static void DMA_Configuration(struct stm32_spi_bus * stm32_spi_bus, const void * DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; } - DMA_Init(stm32_spi_bus->DMA_Channel_RX, &DMA_InitStructure); + DMA_Init(stm32_spi_bus->dma->priv_data->DMA_Channel_RX, &DMA_InitStructure); - DMA_Cmd(stm32_spi_bus->DMA_Channel_RX, ENABLE); + DMA_ITConfig(stm32_spi_bus->dma->priv_data->DMA_Channel_RX, DMA_IT_TC, ENABLE); + DMA_Cmd(stm32_spi_bus->dma->priv_data->DMA_Channel_RX, ENABLE); /* TX channel configuration */ - DMA_Cmd(stm32_spi_bus->DMA_Channel_TX, DISABLE); + DMA_Cmd(stm32_spi_bus->dma->priv_data->DMA_Channel_TX, DISABLE); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(stm32_spi_bus->SPI->DR)); DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; @@ -88,18 +82,125 @@ static void DMA_Configuration(struct stm32_spi_bus * stm32_spi_bus, const void * DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; } - DMA_Init(stm32_spi_bus->DMA_Channel_TX, &DMA_InitStructure); + DMA_Init(stm32_spi_bus->dma->priv_data->DMA_Channel_TX, &DMA_InitStructure); - DMA_Cmd(stm32_spi_bus->DMA_Channel_TX, ENABLE); + DMA_ITConfig(stm32_spi_bus->dma->priv_data->DMA_Channel_TX, DMA_IT_TC, ENABLE); + DMA_Cmd(stm32_spi_bus->dma->priv_data->DMA_Channel_TX, ENABLE); } -#endif +#ifdef SPI1_USING_DMA +static const struct stm32_spi_dma_private dma1_priv = +{ + DMA1_Channel3, + DMA1_Channel2, + DMA1_FLAG_TC3, + DMA1_FLAG_TE3, + DMA1_FLAG_TC2, + DMA1_FLAG_TE2, + DMA1_Channel3_IRQn, + DMA1_Channel2_IRQn, + DMA1_FLAG_GL3, + DMA1_FLAG_GL2, +}; +static struct stm32_spi_dma dma1 = +{ + &dma1_priv, +}; +void DMA1_Channel2_IRQHandler(void) { + /* enter interrupt */ + rt_interrupt_enter(); + rt_event_send(&dma1.event, SPI_DMA_TX_DONE); + DMA_ClearFlag(dma1.priv_data->tx_gl_flag); + /* leave interrupt */ + rt_interrupt_leave(); +} +void DMA1_Channel3_IRQHandler(void) { + /* enter interrupt */ + rt_interrupt_enter(); + rt_event_send(&dma1.event, SPI_DMA_RX_DONE); + DMA_ClearFlag(dma1.priv_data->rx_gl_flag); + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /*SPI1_USING_DMA*/ +#ifdef SPI2_USING_DMA +static const struct stm32_spi_dma_private dma2_priv = +{ + DMA1_Channel5, + DMA1_Channel5, + DMA1_FLAG_TC5, + DMA1_FLAG_TE5, + DMA1_FLAG_TC4, + DMA1_FLAG_TE4, + DMA1_Channel5_IRQn, + DMA1_Channel4_IRQn, + DMA1_FLAG_GL5, + DMA1_FLAG_GL4, +}; +static struct stm32_spi_dma dma2 = +{ + &dma2_priv, +}; +void DMA1_Channel4_IRQHandler(void) { + /* enter interrupt */ + rt_interrupt_enter(); + rt_event_send(&dma2.event, SPI_DMA_TX_DONE); + DMA_ClearFlag(dma2.tx_gl_flag); + /* leave interrupt */ + rt_interrupt_leave(); +} +void DMA1_Channel5_IRQHandler(void) { + /* enter interrupt */ + rt_interrupt_enter(); + rt_event_send(&dma2.event, SPI_DMA_RX_DONE); + DMA_ClearFlag(dma2.priv_data->rx_gl_flag); + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /*SPI2_USING_DMA*/ +#ifdef SPI3_USING_DMA +static const struct stm32_spi_dma_private dma3_priv = +{ + DMA2_Channel2, + DMA2_Channel1, + DMA2_FLAG_TC2, + DMA2_FLAG_TE2, + DMA2_FLAG_TC1, + DMA2_FLAG_TE1, + DMA2_Channel2_IRQn, + DMA2_Channel1_IRQn, + DMA2_FLAG_GL2, + DMA2_FLAG_GL1, +}; +static struct stm32_spi_dma dma3 = +{ + &dma3_priv, +}; +void DMA2_Channel1_IRQHandler(void) { + /* enter interrupt */ + rt_interrupt_enter(); + rt_event_send(&dma3.event, SPI_DMA_TX_DONE); + DMA_ClearFlag(dma3.priv_data->tx_gl_flag); + /* leave interrupt */ + rt_interrupt_leave(); +} +void DMA2_Channel2_IRQHandler(void) { + /* enter interrupt */ + rt_interrupt_enter(); + rt_event_send(&dma3.event, SPI_DMA_RX_DONE); + DMA_ClearFlag(dma3.priv_data->rx_gl_flag); + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /*SPI3_USING_DMA*/ + +#endif /*SPI_USE_DMA*/ rt_inline uint16_t get_spi_BaudRatePrescaler(rt_uint32_t max_hz) { uint16_t SPI_BaudRatePrescaler; /* STM32F10x SPI MAX 18Mhz */ - if(max_hz >= SystemCoreClock/2 && SystemCoreClock/2 <= 18000000) + if(max_hz >= SystemCoreClock/2 && SystemCoreClock/2 <= 36000000) { SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; } @@ -208,27 +309,30 @@ static rt_uint32_t xfer(struct rt_spi_device* device, struct rt_spi_message* mes rt_uint32_t size = message->length; /* take CS */ - if(message->cs_take) + if(message->cs_take && stm32_spi_cs) { GPIO_ResetBits(stm32_spi_cs->GPIOx, stm32_spi_cs->GPIO_Pin); } - #ifdef SPI_USE_DMA - if(message->length > 32) + if( + (stm32_spi_bus->parent.parent.flag & (RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX)) && + stm32_spi_bus->dma && + message->length > 32) { if(config->data_width <= 8) { + rt_uint32_t ev = 0; DMA_Configuration(stm32_spi_bus, message->send_buf, message->recv_buf, message->length); SPI_I2S_DMACmd(SPI, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE); - while (DMA_GetFlagStatus(stm32_spi_bus->DMA_Channel_RX_FLAG_TC) == RESET - || DMA_GetFlagStatus(stm32_spi_bus->DMA_Channel_TX_FLAG_TC) == RESET); + rt_event_recv(&stm32_spi_bus->dma->event, SPI_DMA_COMPLETE, + RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &ev); SPI_I2S_DMACmd(SPI, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, DISABLE); + DMA_ITConfig(stm32_spi_bus->dma->priv_data->DMA_Channel_TX, DMA_IT_TC, DISABLE); + DMA_ITConfig(stm32_spi_bus->dma->priv_data->DMA_Channel_RX, DMA_IT_TC, DISABLE); } -// rt_memcpy(buffer,_spi_flash_buffer,DMA_BUFFER_SIZE); -// buffer += DMA_BUFFER_SIZE; } else -#endif +#endif /*SPI_USE_DMA*/ { if(config->data_width <= 8) { @@ -293,7 +397,7 @@ static rt_uint32_t xfer(struct rt_spi_device* device, struct rt_spi_message* mes } /* release CS */ - if(message->cs_release) + if(message->cs_release && stm32_spi_cs) { GPIO_SetBits(stm32_spi_cs->GPIOx, stm32_spi_cs->GPIO_Pin); } @@ -313,60 +417,97 @@ rt_err_t stm32_spi_register(SPI_TypeDef * SPI, struct stm32_spi_bus * stm32_spi, const char * spi_bus_name) { + rt_err_t res = RT_EOK; + NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); - + rt_uint32_t flags = 0; if(SPI == SPI1) { stm32_spi->SPI = SPI1; #ifdef SPI_USE_DMA - /* Enable the DMA1 Clock */ - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); - - stm32_spi->DMA_Channel_RX = DMA1_Channel2; - stm32_spi->DMA_Channel_TX = DMA1_Channel3; - stm32_spi->DMA_Channel_RX_FLAG_TC = DMA1_FLAG_TC2; - stm32_spi->DMA_Channel_RX_FLAG_TE = DMA1_FLAG_TE2; - stm32_spi->DMA_Channel_TX_FLAG_TC = DMA1_FLAG_TC3; - stm32_spi->DMA_Channel_TX_FLAG_TE = DMA1_FLAG_TE3; -#endif +#ifdef SPI1_USING_DMA + { + rt_event_init(&dma1.event, "spi1ev", RT_IPC_FLAG_FIFO); + stm32_spi->dma = &dma1; + /* rx dma interrupt config */ + NVIC_InitStructure.NVIC_IRQChannel = dma1.priv_data->tx_irq_ch; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + NVIC_InitStructure.NVIC_IRQChannel = dma1.priv_data->rx_irq_ch; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + /* Enable the DMA1 Clock */ + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); + flags |= RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX; + } +#else /*!SPI1_USING_DMA*/ + stm32_spi->dma = RT_NULL; +#endif /*SPI1_USING_DMA*/ +#endif /*SPI_USE_DMA*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); } else if(SPI == SPI2) { stm32_spi->SPI = SPI2; #ifdef SPI_USE_DMA - /* Enable the DMA1 Clock */ - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); - - stm32_spi->DMA_Channel_RX = DMA1_Channel4; - stm32_spi->DMA_Channel_TX = DMA1_Channel5; - stm32_spi->DMA_Channel_RX_FLAG_TC = DMA1_FLAG_TC4; - stm32_spi->DMA_Channel_RX_FLAG_TE = DMA1_FLAG_TE4; - stm32_spi->DMA_Channel_TX_FLAG_TC = DMA1_FLAG_TC5; - stm32_spi->DMA_Channel_TX_FLAG_TE = DMA1_FLAG_TE5; -#endif +#ifdef SPI2_USING_DMA + { + rt_event_init(&dma2.event, "spi2ev", RT_IPC_FLAG_FIFO); + stm32_spi->dma = &dma2; + /* rx dma interrupt config */ + NVIC_InitStructure.NVIC_IRQChannel = dma2.priv_data->tx_irq_ch; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + NVIC_InitStructure.NVIC_IRQChannel = dma2.priv_data->rx_irq_ch; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + /* Enable the DMA1 Clock */ + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); + flags |= RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX; + } +#else /*!SPI2_USING_DMA*/ + stm32_spi->dma = RT_NULL; +#endif /*SPI2_USING_DMA*/ +#endif /*SPI_USE_DMA*/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); } else if(SPI == SPI3) { stm32_spi->SPI = SPI3; #ifdef SPI_USE_DMA - /* Enable the DMA2 Clock */ - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); - - stm32_spi->DMA_Channel_RX = DMA2_Channel1; - stm32_spi->DMA_Channel_TX = DMA2_Channel2; - stm32_spi->DMA_Channel_RX_FLAG_TC = DMA2_FLAG_TC1; - stm32_spi->DMA_Channel_RX_FLAG_TE = DMA2_FLAG_TE1; - stm32_spi->DMA_Channel_TX_FLAG_TC = DMA2_FLAG_TC2; - stm32_spi->DMA_Channel_TX_FLAG_TE = DMA2_FLAG_TE2; -#endif +#ifdef SPI3_USING_DMA + { + rt_event_init(&dma3.event, "spi3ev", RT_IPC_FLAG_FIFO); + stm32_spi->dma = &dma3; + /* rx dma interrupt config */ + NVIC_InitStructure.NVIC_IRQChannel = dma3.priv_data->tx_irq_ch; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + NVIC_InitStructure.NVIC_IRQChannel = dma3.priv_data->rx_irq_ch; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + /* Enable the DMA1 Clock */ + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); + flags |= RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX; + } +#else /*!SPI3_USING_DMA*/ + stm32_spi->dma = RT_NULL; +#endif /*SPI3_USING_DMA*/ +#endif /*SPI_USE_DMA*/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); } else { return RT_ENOSYS; } + res = rt_spi_bus_register(&stm32_spi->parent, spi_bus_name, &stm32_spi_ops); + stm32_spi->parent.parent.flag |= flags; - return rt_spi_bus_register(&stm32_spi->parent, spi_bus_name, &stm32_spi_ops); + return res; } diff --git a/bsp/stm32f107/drivers/rt_stm32f10x_spi.h b/bsp/stm32f107/drivers/rt_stm32f10x_spi.h index 55834a1da..12a0836a2 100644 --- a/bsp/stm32f107/drivers/rt_stm32f10x_spi.h +++ b/bsp/stm32f107/drivers/rt_stm32f10x_spi.h @@ -8,19 +8,41 @@ #include "board.h" -//#define SPI_USE_DMA +#if defined(SPI1_USING_DMA) || defined(SPI2_USING_DMA) || defined(SPI3_USING_DMA) +#define SPI_USE_DMA +#endif /*defined(SPI1_USING_DMA) || defined(SPI2_USING_DMA) || defined(SPI3_USING_DMA)*/ -struct stm32_spi_bus -{ - struct rt_spi_bus parent; - SPI_TypeDef * SPI; #ifdef SPI_USE_DMA + +#define SPI_DMA_RX_DONE 0x01 +#define SPI_DMA_TX_DONE 0x02 +#define SPI_DMA_COMPLETE (SPI_DMA_RX_DONE | SPI_DMA_TX_DONE) + +struct stm32_spi_dma_private +{ DMA_Channel_TypeDef * DMA_Channel_TX; DMA_Channel_TypeDef * DMA_Channel_RX; uint32_t DMA_Channel_TX_FLAG_TC; uint32_t DMA_Channel_TX_FLAG_TE; uint32_t DMA_Channel_RX_FLAG_TC; uint32_t DMA_Channel_RX_FLAG_TE; + uint8_t tx_irq_ch; + uint8_t rx_irq_ch; + uint32_t tx_gl_flag; + uint32_t rx_gl_flag; +}; +struct stm32_spi_dma +{ + const struct stm32_spi_dma_private *priv_data; + struct rt_event event; +}; +#endif /*SPI_USE_DMA*/ +struct stm32_spi_bus +{ + struct rt_spi_bus parent; + SPI_TypeDef * SPI; +#ifdef SPI_USE_DMA + struct stm32_spi_dma *dma; #endif /* SPI_USE_DMA */ };