Subversion Repositories DashDisplay

Rev

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