-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDMA_UARTDriver.cpp
More file actions
129 lines (102 loc) · 4.27 KB
/
DMA_UARTDriver.cpp
File metadata and controls
129 lines (102 loc) · 4.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/** ********************************************************************************
* @file DMA_UARTDriver.cpp
* @author Noah
* @date Nov 8, 2024
* @brief ******************************************************************************** */
/************************************ * INCLUDES ************************************/
#include "DMA_UARTDriver.hpp"
/************************************ * PRIVATE MACROS AND DEFINES ************************************/
/************************************ * VARIABLES ************************************/
/************************************ * FUNCTION DECLARATIONS ************************************/
/**
* @brief Starts a DMA transmission
* @param data The data to transmit
* @param len The length of the data to transmit
* @return True if the transmission was successful, False otherwise
*/
bool DMA_UARTDriver::Transmit(uint8_t* data, uint16_t len);
/**
* @brief Reads a byte from a circular buffer, increments buffer for valid bytes (waits for valid data otherwise)
* @return the byte value
*/
uint8_t DMA_UARTDriver::read_byte(uint8_t*& read_head, uint8_t* buffer, uint16_t bufferSize);
/**
* @brief Read the uart data buffer and store it in a passed data array
* @param charBuf buffer to store the read data
* @attention calling function must handle cases where the read message overflows charBuf
* @attention calling function should also call this until it returns true
* allowing for the function to be called before a message is complete
* @param buffIdx the index in charBuf that is currently being wrote to
* @return TRUE if interrupt was successfully enabled, FALSE otherwise
*/
bool DMA_UARTDriver::Receive(uint8_t* charBuf, uint8_t& buffIdx);
/************************************ * FUNCTION DEFINITIONS ************************************/
bool DMA_UARTDriver::Transmit(uint8_t* data, uint16_t len)
{
uint8_t metabytes = 0;
if(!is_Debug){
metabytes = 2; // add stop bytes for non-debug messages
}
// HAL DMA transmission
// make sure the data wont overflow the buffer
if(len + metabytes > MAX_DMA_BUFFER_LEN){
return false;
}
// check if current transfer is complete
for (int i = 0; HAL_UART_GetState(hUart_) != HAL_UART_STATE_READY; i++){
if(i > 10000) break; // TEMP fix for hal uart not readying error
}
// copy the message to the buffer
for(int i = 0; i < len; i++){
lin_tx_buffer[i] = data[i]; // sets the data to the message buffer, with an offset if its not to serial
}
// set the stop bytes in the buffer
// can ignore for terminal communications
if(!isdebug){
lin_tx_buffer[len] = '\r';
lin_tx_buffer[len + 1] = '\n';
}
// starts the process of transmitting the data via DMA
if(HAL_UART_Transmit_DMA(hUart_, (uint8_t*)lin_tx_buffer, len + metabytes)!= HAL_OK)
{
/* Transfer error in transmission process */
return false;
}
return true;
}
bool UARTDriver::Receive(uint8_t* charBuf, uint8_t& buffIdx)
{
if(HAL_UART_Receive_DMA(hUart_, (uint8_t *)rx_buffer, MAX_DMA_BUFFER_LEN) != HAL_OK){
} // make sure we're receiving
// read the next byte in the circular buffer
charBuf[buffIdx] = read_byte(rx_read_head, rx_buffer, MAX_DMA_BUFFER_LEN);
if(charBuf[buffIdx] && is_Debug) Transmit(charBuf+buffIdx, 1); // send input response to debug terminal
// makes debug messages cleaner by eliminating the metadata
// requires specific messages to work (ie '\r\n' terminated)
// loop until end of line character
while(charBuf[buffIdx] != '\n'){
if(charBuf[buffIdx] == '\0') return false; // wait until message is finished
buffIdx++;
charBuf[buffIdx] = read_byte(rx_read_head, rx_buffer, MAX_DMA_BUFFER_LEN); // continue to copy data
}
charBuf[buffIdx-1] = '\0'; // null terminate for a string
charBuf[buffIdx] = '\0';
buffIdx = 0; // reset the buffer
return true;
}
uint8_t UARTDriver::read_byte(uint8_t*& read_head, uint8_t* buffer, uint16_t bufferSize)
{
// read the byte from the current read head
uint8_t copy_to = *read_head;
// return if the read data hasnt been updated (no unread data)
if(copy_to == 0) return '\0';
// reset the address to a read state
*read_head = '\0';
// increment the read head, loop it around the circular buffer
if(read_head - buffer < bufferSize - 1){
read_head++;
}else{
read_head = buffer;
}
return copy_to;
}