drv_uart.c
Go to the documentation of this file.
1 /*
2  drv_uart.c : UART support for STM32F103CB
3 
4  Adapted from https://github.com/multiwii/baseflight/blob/master/src/drv_uart.c
5 
6  This file is part of BreezySTM32.
7 
8  BreezySTM32 is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  BreezySTM32 is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with BreezySTM32. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 
23 #include <stdint.h>
24 #include <stdbool.h>
25 #include <stdlib.h>
26 
27 #include "stm32f10x_conf.h"
28 
29 #include "drv_serial.h"
30 #include "drv_gpio.h"
31 #include "drv_uart.h"
32 
34 
35 // USART1 - Telemetry (RX/TX by DMA)
36 uartPort_t *serialUSART1(uint32_t baudRate, portMode_t mode)
37 {
38  uartPort_t *s;
39  static volatile uint8_t rx1Buffer[UART1_RX_BUFFER_SIZE];
40  static volatile uint8_t tx1Buffer[UART1_TX_BUFFER_SIZE];
41  gpio_config_t gpio;
42  NVIC_InitTypeDef NVIC_InitStructure;
43 
44  s = &uartPort1;
45  s->port.vTable = uartVTable;
46 
47  s->port.baudRate = baudRate;
48 
49  s->port.rxBuffer = rx1Buffer;
50  s->port.txBuffer = tx1Buffer;
53 
56 
58  // USART1_TX PA9
59  // USART1_RX PA10
60  gpio.speed = Speed_2MHz;
61  gpio.pin = Pin_9;
62  gpio.mode = Mode_AF_PP;
63  if (mode & MODE_TX)
64  gpioInit(GPIOA, &gpio);
65  gpio.pin = Pin_10;
66  gpio.mode = Mode_IPU;
67  if (mode & MODE_RX)
68  gpioInit(GPIOA, &gpio);
69 
70  // DMA TX Interrupt
71  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
72  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
73  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
74  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
75  NVIC_Init(&NVIC_InitStructure);
76 
77  return s;
78 }
79 
80 serialPort_t *uartOpen(USART_TypeDef *USARTx, serialReceiveCallbackPtr callback, uint32_t baudRate, portMode_t mode)
81 {
82  DMA_InitTypeDef DMA_InitStructure;
83  USART_InitTypeDef USART_InitStructure;
84 
85  uartPort_t *s = NULL;
86 
87  if (!USARTx)
88  return NULL;
89 
90  if (USARTx == USART1)
91  s = serialUSART1(baudRate, mode);
92 
93  s->USARTx = USARTx;
94 
95  // common serial initialisation code should move to serialPort::init()
96  s->port.rxBufferHead = s->port.rxBufferTail = 0;
97  s->port.txBufferHead = s->port.txBufferTail = 0;
98  // callback for IRQ-based RX ONLY
99  s->port.callback = callback;
100  s->port.mode = mode;
101  s->port.baudRate = baudRate;
102 
103  USART_InitStructure.USART_BaudRate = baudRate;
104  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
105  if (mode & MODE_SBUS) {
106  USART_InitStructure.USART_StopBits = USART_StopBits_2;
107  USART_InitStructure.USART_Parity = USART_Parity_Even;
108  } else {
109  USART_InitStructure.USART_StopBits = USART_StopBits_1;
110  USART_InitStructure.USART_Parity = USART_Parity_No;
111  }
113  USART_InitStructure.USART_Mode = 0;
114  if (mode & MODE_RX)
115  USART_InitStructure.USART_Mode |= USART_Mode_Rx;
116  if (mode & MODE_TX)
117  USART_InitStructure.USART_Mode |= USART_Mode_Tx;
118  USART_Init(USARTx, &USART_InitStructure);
119  USART_Cmd(USARTx, ENABLE);
120 
121  DMA_StructInit(&DMA_InitStructure);
122  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USARTx->DR;
123  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
124  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
125  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
127  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
128  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
129 
130  // Receive DMA or IRQ
131  if (mode & MODE_RX) {
132  if (s->rxDMAChannel) {
133  DMA_InitStructure.DMA_BufferSize = s->port.rxBufferSize;
134  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
135  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
136  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)s->port.rxBuffer;
138  DMA_Init(s->rxDMAChannel, &DMA_InitStructure);
142  } else {
144  }
145  }
146 
147  // Transmit DMA or IRQ
148  if (mode & MODE_TX) {
149  if (s->txDMAChannel) {
150  DMA_InitStructure.DMA_BufferSize = s->port.txBufferSize;
151  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
152  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
154  DMA_Init(s->txDMAChannel, &DMA_InitStructure);
157  s->txDMAChannel->CNDTR = 0;
159  } else {
161  }
162  }
163 
164  return (serialPort_t *)s;
165 }
166 
167 void uartSetBaudRate(serialPort_t *instance, uint32_t baudRate)
168 {
169  USART_InitTypeDef USART_InitStructure;
170  uartPort_t *s = (uartPort_t *)instance;
171 
172  USART_InitStructure.USART_BaudRate = baudRate;
173  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
174  USART_InitStructure.USART_StopBits = USART_StopBits_1;
175  USART_InitStructure.USART_Parity = USART_Parity_No;
177  USART_InitStructure.USART_Mode = 0;
178  if (s->port.mode & MODE_RX)
179  USART_InitStructure.USART_Mode |= USART_Mode_Rx;
180  if (s->port.mode & MODE_TX)
181  USART_InitStructure.USART_Mode |= USART_Mode_Tx;
182  USART_Init(s->USARTx, &USART_InitStructure);
183 
184  s->port.baudRate = baudRate;
185 }
186 
188 {
189  (void)s;
190  (void)mode;
191  // not implemented.
192 }
193 
194 
195 static void uartStartTxDMA(uartPort_t *s)
196 {
197  s->txDMAChannel->CMAR = (uint32_t)&s->port.txBuffer[s->port.txBufferTail];
198  if (s->port.txBufferHead > s->port.txBufferTail) {
201  } else {
203  s->port.txBufferTail = 0;
204  }
205  s->txDMAEmpty = false;
207 }
208 
210 {
211  uartPort_t *s = (uartPort_t *)instance;
212  // FIXME always returns 1 or 0, not the amount of bytes waiting
213  if (s->rxDMAChannel)
214  return s->rxDMAChannel->CNDTR != s->rxDMAPos;
215  else
216  return s->port.rxBufferTail != s->port.rxBufferHead;
217 }
218 
219 // BUGBUG TODO TODO FIXME - What is the bug?
221 {
222  uartPort_t *s = (uartPort_t *)instance;
223  if (s->txDMAChannel)
224  return s->txDMAEmpty;
225  else
226  return s->port.txBufferTail == s->port.txBufferHead;
227 }
228 
229 uint8_t uartRead(serialPort_t *instance)
230 {
231  uint8_t ch;
232  uartPort_t *s = (uartPort_t *)instance;
233 
234  if (s->rxDMAChannel) {
235  ch = s->port.rxBuffer[s->port.rxBufferSize - s->rxDMAPos];
236  if (--s->rxDMAPos == 0)
237  s->rxDMAPos = s->port.rxBufferSize;
238  } else {
239  ch = s->port.rxBuffer[s->port.rxBufferTail];
240  s->port.rxBufferTail = (s->port.rxBufferTail + 1) % s->port.rxBufferSize;
241  }
242 
243  return ch;
244 }
245 
246 void uartWrite(serialPort_t *instance, uint8_t ch)
247 {
248  uartPort_t *s = (uartPort_t *)instance;
249  s->port.txBuffer[s->port.txBufferHead] = ch;
250  s->port.txBufferHead = (s->port.txBufferHead + 1) % s->port.txBufferSize;
251 
252  if (s->txDMAChannel) {
253  if (!(s->txDMAChannel->CCR & 1))
254  uartStartTxDMA(s);
255  } else {
257  }
258 }
259 
260 const struct serialPortVTable uartVTable[] = {
261  {
262  uartWrite,
264  uartRead,
267  uartSetMode,
268  }
269 };
270 
271 // Handlers
272 
273 // USART1 Tx DMA Handler
275 {
276  uartPort_t *s = &uartPort1;
279 
280  if (s->port.txBufferHead != s->port.txBufferTail)
281  uartStartTxDMA(s);
282  else
283  s->txDMAEmpty = true;
284 }
285 
286 // USART1 Tx IRQ Handler
288 {
289  uartPort_t *s = &uartPort1;
290  uint16_t SR = s->USARTx->SR;
291 
292  if (SR & USART_FLAG_TXE) {
293  if (s->port.txBufferTail != s->port.txBufferHead) {
294  s->USARTx->DR = s->port.txBuffer[s->port.txBufferTail];
295  s->port.txBufferTail = (s->port.txBufferTail + 1) % s->port.txBufferSize;
296  } else {
298  }
299  }
300 }
const struct serialPortVTable uartVTable[]
Definition: drv_uart.c:260
#define DMA_MemoryInc_Enable
uint32_t DMA_MemoryInc
Definition: stm32f4xx_dma.h:76
uint32_t txBufferSize
Definition: drv_serial.h:41
#define DMA1_IT_TC4
volatile uint8_t * txBuffer
Definition: drv_serial.h:43
void NVIC_Init(NVIC_InitTypeDef *NVIC_InitStruct)
Initializes the NVIC peripheral according to the specified parameters in the NVIC_InitStruct.
#define DMA_Priority_Medium
GPIO_Mode mode
Definition: drv_gpio.h:63
portMode_t
Definition: drv_serial.h:26
uartPort_t * serialUSART1(uint32_t baudRate, portMode_t mode)
Definition: drv_uart.c:36
volatile uint8_t * rxBuffer
Definition: drv_serial.h:42
uint32_t rxBufferSize
Definition: drv_serial.h:40
GPIO_Speed speed
Definition: drv_gpio.h:64
#define USART_Parity_No
DMA Init structure definition.
Definition: stm32f4xx_dma.h:54
uint16_t USART_HardwareFlowControl
const struct serialPortVTable * vTable
Definition: drv_serial.h:35
Universal Synchronous Asynchronous Receiver Transmitter.
Definition: stm32f4xx.h:1710
#define USART_Mode_Tx
#define DMA_MemoryDataSize_Byte
#define GPIOA
Definition: stm32f4xx.h:2110
static uartPort_t uartPort1
Definition: drv_uart.c:33
#define DMA1_Channel4
Definition: stm32f10x.h:1434
void DMA_DeInit(DMA_Stream_TypeDef *DMAy_Streamx)
Deinitialize the DMAy Streamx registers to their default reset values.
#define DMA_PeripheralInc_Disable
XmlRpcServer s
USART_TypeDef * USARTx
Definition: drv_uart.h:48
uint32_t DMA_MemoryDataSize
Definition: stm32f4xx_dma.h:82
void USART1_IRQHandler(void)
Definition: drv_uart.c:287
void DMA_Init(DMA_Stream_TypeDef *DMAy_Streamx, DMA_InitTypeDef *DMA_InitStruct)
Initializes the DMAy Streamx according to the specified parameters in the DMA_InitStruct structure...
#define USART_Mode_Rx
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
Enables or disables the High Speed APB (APB2) peripheral clock.
static void uartStartTxDMA(uartPort_t *s)
Definition: drv_uart.c:195
#define UART1_TX_BUFFER_SIZE
Definition: drv_uart.h:27
uint32_t DMA_DIR
Definition: stm32f4xx_dma.h:65
uint32_t DMA_PeripheralInc
Definition: stm32f4xx_dma.h:73
uint32_t rxBufferTail
Definition: drv_serial.h:45
#define USART_IT_TXE
void USART_ITConfig(USART_TypeDef *USARTx, uint16_t USART_IT, FunctionalState NewState)
Enables or disables the specified USART interrupts.
void gpioInit(GPIO_TypeDef *gpio, gpio_config_t *config)
Definition: drv_gpio.c:56
void DMA_ClearITPendingBit(DMA_Stream_TypeDef *DMAy_Streamx, uint32_t DMA_IT)
Clears the DMAy Streamx&#39;s interrupt pending bits.
void DMA_ITConfig(DMA_Stream_TypeDef *DMAy_Streamx, uint32_t DMA_IT, FunctionalState NewState)
Enables or disables the specified DMAy Streamx interrupts.
uint32_t DMA_PeripheralDataSize
Definition: stm32f4xx_dma.h:79
#define DMA_M2M_Disable
#define USART_DMAReq_Tx
bool txDMAEmpty
Definition: drv_uart.h:46
__IO uint32_t CMAR
Definition: stm32f10x.h:803
#define USART_HardwareFlowControl_None
__IO uint16_t SR
Definition: stm32f4xx.h:1712
#define USART_WordLength_8b
uint32_t DMA_MemoryBaseAddr
Definition: stm32f10x_dma.h:54
uint16_t pin
Definition: drv_gpio.h:62
void USART_DMACmd(USART_TypeDef *USARTx, uint16_t USART_DMAReq, FunctionalState NewState)
Enables or disables the USART&#39;s DMA interface.
#define USART1
Definition: stm32f4xx.h:2080
#define USART_StopBits_2
void DMA_StructInit(DMA_InitTypeDef *DMA_InitStruct)
Fills each DMA_InitStruct member with its default value.
void(* serialReceiveCallbackPtr)(uint16_t data)
Definition: drv_serial.h:24
__IO uint16_t DR
Definition: stm32f4xx.h:1714
uint32_t rxBufferHead
Definition: drv_serial.h:44
#define USART_DMAReq_Rx
void DMA_Cmd(DMA_Stream_TypeDef *DMAy_Streamx, FunctionalState NewState)
Enables or disables the specified DMAy Streamx.
uint32_t DMA_PeripheralBaseAddr
Definition: stm32f4xx_dma.h:59
uint32_t DMA_M2M
Definition: stm32f10x_dma.h:83
DMA_Channel_TypeDef * rxDMAChannel
Definition: drv_uart.h:39
Definition: drv_gpio.h:51
uint16_t USART_WordLength
#define DMA_DIR_PeripheralSRC
uint8_t uartRead(serialPort_t *instance)
Definition: drv_uart.c:229
void DMA1_Channel4_IRQHandler(void)
Definition: drv_uart.c:274
bool isUartTransmitBufferEmpty(serialPort_t *instance)
Definition: drv_uart.c:220
void uartSetMode(serialPort_t *s, portMode_t mode)
Definition: drv_uart.c:187
uint32_t rxDMAPos
Definition: drv_uart.h:45
uint32_t baudRate
Definition: drv_serial.h:38
void USART_Init(USART_TypeDef *USARTx, USART_InitTypeDef *USART_InitStruct)
Initializes the USARTx peripheral according to the specified parameters in the USART_InitStruct ...
#define DMA_DIR_PeripheralDST
#define DMA1_Channel5
Definition: stm32f10x.h:1435
#define DMA_Mode_Normal
uint16_t DMA_GetCurrDataCounter(DMA_Stream_TypeDef *DMAy_Streamx)
Returns the number of remaining data units in the current DMAy Streamx transfer.
void USART_Cmd(USART_TypeDef *USARTx, FunctionalState NewState)
Enables or disables the specified USART peripheral.
#define USART_IT_RXNE
serialPort_t * uartOpen(USART_TypeDef *USARTx, serialReceiveCallbackPtr callback, uint32_t baudRate, portMode_t mode)
Definition: drv_uart.c:80
void uartWrite(serialPort_t *instance, uint8_t ch)
Definition: drv_uart.c:246
serialPort_t port
Definition: drv_uart.h:36
serialReceiveCallbackPtr callback
Definition: drv_serial.h:50
#define DMA_PeripheralDataSize_Byte
#define UART1_RX_BUFFER_SIZE
Definition: drv_uart.h:26
#define USART_FLAG_TXE
uint32_t DMA_Mode
Definition: stm32f4xx_dma.h:85
#define NULL
Definition: usbd_def.h:50
#define USART_StopBits_1
portMode_t mode
Definition: drv_serial.h:37
__IO uint32_t CCR
Definition: stm32f10x.h:800
#define USART_Parity_Even
uint32_t DMA_BufferSize
Definition: stm32f4xx_dma.h:69
__IO uint32_t CNDTR
Definition: stm32f10x.h:801
uint32_t DMA_Priority
Definition: stm32f4xx_dma.h:90
#define DMA_Mode_Circular
uint32_t txBufferTail
Definition: drv_serial.h:47
void uartSetBaudRate(serialPort_t *instance, uint32_t baudRate)
Definition: drv_uart.c:167
uint32_t txBufferHead
Definition: drv_serial.h:46
uint8_t uartTotalBytesWaiting(serialPort_t *instance)
Definition: drv_uart.c:209
USART Init Structure definition.
void DMA_SetCurrDataCounter(DMA_Stream_TypeDef *DMAy_Streamx, uint16_t Counter)
Writes the number of data units to be transferred on the DMAy Streamx.
#define DMA_IT_TC
DMA_Channel_TypeDef * txDMAChannel
Definition: drv_uart.h:40


rosflight_firmware
Author(s): Daniel Koch , James Jackson
autogenerated on Thu Oct 24 2019 03:17:18