Subversion Repositories DashDisplay

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 mjames 1
/*
2
 * serial.c
3
 *
4
 *  Created on: 4 Jan 2016
5
 *      Author: Mike
6
 *
7
 *      This (ab)uses the STMCubeMX HAL declarations to implement a generic STM32F1xx
8
 *      USART driver layer
9
 */
10
 
11
 
12
#include "serial.h"
13
 
14
/* workspaces for the USARTS being used */
4 mjames 15
usart_ctl uc1;
2 mjames 16
usart_ctl uc2;
23 mjames 17
usart_ctl uc3;
2 mjames 18
 
19
 
20
 
21
/* returns the number of characters received by the Rx USART */
22
uint16_t SerialCharsReceived(usart_ctl * instance)
23
{
24
        uint16_t result = 0;    // assume no characters received yet
25
        __HAL_UART_DISABLE_IT(instance,  UART_IT_RXNE);
26
 
27
        if (instance->rx_usart_buffer_full)
28
        {       // buffer is full...
29
                result = RX_USART_BUFF_SIZ;
30
        }
31
        else if (instance->rx_usart_in_Ptr >= instance->rx_usart_out_Ptr)
32
        {       // buffer has not wrapped...
33
                result = instance->rx_usart_in_Ptr - instance->rx_usart_out_Ptr;
34
        }
35
        else
36
        {       // buffer has possibly wrapped...
37
                result = RX_USART_BUFF_SIZ - instance->rx_usart_out_Ptr + instance->rx_usart_in_Ptr;
38
        }
39
        __HAL_UART_ENABLE_IT(instance,  UART_IT_RXNE);
40
 
41
        return result;
42
}
43
 
44
inline uint8_t PollSerial(usart_ctl * instance)
45
{
46
        uint8_t rc;
47
 
48
        __HAL_UART_DISABLE_IT(instance,  UART_IT_RXNE);
49
    rc =  ( instance->rx_usart_buffer_full || (instance->rx_usart_in_Ptr != instance->rx_usart_out_Ptr));
50
        __HAL_UART_ENABLE_IT(instance,  UART_IT_RXNE);
51
 
52
        return rc;
53
}
54
 
55
/***!
56
 * @brief return the next character in the Serial input buffer
57
 * This function will wait until a character arrives.
58
 */
59
uint8_t GetCharSerial(usart_ctl * instance)
60
{
61
        uint8_t c;
62
        __HAL_UART_DISABLE_IT(instance,  UART_IT_RXNE);
63
        while (!instance->rx_usart_buffer_full && (instance->rx_usart_in_Ptr == instance->rx_usart_out_Ptr))
64
        {
65
                __HAL_UART_ENABLE_IT(instance,  UART_IT_RXNE);
66
                __WFI(); /* wait for something */
67
                __HAL_UART_DISABLE_IT(instance,  UART_IT_RXNE);
68
        }
69
 
70
 
71
        c = instance->rx_usart_buff[instance->rx_usart_out_Ptr];
72
        instance->rx_usart_buffer_full = 0; /* removed character */
73
        instance->rx_usart_out_Ptr++;
74
        if (instance->rx_usart_out_Ptr >= RX_USART_BUFF_SIZ)
75
        {
76
                instance->rx_usart_out_Ptr = 0;
77
        }
78
        __HAL_UART_ENABLE_IT(instance,  UART_IT_RXNE);
79
        return c;
80
}
81
 
82
 
83
/*
84
 * \brief
85
 * void EnableSerialRxInterrupt(void) - this function is used from the interrupt handler and the main scheduler loop
86
 * to enable the serial rx interrupt after resetting the serial rx buffer...
87
 */
88
inline void EnableSerialRxInterrupt(usart_ctl * instance)
89
{
90
        /* cheat here - this is a macro and I have the same Instance member as the HAL handle, with the same meaning */
91
        __HAL_UART_ENABLE_IT(instance,  UART_IT_RXNE);
92
}
93
 
94
 
95
 
96
 
97
 
98
 
99
/****!
100
 * @brief send a character to the serial USART via placing it in the serial buffer
101
 *
102
 */
103
 
104
 
105
static void PutCharSerialFIFO(usart_ctl * instance,uint8_t c) {
106
        __HAL_UART_DISABLE_IT(instance, UART_IT_TXE);
107
 
108
        instance->tx_usart_buff[instance->tx_usart_in_Ptr++] = c;
109
        instance->tx_usart_count += 1;
110
        if (instance->tx_usart_in_Ptr >= TX_USART_BUFF_SIZ) {
111
                instance->tx_usart_in_Ptr = 0;
112
        }
113
        /* Handle overrun by losing oldest characters */
114
        if (instance->tx_usart_in_Ptr == instance->tx_usart_out_Ptr) {
115
                instance->tx_usart_out_Ptr++;
116
                if (instance->tx_usart_out_Ptr >= TX_USART_BUFF_SIZ) {
117
                        instance->tx_usart_out_Ptr = 0;
118
                }
119
        }
120
 
121
 
122
        instance->tx_usart_running = 1;
123
        __HAL_UART_ENABLE_IT(instance, UART_IT_TXE);
124
}
125
 
