diff --git a/f4/usart/include/usart3.h b/f4/usart/include/usart3.h new file mode 100644 index 0000000000000000000000000000000000000000..7d659d93cd037e0225abdc12bc6bd103c1a8187e --- /dev/null +++ b/f4/usart/include/usart3.h @@ -0,0 +1,22 @@ +#ifndef USART3_F4_H +#define USART3_F4_H + +#include "stm32f4xx_hal.h" +#include "usart_common.h" +#include "comm.h" + +/* public functions */ +void usart3_init(TComm *comm_dev,UART_InitTypeDef *conf,TUSART_IRQ_Priorities *priorities); +void usart3_config(TComm *comm_dev,UART_InitTypeDef *conf); +void usart3_set_priorities(TComm *comm_dev,TUSART_IRQ_Priorities *priorities); +/* IRQ functions */ +unsigned char usart3_send_irq(unsigned char first_byte); +unsigned char usart3_enable_tx_irq(void); +unsigned char usart3_receive_irq(void); +unsigned char usart3_cancel_receive_irq(void); +/* DMA functions */ +unsigned char usart3_send_dma(unsigned char *data,unsigned short int length); +unsigned char usart3_receive_dma(unsigned char *data,unsigned short int length); +unsigned char usart3_cancel_receive_dma(void); + +#endif diff --git a/f4/usart/src/usart3.c b/f4/usart/src/usart3.c new file mode 100644 index 0000000000000000000000000000000000000000..24a1f696fa387bd43805a2657da20d58e4500807 --- /dev/null +++ b/f4/usart/src/usart3.c @@ -0,0 +1,342 @@ +#include "usart3.h" + +#define USART USART3 +#define USART_ENABLE_CLK __HAL_RCC_USART3_CLK_ENABLE() +#define USART_IRQn USART3_IRQn +#define USART_IRQHandler USART3_IRQHandler + +#define USART_TX_PIN GPIO_PIN_10 +#define USART_TX_GPIO_PORT GPIOB +#define USART_ENABLE_TX_GPIO_CLK __HAL_RCC_GPIOB_CLK_ENABLE() + +#define USART_RX_PIN GPIO_PIN_11 +#define USART_RX_GPIO_PORT GPIOB +#define USART_ENABLE_RX_GPIO_CLK __HAL_RCC_GPIOB_CLK_ENABLE() + +/* DMA configuration */ +#define USART_DMA_CHANNEL DMA_CHANNEL_4 +#define USART_ENABLE_DMA_CLK __HAL_RCC_DMA1_CLK_ENABLE() + +#define USART_TX_DMA_STREAM DMA1_Stream3 +#define USART_RX_DMA_STREAM DMA1_Stream1 + +#define USART_DMA_TX_IRQn DMA1_Stream3_IRQn +#define USART_DMA_RX_IRQn DMA1_Stream1_IRQn +#define USART_DMA_TX_IRQHandler DMA1_Stream3_IRQHandler +#define USART_DMA_RX_IRQHandler DMA1_Stream1_IRQHandler + +// private variables +UART_HandleTypeDef Uart3Handle; +DMA_HandleTypeDef usart3_hdma_tx; +DMA_HandleTypeDef usart3_hdma_rx; +TComm *usart3_comm_dev; + +// interrupt handlers +void USART_IRQHandler(void) +{ + unsigned char data,ret; + uint32_t source; + + if(__HAL_UART_GET_FLAG(&Uart3Handle, UART_FLAG_RXNE) != RESET) + { + if(__HAL_UART_GET_IT_SOURCE(&Uart3Handle, UART_IT_RXNE) !=RESET) + { + __HAL_UART_CLEAR_FLAG(&Uart3Handle,UART_FLAG_RXNE); + data=(uint8_t)(Uart3Handle.Instance->DR & (uint8_t)0x00FF); + // call the reception function + if(!comm_do_irq_receive(usart3_comm_dev,data)) + __HAL_UART_DISABLE_IT(&Uart3Handle, UART_IT_RXNE); + } + } + if(__HAL_UART_GET_FLAG(&Uart3Handle, UART_FLAG_TC) != RESET) + { + if(__HAL_UART_GET_IT_SOURCE(&Uart3Handle, UART_IT_TC) !=RESET) + { + __HAL_UART_CLEAR_FLAG(&Uart3Handle,UART_FLAG_TC); + ret=comm_do_irq_send(usart3_comm_dev,&data); + if(ret==0x01) + Uart3Handle.Instance->DR=data; + else if(ret==0x00) + __HAL_UART_DISABLE_IT(&Uart3Handle, UART_IT_TC); + } + } + if(__HAL_UART_GET_FLAG(&Uart3Handle, UART_FLAG_PE) != RESET)// parity error + { + if(__HAL_UART_GET_IT_SOURCE(&Uart3Handle, UART_IT_PE) !=RESET) + { + __HAL_UART_CLEAR_PEFLAG(&Uart3Handle); + } + } + source=__HAL_UART_GET_IT_SOURCE(&Uart3Handle, UART_IT_ERR); + if(__HAL_UART_GET_FLAG(&Uart3Handle, UART_FLAG_FE) != RESET)// frame error + { + if(source !=RESET) + { + __HAL_UART_CLEAR_FEFLAG(&Uart3Handle); + } + } + if(__HAL_UART_GET_FLAG(&Uart3Handle, UART_FLAG_NE) != RESET)// noise error + { + if(source !=RESET) + { + __HAL_UART_CLEAR_NEFLAG(&Uart3Handle); + } + } + if(__HAL_UART_GET_FLAG(&Uart3Handle, UART_FLAG_ORE) != RESET)// overrun error + { + if(source !=RESET) + { + __HAL_UART_CLEAR_OREFLAG(&Uart3Handle); + } + } +} + +void USART_DMA_TX_IRQHandler(void) +{ + if(__HAL_DMA_GET_FLAG(Uart3Handle.hdmatx,__HAL_DMA_GET_TE_FLAG_INDEX(Uart3Handle.hdmatx)) != RESET) + { + if(__HAL_DMA_GET_IT_SOURCE(Uart3Handle.hdmatx, DMA_IT_TE) != RESET) + { + /* Disable the transfer error interrupt */ + __HAL_DMA_DISABLE_IT(Uart3Handle.hdmatx, DMA_IT_TE); + /* Clear the transfer error flag */ + __HAL_DMA_CLEAR_FLAG(Uart3Handle.hdmatx, __HAL_DMA_GET_TE_FLAG_INDEX(Uart3Handle.hdmatx)); + } + } + if(__HAL_DMA_GET_FLAG(Uart3Handle.hdmatx,__HAL_DMA_GET_TC_FLAG_INDEX(Uart3Handle.hdmatx)) != RESET) + { + if(__HAL_DMA_GET_IT_SOURCE(Uart3Handle.hdmatx, DMA_IT_TC) != RESET) + { + /* Disable the half transfer interrupt */ + __HAL_DMA_DISABLE_IT(Uart3Handle.hdmatx, DMA_IT_TC); + /* Clear the transfer complete flag */ + __HAL_DMA_CLEAR_FLAG(Uart3Handle.hdmatx, __HAL_DMA_GET_TC_FLAG_INDEX(Uart3Handle.hdmatx)); + CLEAR_BIT(Uart3Handle.Instance->CR3, (USART_CR3_DMAT | USART_CR3_DMAR)); + HAL_DMA_Abort(Uart3Handle.hdmatx); + // call the user function + comm_do_dma_send(usart3_comm_dev); + } + } + if(__HAL_DMA_GET_FLAG(Uart3Handle.hdmatx, __HAL_DMA_GET_HT_FLAG_INDEX(Uart3Handle.hdmatx)) != RESET) + { + if(__HAL_DMA_GET_IT_SOURCE(Uart3Handle.hdmatx, DMA_IT_HT) != RESET) + { + /* Disable the half transfer interrupt */ + __HAL_DMA_DISABLE_IT(Uart3Handle.hdmatx, DMA_IT_HT); + /* Clear the half transfer complete flag */ + __HAL_DMA_CLEAR_FLAG(Uart3Handle.hdmatx, __HAL_DMA_GET_HT_FLAG_INDEX(Uart3Handle.hdmatx)); + } + } +} + +void USART_DMA_RX_IRQHandler(void) +{ + if(__HAL_DMA_GET_FLAG(Uart3Handle.hdmarx,__HAL_DMA_GET_TE_FLAG_INDEX(Uart3Handle.hdmarx)) != RESET) + { + if(__HAL_DMA_GET_IT_SOURCE(Uart3Handle.hdmarx, DMA_IT_TE) != RESET) + { + /* Disable the transfer error interrupt */ + __HAL_DMA_DISABLE_IT(Uart3Handle.hdmarx, DMA_IT_TE); + /* Clear the transfer error flag */ + __HAL_DMA_CLEAR_FLAG(Uart3Handle.hdmarx, __HAL_DMA_GET_TE_FLAG_INDEX(Uart3Handle.hdmarx)); + } + } + if(__HAL_DMA_GET_FLAG(Uart3Handle.hdmarx,__HAL_DMA_GET_TC_FLAG_INDEX(Uart3Handle.hdmarx)) != RESET) + { + if(__HAL_DMA_GET_IT_SOURCE(Uart3Handle.hdmarx, DMA_IT_TC) != RESET) + { + /* Disable the transfer complete interrupt */ + __HAL_DMA_DISABLE_IT(Uart3Handle.hdmarx, DMA_IT_TC); + /* Clear the transfer complete flag */ + __HAL_DMA_CLEAR_FLAG(Uart3Handle.hdmarx, __HAL_DMA_GET_TC_FLAG_INDEX(Uart3Handle.hdmarx)); + CLEAR_BIT(Uart3Handle.Instance->CR3, (USART_CR3_DMAT | USART_CR3_DMAR)); + HAL_DMA_Abort(Uart3Handle.hdmarx); + // call the user function + comm_do_dma_receive(usart3_comm_dev); + } + } + if(__HAL_DMA_GET_FLAG(Uart3Handle.hdmarx, __HAL_DMA_GET_HT_FLAG_INDEX(Uart3Handle.hdmarx)) != RESET) + { + if(__HAL_DMA_GET_IT_SOURCE(Uart3Handle.hdmarx, DMA_IT_HT) != RESET) + { + /* Disable the half transfer interrupt */ + __HAL_DMA_DISABLE_IT(Uart3Handle.hdmarx, DMA_IT_HT); + /* Clear the half transfer complete flag */ + __HAL_DMA_CLEAR_FLAG(Uart3Handle.hdmarx, __HAL_DMA_GET_HT_FLAG_INDEX(Uart3Handle.hdmarx)); + } + } +} + +/* public functions*/ +void usart3_init(TComm *comm_dev,UART_InitTypeDef *conf,TUSART_IRQ_Priorities *priorities) +{ + GPIO_InitTypeDef GPIO_InitStructure; + + /* Enable GPIO clock */ + USART_ENABLE_TX_GPIO_CLK; + USART_ENABLE_RX_GPIO_CLK; + USART_ENABLE_DMA_CLK; + // configure the GPIO pins + + /* Configure USART Tx and Rx as alternate function push-pull */ + GPIO_InitStructure.Pin = USART_TX_PIN; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Alternate = GPIO_AF7_USART3; + HAL_GPIO_Init(USART_TX_GPIO_PORT, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = USART_RX_PIN; + HAL_GPIO_Init(USART_RX_GPIO_PORT, &GPIO_InitStructure); + + USART_ENABLE_CLK; + + Uart3Handle.Instance = USART; + usart3_config(comm_dev,conf); + + if(comm_dev->use_dma) + { + // configure the DMA channels + usart3_hdma_tx.Instance = USART_RX_DMA_STREAM; + usart3_hdma_tx.Init.Channel = USART_DMA_CHANNEL; + usart3_hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + usart3_hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE; + usart3_hdma_tx.Init.MemInc = DMA_MINC_ENABLE; + usart3_hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + usart3_hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + usart3_hdma_tx.Init.Mode = DMA_NORMAL; + usart3_hdma_tx.Init.Priority = DMA_PRIORITY_LOW; + usart3_hdma_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + + HAL_DMA_Init(&usart3_hdma_tx); + + /* Associate the initialized DMA handle to the UART handle */ + __HAL_LINKDMA(&Uart3Handle, hdmatx, usart3_hdma_tx); + + /* Configure the DMA handler for reception process */ + usart3_hdma_rx.Instance = USART_RX_DMA_STREAM; + usart3_hdma_rx.Init.Channel = USART_DMA_CHANNEL; + usart3_hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + usart3_hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE; + usart3_hdma_rx.Init.MemInc = DMA_MINC_ENABLE; + usart3_hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + usart3_hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + usart3_hdma_rx.Init.Mode = DMA_NORMAL; + usart3_hdma_rx.Init.Priority = DMA_PRIORITY_HIGH; + usart3_hdma_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + + HAL_DMA_Init(&usart3_hdma_rx); + + /* Associate the initialized DMA handle to the the UART handle */ + __HAL_LINKDMA(&Uart3Handle, hdmarx, usart3_hdma_rx); + } + usart3_set_priorities(comm_dev,priorities); + + /* Initialize the comm structure */ + comm_dev->send_irq=usart3_send_irq; + comm_dev->enable_tx_irq=usart3_enable_tx_irq; + comm_dev->receive_irq=usart3_receive_irq; + comm_dev->cancel_receive_irq=usart3_cancel_receive_irq; + if(comm_dev->use_dma) + { + comm_dev->send_dma=usart3_send_dma; + comm_dev->receive_dma=usart3_receive_dma; + comm_dev->cancel_receive_dma=usart3_cancel_receive_dma; + } + comm_dev->irq_send_cb=0x00000000; + comm_dev->irq_receive_cb=0x00000000; + comm_dev->dma_send_cb=0x00000000; + comm_dev->dma_receive_cb=0x00000000; + + /* initialize internal variables */ + usart3_comm_dev=comm_dev; +} + +void usart3_config(TComm *comm_dev,UART_InitTypeDef *conf) +{ + Uart3Handle.Init.BaudRate = conf->BaudRate; + Uart3Handle.Init.WordLength = conf->WordLength; + Uart3Handle.Init.StopBits = conf->StopBits; + Uart3Handle.Init.Parity = conf->Parity; + Uart3Handle.Init.Mode = conf->Mode; + Uart3Handle.Init.HwFlowCtl = conf->HwFlowCtl; + Uart3Handle.Init.OverSampling = conf->OverSampling; + HAL_UART_Init(&Uart3Handle); +} + +void usart3_set_priorities(TComm *comm_dev,TUSART_IRQ_Priorities *priorities) +{ + HAL_NVIC_SetPriority(USART_IRQn, priorities->irq_priority,priorities->irq_subpriority); + HAL_NVIC_EnableIRQ(USART_IRQn); + if(comm_dev->use_dma) + { + HAL_NVIC_SetPriority(USART_DMA_TX_IRQn, priorities->dma_tx_priority,priorities->dma_tx_subpriority); + HAL_NVIC_EnableIRQ(USART_DMA_TX_IRQn); + HAL_NVIC_SetPriority(USART_DMA_RX_IRQn, priorities->dma_rx_priority,priorities->dma_rx_subpriority); + HAL_NVIC_EnableIRQ(USART_DMA_RX_IRQn); + } +} + +/* IRQ functions */ +unsigned char usart3_send_irq(unsigned char first_byte) +{ + __HAL_UART_CLEAR_FLAG(&Uart3Handle,UART_FLAG_TC); + __HAL_UART_ENABLE_IT(&Uart3Handle, UART_IT_TC); + Uart3Handle.Instance->DR=first_byte; + + return 0x00; +} + +unsigned char usart3_enable_tx_irq(void) +{ + __HAL_UART_CLEAR_FLAG(&Uart3Handle,UART_FLAG_TC); + __HAL_UART_ENABLE_IT(&Uart3Handle, UART_IT_TC); + + return 0x00; +} + +unsigned char usart3_receive_irq(void) +{ + /* enable the rx interrupt */ + __HAL_UART_ENABLE_IT(&Uart3Handle, UART_IT_RXNE); + + return 0x00; +} + +unsigned char usart3_cancel_receive_irq(void) +{ + /* disable the rx interrupt */ + __HAL_UART_DISABLE_IT(&Uart3Handle, UART_IT_RXNE); + + return 0x00; +} + +/* DMA functions */ +unsigned char usart3_send_dma(unsigned char *data,unsigned short int length) +{ + HAL_DMA_Start_IT(Uart3Handle.hdmatx,(uint32_t)data,(uint32_t)&Uart3Handle.Instance->DR,length); + /* Clear the TC flag in the SR register by writing 0 to it */ + __HAL_UART_CLEAR_FLAG(&Uart3Handle,UART_FLAG_TC); + /* Enable the DMA transfer for transmit request by setting the DMAT bit + in the UART CR3 register */ + SET_BIT(Uart3Handle.Instance->CR3, USART_CR3_DMAT); + + return 0x00; +} + +unsigned char usart3_receive_dma(unsigned char *data,unsigned short int length) +{ + HAL_DMA_Start_IT(Uart3Handle.hdmarx,(uint32_t)&Uart3Handle.Instance->DR,(uint32_t)data,length); + SET_BIT(Uart3Handle.Instance->CR3, USART_CR3_DMAR); + + return 0x00; +} + +unsigned char usart3_cancel_receive_dma(void) +{ + CLEAR_BIT(Uart3Handle.Instance->CR3, (USART_CR3_DMAT | USART_CR3_DMAR)); + HAL_DMA_Abort(Uart3Handle.hdmarx); + + return 0x00; +} +