uart.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, James Jackson
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * * Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "uart.h"
33 
36 
38 {}
39 
40 
41 void UART::init(const uart_hardware_struct_t *conf, uint32_t baudrate, uart_mode_t mode)
42 {
43  receive_CB_ = nullptr;
44  c_ = conf;//Save the configuration
45 
46  //initialize pins
51 
52 
53  //Save the pointer, for callbacks
54  if (c_->dev == USART1)
55  {
56  UART1Ptr = this;
57  }
58  if (c_->dev == USART3)
59  {
60  UART3Ptr = this;
61  }
62 
63  init_UART(baudrate, mode);
64  init_DMA();
65  init_NVIC();
66 }
67 
68 void UART::init_UART(uint32_t baudrate, uart_mode_t mode)
69 {
70  // Configure the device
71  USART_Cmd(c_->dev, DISABLE);//Disable the usart device for configuration
72 
73  USART_InitTypeDef USART_InitStruct;
74  USART_InitStruct.USART_BaudRate = baudrate;
75 
76  switch (mode)
77  {
78  case MODE_8N1:
79  default:
80  USART_InitStruct.USART_WordLength = USART_WordLength_8b;
81  USART_InitStruct.USART_Parity = USART_Parity_No;
82  USART_InitStruct.USART_StopBits = USART_StopBits_1;
83  break;
84  case MODE_8E2:
85  USART_InitStruct.USART_WordLength = USART_WordLength_8b;
86  USART_InitStruct.USART_Parity = USART_Parity_Even;
87  USART_InitStruct.USART_StopBits = USART_StopBits_2;
88  break;
89  }
90 
92  USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//Set to both recieve and send
93  USART_Init(c_->dev, &USART_InitStruct);
94  //USART_OverSampling8Cmd(c_->dev, ENABLE);//Please don't break anything
95 
96  // Throw interrupts on byte receive
97  USART_ITConfig(c_->dev, USART_IT_RXNE, ENABLE);//enable interupts on recieve
98  USART_Cmd(c_->dev, ENABLE);//reenable the usart
99 }
100 
102 {
103  DMA_InitTypeDef DMA_InitStructure;
104 
105  // Common DMA Configuration
106  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable ;
108  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ;
109  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
110 
111  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
114  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
115 
116  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
117  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
118  DMA_InitStructure.DMA_PeripheralBaseAddr = reinterpret_cast<uint32_t>(&(c_->dev->DR));
119  DMA_InitStructure.DMA_Channel = c_->DMA_Channel;
120 
121  // Configure the Tx DMA
123  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
124  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
125  DMA_InitStructure.DMA_BufferSize = TX_BUFFER_SIZE;
126  DMA_InitStructure.DMA_Memory0BaseAddr = reinterpret_cast<uint32_t>(tx_buffer_);
127  DMA_Init(c_->Tx_DMA_Stream, &DMA_InitStructure);
128 
129  // Configure the Rx DMA
131  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
132  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
133  DMA_InitStructure.DMA_BufferSize = RX_BUFFER_SIZE;
134  DMA_InitStructure.DMA_Memory0BaseAddr = reinterpret_cast<uint32_t>(rx_buffer_);
135  DMA_Init(c_->Rx_DMA_Stream, &DMA_InitStructure);
136 
137  // Turn on the Rx DMA Stream
139 
140  // Hook up the DMA to the uart
143 
144  // Turn on the transfer complete interrupt source from the DMA
147 
148  // Initialize the Circular Buffers
149  // set the buffer pointers to where the DMA is starting (starts at 256 and counts down)
152  tx_buffer_head_ = 0;
153  tx_buffer_tail_ = 0;
154 
155  memset(rx_buffer_, 0, RX_BUFFER_SIZE);
156  memset(tx_buffer_, 0, TX_BUFFER_SIZE);
157 }
158 
159 
161 {
162  // Configure the Interrupt
163  NVIC_InitTypeDef NVIC_InitStruct;
164  NVIC_InitStruct.NVIC_IRQChannel = c_->USART_IRQn;
165  NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
166  NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
167  NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
168  NVIC_Init(&NVIC_InitStruct);
169 
170  NVIC_InitStruct.NVIC_IRQChannel = c_->Tx_DMA_IRQn;
171  NVIC_Init(&NVIC_InitStruct);
172 
173  NVIC_InitStruct.NVIC_IRQChannel = c_->Rx_DMA_IRQn;
174  NVIC_Init(&NVIC_InitStruct);
175 }
176 
177 
178 void UART::write(const uint8_t *ch, uint8_t len)
179 {
180  // Put Data on the tx_buffer
181  for (int i = 0; i < len ; i++)
182  {
185  }
187  {
188  startDMA();
189  }
190 // this->flush();//testing
191 }
192 
193 
195 {
196  // Set the start of the transmission to the oldest data
197  c_->Tx_DMA_Stream->M0AR = reinterpret_cast<uint32_t>(&tx_buffer_[tx_buffer_tail_]);
199  {
200  // Set the length of the transmission to the data on the buffer
201  // if contiguous, this is easy
204  }
205  else
206  {
207  // We will have to send the data in two groups, first the tail,
208  // then the head we will do later
210  tx_buffer_tail_ = 0;
211  }
212  // Start the Transmission
214 }
215 
217 {
218  uint8_t byte = 0;
219  // pull the next byte off the array
220  // (the head counts down, because CNTR counts down)
222  {
223  // read a new byte and decrement the tail
225  if (--rx_buffer_tail_ == 0)
226  {
227  // wrap to the top if at the bottom
229  }
230  }
231  return byte;
232 }
233 
234 
235 void UART::put_byte(uint8_t ch)
236 {
237  write(&ch, 1);
238 }
239 
241 {
242  // Remember, the DMA CNDTR counts down
245  {
246  // Easy, becasue it's contiguous
248  }
249  else if (rx_buffer_head_ > rx_buffer_tail_)
250  {
251  // Add the parts on either end of the buffer
252  // I'm pretty sure this is wrong
254  }
255  else
256  {
257  return 0;
258  }
259 }
260 
262 {
263  // Remember, the DMA CNDTR counts down
266  {
268  }
269  else
271 }
272 
273 bool UART::set_mode(uint32_t baud, uart_mode_t mode)
274 {
275  init_UART(baud, mode);
276  return true;
277 }
278 
280 {
282 }
283 
285 {
286  uint32_t timeout = 100000;
287  while (!tx_buffer_empty() && --timeout);
288  if (timeout)
289  return true;
290  else
291  return false;
292 }
293 
295 {
296  // DMA took care of putting the data on the buffer
297  // Just call the callback until we have no more data
298  // Update the head position from the DMA
300  if (receive_CB_ != nullptr)
301  {
303  {
304  // read a new byte and decrement the tail
305  uint8_t byte = rx_buffer_[RX_BUFFER_SIZE - rx_buffer_tail_];
306  receive_CB_(byte);
307  if (--rx_buffer_tail_ == 0)
308  {
309  // wrap to the top if at the bottom
311  }
312  }
313  }
314 }
315 
317 {
318  // If there is more data to be sent
320  {
321  startDMA();
322  }
323 }
324 
325 void UART::register_rx_callback(void (*cb)(uint8_t data))
326 {
327  receive_CB_ = cb;
328 }
329 
331 {
332  receive_CB_ = nullptr;
333 }
334 
335 extern "C"
336 {
337 
338  void USART1_IRQHandler(void)
339  {
340  UART1Ptr->DMA_Rx_IRQ_callback();
341  }
342  void USART3_IRQHandler(void)
343  {
344  UART3Ptr->DMA_Rx_IRQ_callback();
345  }
346 
348  {
350  {
352  UART1Ptr->DMA_Rx_IRQ_callback();
353  }
354  }
355 
357  {
359  {
362  UART1Ptr->DMA_Tx_IRQ_callback();
363  }
364  }
365 
367  {
369  {
371  UART3Ptr->DMA_Rx_IRQ_callback();
372  }
373  }
374 
376  {
378  {
381  UART3Ptr->DMA_Tx_IRQ_callback();
382  }
383  }
384 
385 }
#define DMA_MemoryInc_Enable
uint32_t DMA_MemoryInc
Definition: stm32f4xx_dma.h:76
#define DMA_IT_TCIF5
void init_UART(uint32_t baudrate_, uart_mode_t mode=MODE_8N1)
Definition: uart.cpp:68
bool tx_buffer_empty() override
Definition: uart.cpp:279
void init(const uart_hardware_struct_t *conf, uint32_t baudrate_, uart_mode_t mode=MODE_8N1)
Definition: uart.cpp:41
uint32_t DMA_Channel
Definition: stm32f4xx_dma.h:56
void GPIO_PinAFConfig(GPIO_TypeDef *GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)
Changes the mapping of the specified pin.
GPIO rx_pin_
Definition: uart.h:86
void NVIC_Init(NVIC_InitTypeDef *NVIC_InitStruct)
Initializes the NVIC peripheral according to the specified parameters in the NVIC_InitStruct.
void register_rx_callback(void(*cb)(uint8_t data)) override
Definition: uart.cpp:325
#define TX_BUFFER_SIZE
Definition: serial.h:40
#define USART_Parity_No
DMA Init structure definition.
Definition: stm32f4xx_dma.h:54
uint16_t USART_HardwareFlowControl
#define USART_Mode_Tx
UART * UART3Ptr
Definition: uart.cpp:35
#define DMA_MemoryDataSize_Byte
uint16_t tx_buffer_head_
Definition: uart.h:84
void DMA_Tx_IRQ_callback()
Definition: uart.cpp:316
uint32_t DMA_MemoryBurst
void DMA_DeInit(DMA_Stream_TypeDef *DMAy_Streamx)
Deinitialize the DMAy Streamx registers to their default reset values.
IRQn_Type Rx_DMA_IRQn
Definition: system.h:115
#define DMA_PeripheralInc_Disable
#define DMA_IT_TCIF3
IRQn_Type USART_IRQn
Definition: system.h:114
bool flush() override
Definition: uart.cpp:284
#define DMA1_Stream3
Definition: stm32f4xx.h:2128
std::function< void(uint8_t)> receive_CB_
Definition: serial.h:76
void put_byte(uint8_t ch) override
Definition: uart.cpp:235
uint32_t DMA_MemoryDataSize
Definition: stm32f4xx_dma.h:82
#define DMA_Priority_High
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...
uint8_t rx_buffer_[RX_BUFFER_SIZE]
Definition: uart.h:80
#define USART_Mode_Rx
uint32_t DMA_DIR
Definition: stm32f4xx_dma.h:65
uint16_t rx_buffer_tail_
Definition: uart.h:83
UART()
Definition: uart.cpp:37
uint32_t DMA_PeripheralInc
Definition: stm32f4xx_dma.h:73
#define DMA_IT_TCIF1
#define DMA_DIR_MemoryToPeripheral
#define DMA_IT_TCIF7
uart_mode_t
Definition: uart.h:47
void USART_ITConfig(USART_TypeDef *USARTx, uint16_t USART_IT, FunctionalState NewState)
Enables or disables the specified USART interrupts.
const uart_hardware_struct_t * c_
Definition: uart.h:77
ITStatus DMA_GetITStatus(DMA_Stream_TypeDef *DMAy_Streamx, uint32_t DMA_IT)
Checks whether the specified DMAy Streamx interrupt has occurred or not.
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
uint8_t read_byte() override
Definition: uart.cpp:216
#define USART_DMAReq_Tx
#define USART_HardwareFlowControl_None
#define USART_WordLength_8b
uint32_t tx_bytes_free() override
Definition: uart.cpp:261
void DMA1_Stream1_IRQHandler(void)
Definition: uart.cpp:366
void init(GPIO_TypeDef *BasePort, uint16_t pin, gpio_mode_t mode)
Definition: gpio.cpp:34
void DMA2_Stream5_IRQHandler(void)
Definition: uart.cpp:347
void init_NVIC()
Definition: uart.cpp:160
GPIO_TypeDef * GPIO
Definition: system.h:108
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 DMA1_Stream1
Definition: stm32f4xx.h:2126
#define USART_StopBits_2
__IO uint16_t DR
Definition: stm32f4xx.h:1714
uint32_t DMA_PeripheralBurst
#define USART_DMAReq_Rx
#define DMA_FIFOThreshold_1QuarterFull
#define DMA2_Stream7
Definition: stm32f4xx.h:2141
uint8_t Rx_PinSource
Definition: system.h:111
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
#define RX_BUFFER_SIZE
Definition: serial.h:39
void USART1_IRQHandler(void)
Definition: uart.cpp:338
uint32_t DMA_Memory0BaseAddr
Definition: stm32f4xx_dma.h:61
uint16_t USART_WordLength
UART * UART1Ptr
Definition: uart.cpp:34
void init_DMA()
Definition: uart.cpp:101
Definition: uart.h:43
#define DMA_MemoryBurst_Single
uint32_t DMA_FIFOThreshold
Definition: stm32f4xx_dma.h:98
__IO uint32_t M0AR
Definition: stm32f4xx.h:912
uint16_t rx_buffer_head_
Definition: uart.h:82
void USART_Init(USART_TypeDef *USARTx, USART_InitTypeDef *USART_InitStruct)
Initializes the USARTx peripheral according to the specified parameters in the USART_InitStruct ...
#define DMA2_Stream5
Definition: stm32f4xx.h:2139
uint8_t tx_buffer_[TX_BUFFER_SIZE]
Definition: uart.h:81
#define DMA_Mode_Normal
void DMA1_Stream3_IRQHandler(void)
Definition: uart.cpp:375
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 DMA_FIFOMode_Disable
FunctionalState DMA_GetCmdStatus(DMA_Stream_TypeDef *DMAy_Streamx)
Returns the status of EN bit for the specified DMAy Streamx.
void DMA2_Stream7_IRQHandler(void)
Definition: uart.cpp:356
#define USART_IT_RXNE
#define USART3
Definition: stm32f4xx.h:2057
uint32_t DMA_FIFOMode
Definition: stm32f4xx_dma.h:93
#define DMA_PeripheralDataSize_Byte
uint32_t rx_bytes_waiting() override
Definition: uart.cpp:240
bool set_mode(uint32_t baud, uart_mode_t mode)
Definition: uart.cpp:273
USART_TypeDef * dev
Definition: system.h:107
IRQn_Type Tx_DMA_IRQn
Definition: system.h:116
void startDMA()
Definition: uart.cpp:194
void cb(uint8_t byte)
Definition: ublox.cpp:15
GPIO tx_pin_
Definition: uart.h:87
void DMA_Rx_IRQ_callback()
Definition: uart.cpp:294
uint16_t tx_buffer_tail_
Definition: uart.h:85
uint32_t DMA_Mode
Definition: stm32f4xx_dma.h:85
#define NULL
Definition: usbd_def.h:50
#define USART_StopBits_1
#define DMA_DIR_PeripheralToMemory
#define USART_Parity_Even
void USART3_IRQHandler(void)
Definition: uart.cpp:342
uint32_t DMA_BufferSize
Definition: stm32f4xx_dma.h:69
uint32_t DMA_Priority
Definition: stm32f4xx_dma.h:90
#define DMA_Mode_Circular
DMA_Stream_TypeDef * Rx_DMA_Stream
Definition: system.h:117
uint32_t DMA_Channel
Definition: system.h:119
void write(const uint8_t *ch, uint8_t len) override
Definition: uart.cpp:178
uint8_t Tx_PinSource
Definition: system.h:112
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
void unregister_rx_callback() override
Definition: uart.cpp:330
DMA_Stream_TypeDef * Tx_DMA_Stream
Definition: system.h:118
#define DMA_PeripheralBurst_Single


rosflight_firmware
Author(s): Daniel Koch , James Jackson
autogenerated on Wed Jul 3 2019 19:59:26