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 void UART::init(const uart_hardware_struct_t* conf, uint32_t baudrate, uart_mode_t mode)
40 {
41  receive_CB_ = nullptr;
42  c_ = conf; // Save the configuration
43 
44  // initialize pins
49 
50  // Save the pointer, for callbacks
51  if (c_->dev == USART1)
52  {
53  UART1Ptr = this;
54  }
55  if (c_->dev == USART3)
56  {
57  UART3Ptr = this;
58  }
59 
60  init_UART(baudrate, mode);
61  init_DMA();
62  init_NVIC();
63 }
64 
65 void UART::init_UART(uint32_t baudrate, uart_mode_t mode)
66 {
67  // Configure the device
68  USART_Cmd(c_->dev, DISABLE); // Disable the usart device for configuration
69 
70  USART_InitTypeDef USART_InitStruct;
71  USART_InitStruct.USART_BaudRate = baudrate;
72 
73  switch (mode)
74  {
75  case MODE_8N1:
76  default:
77  USART_InitStruct.USART_WordLength = USART_WordLength_8b;
78  USART_InitStruct.USART_Parity = USART_Parity_No;
79  USART_InitStruct.USART_StopBits = USART_StopBits_1;
80  break;
81  case MODE_8E2:
82  USART_InitStruct.USART_WordLength = USART_WordLength_8b;
83  USART_InitStruct.USART_Parity = USART_Parity_Even;
84  USART_InitStruct.USART_StopBits = USART_StopBits_2;
85  break;
86  }
87 
89  USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // Set to both receive and send
90  USART_Init(c_->dev, &USART_InitStruct);
91  // USART_OverSampling8Cmd(c_->dev, ENABLE);//Please don't break anything
92 
93  // Throw interrupts on byte receive
94  USART_ITConfig(c_->dev, USART_IT_RXNE, ENABLE); // enable interupts on receive
95  USART_Cmd(c_->dev, ENABLE); // reenable the usart
96 }
97 
99 {
100  DMA_InitTypeDef DMA_InitStructure;
101 
102  // Common DMA Configuration
103  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
105  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
106  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
107 
108  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
111  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
112 
113  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
114  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
115  DMA_InitStructure.DMA_PeripheralBaseAddr = reinterpret_cast<uint32_t>(&(c_->dev->DR));
116  DMA_InitStructure.DMA_Channel = c_->DMA_Channel;
117 
118  // Configure the Tx DMA
120  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
121  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
122  DMA_InitStructure.DMA_BufferSize = TX_BUFFER_SIZE;
123  DMA_InitStructure.DMA_Memory0BaseAddr = reinterpret_cast<uint32_t>(tx_buffer_);
124  DMA_Init(c_->Tx_DMA_Stream, &DMA_InitStructure);
125 
126  // Configure the Rx DMA
128  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
129  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
130  DMA_InitStructure.DMA_BufferSize = RX_BUFFER_SIZE;
131  DMA_InitStructure.DMA_Memory0BaseAddr = reinterpret_cast<uint32_t>(rx_buffer_);
132  DMA_Init(c_->Rx_DMA_Stream, &DMA_InitStructure);
133 
134  // Turn on the Rx DMA Stream
136 
137  // Hook up the DMA to the uart
140 
141  // Turn on the transfer complete interrupt source from the DMA
144 
145  // Initialize the Circular Buffers
146  // set the buffer pointers to where the DMA is starting (starts at 256 and counts down)
149  tx_buffer_head_ = 0;
150  tx_buffer_tail_ = 0;
151 
152  memset(rx_buffer_, 0, RX_BUFFER_SIZE);
153  memset(tx_buffer_, 0, TX_BUFFER_SIZE);
154 }
155 
157 {
158  // Configure the Interrupt
159  NVIC_InitTypeDef NVIC_InitStruct;
160  NVIC_InitStruct.NVIC_IRQChannel = c_->USART_IRQn;
161  NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
162  NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
163  NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
164  NVIC_Init(&NVIC_InitStruct);
165 
166  NVIC_InitStruct.NVIC_IRQChannel = c_->Tx_DMA_IRQn;
167  NVIC_Init(&NVIC_InitStruct);
168 
169  NVIC_InitStruct.NVIC_IRQChannel = c_->Rx_DMA_IRQn;
170  NVIC_Init(&NVIC_InitStruct);
171 }
172 
173 void UART::write(const uint8_t* ch, uint8_t len)
174 {
175  // Put Data on the tx_buffer
176  for (int i = 0; i < len; i++)
177  {
180  }
182  {
183  startDMA();
184  }
185  // this->flush();//testing
186 }
187 
189 {
190  // Set the start of the transmission to the oldest data
191  c_->Tx_DMA_Stream->M0AR = reinterpret_cast<uint32_t>(&tx_buffer_[tx_buffer_tail_]);
193  {
194  // Set the length of the transmission to the data on the buffer
195  // if contiguous, this is easy
198  }
199  else
200  {
201  // We will have to send the data in two groups, first the tail,
202  // then the head we will do later
204  tx_buffer_tail_ = 0;
205  }
206  // Start the Transmission
208 }
209 
211 {
212  uint8_t byte = 0;
213  // pull the next byte off the array
214  // (the head counts down, because CNTR counts down)
216  {
217  // read a new byte and decrement the tail
219  if (--rx_buffer_tail_ == 0)
220  {
221  // wrap to the top if at the bottom
223  }
224  }
225  return byte;
226 }
227 
228 void UART::put_byte(uint8_t ch)
229 {
230  write(&ch, 1);
231 }
232 
234 {
235  // Remember, the DMA CNDTR counts down
238  {
239  // Easy, becasue it's contiguous
241  }
242  else if (rx_buffer_head_ > rx_buffer_tail_)
243  {
244  // Add the parts on either end of the buffer
245  // I'm pretty sure this is wrong
247  }
248  else
249  {
250  return 0;
251  }
252 }
253 
255 {
256  // Remember, the DMA CNDTR counts down
259  {
261  }
262  else
264 }
265 
266 bool UART::set_mode(uint32_t baud, uart_mode_t mode)
267 {
268  init_UART(baud, mode);
269  return true;
270 }
271 
273 {
275 }
276 
278 {
279  uint32_t timeout = 100000;
280  while (!tx_buffer_empty() && --timeout)
281  ;
282  if (timeout)
283  return true;
284  else
285  return false;
286 }
287 
289 {
290  // DMA took care of putting the data on the buffer
291  // Just call the callback until we have no more data
292  // Update the head position from the DMA
294  if (receive_CB_ != nullptr)
295  {
297  {
298  // read a new byte and decrement the tail
299  uint8_t byte = rx_buffer_[RX_BUFFER_SIZE - rx_buffer_tail_];
300  receive_CB_(byte);
301  if (--rx_buffer_tail_ == 0)
302  {
303  // wrap to the top if at the bottom
305  }
306  }
307  }
308 }
309 
311 {
312  // If there is more data to be sent
314  {
315  startDMA();
316  }
317 }
318 
319 void UART::register_rx_callback(void (*cb)(uint8_t data))
320 {
321  receive_CB_ = cb;
322 }
323 
325 {
326  receive_CB_ = nullptr;
327 }
328 
329 extern "C"
330 {
331  void USART1_IRQHandler(void) { UART1Ptr->DMA_Rx_IRQ_callback(); }
332  void USART3_IRQHandler(void) { UART3Ptr->DMA_Rx_IRQ_callback(); }
333 
335  {
337  {
339  UART1Ptr->DMA_Rx_IRQ_callback();
340  }
341  }
342 
344  {
346  {
349  UART1Ptr->DMA_Tx_IRQ_callback();
350  }
351  }
352 
354  {
356  {
358  UART3Ptr->DMA_Rx_IRQ_callback();
359  }
360  }
361 
363  {
365  {
368  UART3Ptr->DMA_Tx_IRQ_callback();
369  }
370  }
371 }
#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:65
bool tx_buffer_empty() override
Definition: uart.cpp:272
void init(const uart_hardware_struct_t *conf, uint32_t baudrate_, uart_mode_t mode=MODE_8N1)
Definition: uart.cpp:39
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:84
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:319
#define TX_BUFFER_SIZE
Definition: serial.h:42
#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:82
void DMA_Tx_IRQ_callback()
Definition: uart.cpp:310
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:116
#define DMA_PeripheralInc_Disable
#define DMA_IT_TCIF3
IRQn_Type USART_IRQn
Definition: system.h:115
bool flush() override
Definition: uart.cpp:277
#define DMA1_Stream3
Definition: stm32f4xx.h:2128
std::function< void(uint8_t)> receive_CB_
Definition: serial.h:77
void put_byte(uint8_t ch) override
Definition: uart.cpp:228
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:78
#define USART_Mode_Rx
uint32_t DMA_DIR
Definition: stm32f4xx_dma.h:65
uint16_t rx_buffer_tail_
Definition: uart.h:81
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:45
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:75
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:210
#define USART_DMAReq_Tx
#define USART_HardwareFlowControl_None
#define USART_WordLength_8b
uint32_t tx_bytes_free() override
Definition: uart.cpp:254
void DMA1_Stream1_IRQHandler(void)
Definition: uart.cpp:353
void init(GPIO_TypeDef *BasePort, uint16_t pin, gpio_mode_t mode)
Definition: gpio.cpp:34
void DMA2_Stream5_IRQHandler(void)
Definition: uart.cpp:334
void init_NVIC()
Definition: uart.cpp:156
GPIO_TypeDef * GPIO
Definition: system.h:109
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:112
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:41
void USART1_IRQHandler(void)
Definition: uart.cpp:331
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:98
Definition: uart.h:42
#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:80
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:79
#define DMA_Mode_Normal
void DMA1_Stream3_IRQHandler(void)
Definition: uart.cpp:362
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:343
#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:233
bool set_mode(uint32_t baud, uart_mode_t mode)
Definition: uart.cpp:266
USART_TypeDef * dev
Definition: system.h:108
IRQn_Type Tx_DMA_IRQn
Definition: system.h:117
void startDMA()
Definition: uart.cpp:188
void cb(uint8_t byte)
Definition: ublox.cpp:8
GPIO tx_pin_
Definition: uart.h:85
void DMA_Rx_IRQ_callback()
Definition: uart.cpp:288
uint16_t tx_buffer_tail_
Definition: uart.h:83
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:332
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:118
uint32_t DMA_Channel
Definition: system.h:120
void write(const uint8_t *ch, uint8_t len) override
Definition: uart.cpp:173
uint8_t Tx_PinSource
Definition: system.h:113
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:324
DMA_Stream_TypeDef * Tx_DMA_Stream
Definition: system.h:119
#define DMA_PeripheralBurst_Single


rosflight_firmware
Author(s): Daniel Koch , James Jackson
autogenerated on Thu Apr 15 2021 05:07:49