Subversion Repositories libSerial

Rev

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