-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbsp_tty.cpp
332 lines (254 loc) · 7.64 KB
/
bsp_tty.cpp
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
/*
* bsp-nucleo-f103, a generic bsp for nucleo f103rb based projects.
*
* Copyright (C) 2020 Julian Friedrich
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* You can file issues at https://github.com/fjulian79/bsp-stm32-f103.git
*/
#include <stm32f1xx_ll_usart.h>
#include <stm32f1xx_ll_dma.h>
#include "bsp/bsp.h"
#include "bsp/bsp_gpio.h"
#include "bsp/bsp_tty.h"
#include "bsp/bsp_assert.h"
#include "generic/generic.hpp"
#include "generic/fifo.hpp"
#include <stdbool.h>
#include <stdio.h>
#include <errno.h>
#if BSP_TTY_TX_DMA == BSP_ENABLED
/**
* @brief TTY Data shared with the interrupt.
*/
struct
{
char Data[BSP_TTY_TX_BUFSIZ];
volatile size_t TxBytes;
uint32_t NumLost;
} ttyTxData;
/**
* @brief Generic fifo instance operation on ttyData.Data
*/
Fifo *pTxFifo;
/**
* @brief Starts a DMS transfer at the given address with the given length.
*
* @param pData Address to start.
* @param siz Number of bytes to transfer.
*/
void startDmaTx(uint8_t *pData, size_t siz)
{
LL_DMA_SetMemoryAddress(DMA1, TTY_TXDMACH_LLCH, (uint32_t)pData);
LL_DMA_SetDataLength(DMA1, TTY_TXDMACH_LLCH, siz);
LL_USART_EnableDMAReq_TX(TTY_USARTx);
LL_DMA_EnableChannel(DMA1, TTY_TXDMACH_LLCH);
}
/**
* @brief TTY Tx DMA Interrupt handler.
*/
extern "C" void TTY_TXDMACH_IRQHandler(void)
{
uint8_t *ptr = NULL;
if(TTY_TXDMACH_ISACTIVEFLAG_TC())
{
TTY_TXDMACH_CLEARFLAG_TC();
LL_USART_DisableDMAReq_TX(TTY_USARTx);
LL_DMA_DisableChannel(DMA1, TTY_TXDMACH_LLCH);
pTxFifo->free(ttyTxData.TxBytes);
ttyTxData.TxBytes = pTxFifo->getReadBlock((void**)&ptr);
if (ttyTxData.TxBytes != 0)
startDmaTx(ptr, ttyTxData.TxBytes);
}
else
{
bspDoAssert();
}
}
#endif /* BSP_TTY_TX_DMA == BSP_ENABLED */
#if BSP_TTY_RX_IRQ == BSP_ENABLED
/**
* @brief TTY Rx data shared with the interrupt.
*/
struct
{
char Data[BSP_TTY_RX_BUFSIZ];
uint32_t NumLost;
} ttyRxData;
/**
* @brief Generic fifo instance operation on ttyData.Data
*/
Fifo *pRxFifo;
extern "C" void TTY_USARTx_IRQHandler(void)
{
if( LL_USART_IsActiveFlag_RXNE(TTY_USARTx)
&& LL_USART_IsEnabledIT_RXNE(TTY_USARTx))
{
uint8_t data = LL_USART_ReceiveData8(TTY_USARTx);
if (pRxFifo->put(&data))
ttyRxData.NumLost++;
}
}
#endif /* BSP_TTY_RX_IRQ == BSP_ENABLED */
/**
* @brief Called by c library for printf calls.
*
* @param file The used Stream number.
* @param pData The data to write.
* @param siz The number of bytes to write.
*
* @return siz,if BSP_TTY_BLOCKING is disabled.
* The number of bytes really written to the tx buffer
* if BSP_TTY_BLOCKING is enabled.
*/
extern "C" int _write(int file, char *pData, int siz)
{
#if BSP_TTY_TX_DMA == BSP_ENABLED
int tmp = 0;
uint8_t *ptr = NULL;
do
{
NVIC_DisableIRQ(TTY_TXDMACH_IRQn);
if ((siz - tmp) == 1)
tmp += pTxFifo->put(pData + tmp);
else
tmp += pTxFifo->write(pData + tmp, (siz - tmp));
if (ttyTxData.TxBytes == 0)
{
ttyTxData.TxBytes = pTxFifo->getReadBlock((void**)&ptr);
startDmaTx(ptr, ttyTxData.TxBytes);
}
NVIC_EnableIRQ(TTY_TXDMACH_IRQn);
#if BSP_TTY_BLOCKING == BSP_ENABLED
while (pTxFifo->getFree() == 0 && (tmp < siz));
} while (tmp < siz);
return tmp;
#else /* BSP_TTY_BLOCKING == BSP_ENABLED */
} while (0);
unused(tmp);
return siz;
#endif /* BSP_TTY_BLOCKING == BSP_ENABLED */
#else /* #if BSP_TTY_TX_DMA == BSP_ENABLED */
for (int pos = 0; pos < siz; pos++)
{
while (!LL_USART_IsActiveFlag_TXE(TTY_USARTx));
LL_USART_TransmitData8(TTY_USARTx, pData[pos]);
}
return siz;
#endif
errno = EIO;
return -1;
}
/**
* @brief Called by scanf calls to read from the given stream.
*
* @param file The stream to read from.
* @param ptr The buffer to write to.
* @param len The number of bytes to read.
*
* @return TBD
*/
int _read(int file, char *ptr, int len)
{
unused(file);
unused(ptr);
unused(len);
errno = EIO;
return -1;
}
void bspTTYInit(uint32_t baud)
{
LL_USART_InitTypeDef init;
LL_USART_StructInit(&init);
init.BaudRate = baud;
LL_USART_Init(TTY_USARTx, &init);
LL_USART_Enable(TTY_USARTx);
#if BSP_TTY_RX_IRQ == BSP_ENABLED
ttyRxData.NumLost = 0;
pRxFifo = new Fifo(ttyRxData.Data, sizeof(ttyRxData.Data));
NVIC_SetPriority(USART2_IRQn, BSP_IRQPRIO_TTY);
NVIC_EnableIRQ(USART2_IRQn);
LL_USART_EnableIT_RXNE(TTY_USARTx);
#endif /* BSP_TTY_RX_IRQ == BSP_ENABLED */
#if BSP_TTY_TX_DMA == BSP_ENABLED
LL_DMA_InitTypeDef dma;
ttyTxData.TxBytes = 0;
ttyTxData.NumLost = 0;
pTxFifo = new Fifo(ttyTxData.Data, sizeof(ttyTxData.Data));
LL_DMA_StructInit(&dma);
dma.Mode = LL_DMA_MODE_NORMAL;
dma.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
dma.Priority = LL_DMA_PRIORITY_HIGH;
dma.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
dma.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
dma.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE;
dma.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE;
dma.PeriphOrM2MSrcAddress = LL_USART_DMA_GetRegAddr(TTY_USARTx);
LL_DMA_Init(DMA1, TTY_TXDMACH_LLCH, &dma);
NVIC_SetPriority(TTY_TXDMACH_IRQn, BSP_IRQPRIO_TTY);
NVIC_EnableIRQ(TTY_TXDMACH_IRQn);
LL_DMA_EnableIT_TC(DMA1, TTY_TXDMACH_LLCH);
LL_DMA_EnableIT_TE(DMA1, TTY_TXDMACH_LLCH);
#endif /* BSP_TTY_TX_DMA == BSP_ENABLED */
}
bspStatus_t bspTTYSendData(uint8_t *pData, uint16_t siz)
{
bspStatus_t ret = BSP_OK;
if (_write(1, (char *) pData, siz) != (int) siz)
ret = BSP_ERR;
return ret;
}
bool bspTTYDataAvailable(void)
{
#if BSP_TTY_RX_IRQ == BSP_ENABLED
return pRxFifo->getUsed() != 0 ? true : false;
#else /* BSP_TTY_RX_IRQ == BSP_ENABLED */
return LL_USART_IsActiveFlag_RXNE(TTY_USARTx) ? true : false;
#endif /* BSP_TTY_RX_IRQ == BSP_ENABLED */
}
char bspTTYGetChar(void)
{
while (!bspTTYDataAvailable());
#if BSP_TTY_RX_IRQ == BSP_ENABLED
char data;
pRxFifo->get(&data);
return data;
#else /* BSP_TTY_RX_IRQ == BSP_ENABLED */
return LL_USART_ReceiveData8(TTY_USARTx);
#endif /* BSP_TTY_RX_IRQ == BSP_ENABLED */
}
#if BSP_ASSERT_MESSAGE == BSP_ENABLED
void bspTTYAssertMessage(char *pChar)
{
#if BSP_TTY_TX_DMA == BSP_ENABLED
/* If a transfer is ongoing let it complete and disable the DMA once it
* is done */
if(LL_DMA_IsEnabledChannel(DMA1, TTY_TXDMACH_LLCH))
{
while(!TTY_TXDMACH_ISACTIVEFLAG_TC());
TTY_TXDMACH_CLEARFLAG_TC();
LL_USART_DisableDMAReq_TX(TTY_USARTx);
LL_DMA_DisableChannel(DMA1, TTY_TXDMACH_LLCH);
}
#endif /* BSP_TTY_TX_DMA == BSP_ENABLED */
/* Do use DMA here as interrupts will most likely not work anymore */
while (*pChar != 0)
{
while (!LL_USART_IsActiveFlag_TXE(TTY_USARTx));
LL_USART_TransmitData8(TTY_USARTx, *pChar);
pChar++;
}
}
#endif /* BSP_ASSERT_MESSAGE == BSP_ENABLED */