126
void UART_IRQHandler(usart_ctl * instance)
127
{
128
 
129
        __disable_irq();
130
        uint32_t rxStatus;      // status from USART receiver
131
 
132
        rxStatus = instance->Instance->SR;      // read the status bits - this resets all the hardware signalling flags
133
 
134
        if (rxStatus & USART_SR_RXNE) {
135
                // no error has occurred...
136
                uint8_t rxChar = (uint8_t)(instance->Instance->DR & 0xff);      // read the bottom 8-bits only
137
 
138
                if (!instance->rx_usart_buffer_full) {
139
                        instance->rx_usart_buff[instance->rx_usart_in_Ptr++] = rxChar;
140
 
141
                        if (instance->rx_usart_in_Ptr >= RX_USART_BUFF_SIZ) {
142
                                instance->rx_usart_in_Ptr = 0;
143
                        }
144
                        if (instance->rx_usart_in_Ptr == instance->rx_usart_out_Ptr) {
145
                                instance->rx_usart_buffer_full = 1; /* buffer overrun */
146
                        }
147
                }
148
        }
149
        /* check for transmitter interrupt : this code is used */
150
        if ((rxStatus & USART_SR_TXE) != RESET) {
151
 
152
                /* Only enable the transmitter when baud detect has completed or check expired.
153
                 * and the software is ready for it to be enabled as programming mode is wanting
154
                 * to receive a response and that can get blocked if we're streaming a lot of debug messages*/
155
                if (instance->tx_usart_in_Ptr != instance->tx_usart_out_Ptr) {
156
                        instance->Instance->DR = instance->tx_usart_buff[instance->tx_usart_out_Ptr++];
157
                        if (instance->tx_usart_count != 0)
158
                                instance->tx_usart_count -= 1;
159
 
160
                        if (instance->tx_usart_out_Ptr >= TX_USART_BUFF_SIZ) {
161
                                instance->tx_usart_out_Ptr = 0;
162
                        }
163
                } else {
164
                        __HAL_UART_DISABLE_IT(instance, UART_IT_TXE);
165
                        instance->tx_usart_running = 0;
166
                }
167
        }
168
 
169
        __enable_irq();
170
}
171
 
172
 
173
void PutCharSerial(usart_ctl * instance,uint8_t c)
174
{
175
        // Put character in Crayon/Pen interface
176
        PutCharSerialFIFO(instance,c);
177
}
178
 
179
/*
180
 * \brief
181
 * ResetTxBuffer(void) - resets the serial transmitter buffer
182
 */
183
void ResetTxBuffer(usart_ctl * instance)
184
{
185
 
186
        instance->tx_usart_out_Ptr = 0;
187
        instance->tx_usart_running = 0;
188
        instance->tx_usart_in_Ptr = 0; /* setup in pointer last to drop any chars come in */
189
        instance->tx_usart_count = 0;
190
 
191
}
192
 
193
/*
194
 * \brief
195
 * void ResetRxBuffer(void) - resets the serial receiver buffer
196
 */
197
void ResetRxBuffer(usart_ctl * instance)
198
{
199
 
200
        instance->rx_usart_out_Ptr = 0;
201
        instance->rx_usart_buffer_full = 0;
202
        instance->rx_usart_in_Ptr = 0; /* setup in pointer last to drop any chars come in */
203
 
204
}
205
 
206
/***!
207
 * @brief Flush Serial input and output buffers
208
 */
209
void FlushSerial(usart_ctl * instance)
210
{
211
        ResetRxBuffer(instance);
212
        ResetTxBuffer(instance);
213
}
214
 
215
 
216
/***!
217
 * @brief check if tx buffer is empty...
218
 */
219
 
220
uint8_t  TxBufferEmpty(usart_ctl * instance)
221
{
222
        return (0 == instance->tx_usart_count);
223
}
224
 
225
 
226
/****
227
 * @brief Initialise control structure
228
 */
229
void init_usart_ctl(usart_ctl * instance, USART_TypeDef * hardware)
230
{
231
        instance->Instance = hardware;
232
 
233
        instance->tx_usart_in_Ptr = 0;
234
        instance->tx_usart_out_Ptr = 0;
235
        instance->tx_usart_running = 0;
236
        instance->tx_usart_count = 0;
237
 
238
        instance->rx_usart_in_Ptr = 0;
239
        instance->rx_usart_out_Ptr = 0;
240
        instance->rx_usart_buffer_full = 0;
241
 
242
}
243
 
244
 
245
/////////////////////////////////////////////////////////
246
/// Moved from generated code  to avoid crappy HAL handler
4 mjames 247
void USART1_IRQHandler(void)
2 mjames 248
{
4 mjames 249
        UART_IRQHandler(&uc1);
2 mjames 250
}
251
 
252
void USART2_IRQHandler(void)
253
{
254
        UART_IRQHandler(&uc2);
255
}
256
 
23 mjames 257
void USART3_IRQHandler(void)
258
{
259
        UART_IRQHandler(&uc3);
260
}
261