Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 61a2fd8

Browse files
fprfpistm
fpr
authored andcommittedMay 12, 2017
Rework Serial with new pin management
Signed-off-by: fpr <[email protected]>
1 parent 164b740 commit 61a2fd8

File tree

9 files changed

+739
-581
lines changed

9 files changed

+739
-581
lines changed
 

‎cores/arduino/Arduino.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@ extern void loop( void ) ;
6767
#include "Tone.h"
6868
#include "WMath.h"
6969
#include "HardwareSerial.h"
70-
#include "UARTClass.h"
71-
#include "USARTClass.h"
7270
#include "wiring_pulse.h"
7371
#endif // __cplusplus
7472

‎cores/arduino/HardwareSerial.cpp

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/*
2+
HardwareSerial.cpp - Hardware serial library for Wiring
3+
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
19+
Modified 23 November 2006 by David A. Mellis
20+
Modified 28 September 2010 by Mark Sproul
21+
Modified 14 August 2012 by Alarus
22+
Modified 3 December 2013 by Matthijs Kooijman
23+
*/
24+
25+
#include <stdlib.h>
26+
#include <stdio.h>
27+
#include <string.h>
28+
#include <inttypes.h>
29+
#include "Arduino.h"
30+
#include "HardwareSerial.h"
31+
32+
33+
// Constructors ////////////////////////////////////////////////////////////////
34+
HardwareSerial::HardwareSerial(PinName _rx, PinName _tx)
35+
{
36+
_serial.pin_rx = _rx;
37+
_serial.pin_tx = _tx;
38+
_serial.rx_buff = _rx_buffer;
39+
_serial.rx_head = 0;
40+
_serial.rx_tail = 0;
41+
_serial.tx_buff = _tx_buffer;
42+
_serial.tx_head = 0;
43+
_serial.tx_tail = 0;
44+
}
45+
46+
// Actual interrupt handlers //////////////////////////////////////////////////////////////
47+
48+
void HardwareSerial::_rx_complete_irq(serial_t* obj)
49+
{
50+
// No Parity error, read byte and store it in the buffer if there is
51+
// room
52+
unsigned char c = uart_getc(obj);
53+
54+
rx_buffer_index_t i = (unsigned int)(obj->rx_head + 1) % SERIAL_RX_BUFFER_SIZE;
55+
56+
// if we should be storing the received character into the location
57+
// just before the tail (meaning that the head would advance to the
58+
// current location of the tail), we're about to overflow the buffer
59+
// and so we don't write the character or advance the head.
60+
if (i != obj->rx_tail) {
61+
obj->rx_buff[obj->rx_head] = c;
62+
obj->rx_head = i;
63+
}
64+
}
65+
66+
// Actual interrupt handlers //////////////////////////////////////////////////////////////
67+
68+
int HardwareSerial::_tx_complete_irq(serial_t* obj)
69+
{
70+
// If interrupts are enabled, there must be more data in the output
71+
// buffer. Send the next byte
72+
unsigned char c = obj->tx_buff[obj->tx_tail];
73+
obj->tx_tail = (obj->tx_tail + 1) % SERIAL_TX_BUFFER_SIZE;
74+
75+
if (obj->tx_head == obj->tx_tail) {
76+
return -1;
77+
}
78+
79+
return c;
80+
}
81+
82+
// Public Methods //////////////////////////////////////////////////////////////
83+
84+
void HardwareSerial::begin(unsigned long baud, byte config)
85+
{
86+
_serial.baudrate = (uint32_t)baud;
87+
88+
// Could be 8 or 9 bits. Could match with Arduino small data length?
89+
_serial.databits = UART_WORDLENGTH_8B;
90+
91+
if((config & 0x30) == 0x30) {
92+
_serial.parity = UART_PARITY_ODD;
93+
} else if((config & 0x20) == 0x20) {
94+
_serial.parity = UART_PARITY_EVEN;
95+
} else {
96+
_serial.parity = UART_PARITY_NONE;
97+
}
98+
99+
if((config & 0x08) == 0x08) {
100+
_serial.stopbits = UART_STOPBITS_2;
101+
} else {
102+
_serial.stopbits = UART_STOPBITS_1;
103+
}
104+
105+
uart_init(&_serial);
106+
uart_attach_rx_callback(&_serial, _rx_complete_irq);
107+
}
108+
109+
void HardwareSerial::end()
110+
{
111+
// wait for transmission of outgoing data
112+
flush();
113+
114+
uart_deinit(&_serial);
115+
116+
// clear any received data
117+
_serial.rx_head = _serial.rx_tail;
118+
}
119+
120+
int HardwareSerial::available(void)
121+
{
122+
return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _serial.rx_head - _serial.rx_tail)) % SERIAL_RX_BUFFER_SIZE;
123+
}
124+
125+
int HardwareSerial::peek(void)
126+
{
127+
if (_serial.rx_head == _serial.rx_tail) {
128+
return -1;
129+
} else {
130+
return _serial.rx_buff[_serial.rx_tail];
131+
}
132+
}
133+
134+
int HardwareSerial::read(void)
135+
{
136+
// if the head isn't ahead of the tail, we don't have any characters
137+
if (_serial.rx_head == _serial.rx_tail) {
138+
return -1;
139+
} else {
140+
unsigned char c = _serial.rx_buff[_serial.rx_tail];
141+
_serial.rx_tail = (rx_buffer_index_t)(_serial.rx_tail + 1) % SERIAL_RX_BUFFER_SIZE;
142+
return c;
143+
}
144+
}
145+
146+
int HardwareSerial::availableForWrite(void)
147+
{
148+
tx_buffer_index_t head = _serial.tx_head;
149+
tx_buffer_index_t tail = _serial.tx_tail;
150+
151+
if (head >= tail) return SERIAL_TX_BUFFER_SIZE - 1 - head + tail;
152+
return tail - head - 1;
153+
}
154+
155+
void HardwareSerial::flush()
156+
{
157+
// If we have never written a byte, no need to flush. This special
158+
// case is needed since there is no way to force the TXC (transmit
159+
// complete) bit to 1 during initialization
160+
if (!_written)
161+
return;
162+
163+
while((_serial.tx_head != _serial.tx_tail)) {
164+
// nop, the interrupt handler will free up space for us
165+
}
166+
// If we get here, nothing is queued anymore (DRIE is disabled) and
167+
// the hardware finished tranmission (TXC is set).
168+
}
169+
170+
size_t HardwareSerial::write(uint8_t c)
171+
{
172+
_written = true;
173+
174+
tx_buffer_index_t i = (_serial.tx_head + 1) % SERIAL_TX_BUFFER_SIZE;
175+
176+
// If the output buffer is full, there's nothing for it other than to
177+
// wait for the interrupt handler to empty it a bit
178+
while (i == _serial.tx_tail) {
179+
// nop, the interrupt handler will free up space for us
180+
}
181+
182+
_serial.tx_buff[_serial.tx_head] = c;
183+
_serial.tx_head = i;
184+
185+
if(!serial_tx_active(&_serial)) {
186+
uart_attach_tx_callback(&_serial, _tx_complete_irq);
187+
}
188+
189+
return 1;
190+
}

‎cores/arduino/HardwareSerial.h

Lines changed: 93 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
2-
Copyright (c) 2011 Arduino. All right reserved.
2+
HardwareSerial.h - Hardware serial library for Wiring
3+
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
34
45
This library is free software; you can redistribute it and/or
56
modify it under the terms of the GNU Lesser General Public
@@ -8,12 +9,16 @@
89
910
This library is distributed in the hope that it will be useful,
1011
but WITHOUT ANY WARRANTY; without even the implied warranty of
11-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12-
See the GNU Lesser General Public License for more details.
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
1314
1415
You should have received a copy of the GNU Lesser General Public
1516
License along with this library; if not, write to the Free Software
1617
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
19+
Modified 28 September 2010 by Mark Sproul
20+
Modified 14 August 2012 by Alarus
21+
Modified 3 December 2013 by Matthijs Kooijman
1722
*/
1823

1924
#ifndef HardwareSerial_h
@@ -23,18 +28,95 @@
2328

2429
#include "Stream.h"
2530

31+
// Define constants and variables for buffering incoming serial data. We're
32+
// using a ring buffer (I think), in which head is the index of the location
33+
// to which to write the next incoming character and tail is the index of the
34+
// location from which to read.
35+
// NOTE: a "power of 2" buffer size is reccomended to dramatically
36+
// optimize all the modulo operations for ring buffers.
37+
// WARNING: When buffer sizes are increased to > 256, the buffer index
38+
// variables are automatically increased in size, but the extra
39+
// atomicity guards needed for that are not implemented. This will
40+
// often work, but occasionally a race condition can occur that makes
41+
// Serial behave erratically. See https://github.com/arduino/Arduino/issues/2405
42+
#if !defined(SERIAL_TX_BUFFER_SIZE)
43+
#define SERIAL_TX_BUFFER_SIZE 64
44+
#endif
45+
#if !defined(SERIAL_RX_BUFFER_SIZE)
46+
#define SERIAL_RX_BUFFER_SIZE 64
47+
#endif
48+
#if (SERIAL_TX_BUFFER_SIZE>256)
49+
typedef uint16_t tx_buffer_index_t;
50+
#else
51+
typedef uint8_t tx_buffer_index_t;
52+
#endif
53+
#if (SERIAL_RX_BUFFER_SIZE>256)
54+
typedef uint16_t rx_buffer_index_t;
55+
#else
56+
typedef uint8_t rx_buffer_index_t;
57+
#endif
58+
59+
// Define config for Serial.begin(baud, config);
60+
#define SERIAL_5N1 0x00
61+
#define SERIAL_6N1 0x02
62+
#define SERIAL_7N1 0x04
63+
#define SERIAL_8N1 0x06
64+
#define SERIAL_5N2 0x08
65+
#define SERIAL_6N2 0x0A
66+
#define SERIAL_7N2 0x0C
67+
#define SERIAL_8N2 0x0E
68+
#define SERIAL_5E1 0x20
69+
#define SERIAL_6E1 0x22
70+
#define SERIAL_7E1 0x24
71+
#define SERIAL_8E1 0x26
72+
#define SERIAL_5E2 0x28
73+
#define SERIAL_6E2 0x2A
74+
#define SERIAL_7E2 0x2C
75+
#define SERIAL_8E2 0x2E
76+
#define SERIAL_5O1 0x30
77+
#define SERIAL_6O1 0x32
78+
#define SERIAL_7O1 0x34
79+
#define SERIAL_8O1 0x36
80+
#define SERIAL_5O2 0x38
81+
#define SERIAL_6O2 0x3A
82+
#define SERIAL_7O2 0x3C
83+
#define SERIAL_8O2 0x3E
84+
2685
class HardwareSerial : public Stream
2786
{
87+
protected:
88+
// Has any byte been written to the UART since begin()
89+
bool _written;
90+
91+
// Don't put any members after these buffers, since only the first
92+
// 32 bytes of this struct can be accessed quickly using the ldd
93+
// instruction.
94+
unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE];
95+
unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE];
96+
97+
serial_t _serial;
98+
2899
public:
29-
virtual void begin(unsigned long) = 0;
30-
virtual void end() = 0;
31-
virtual int available(void) = 0;
32-
virtual int peek(void) = 0;
33-
virtual int read(void) = 0;
34-
virtual void flush(void) = 0;
35-
virtual size_t write(uint8_t) = 0;
100+
HardwareSerial(PinName _rx, PinName _tx);
101+
void begin(unsigned long baud) { begin(baud, SERIAL_8N1); }
102+
void begin(unsigned long, uint8_t);
103+
void end();
104+
virtual int available(void);
105+
virtual int peek(void);
106+
virtual int read(void);
107+
int availableForWrite(void);
108+
virtual void flush(void);
109+
virtual size_t write(uint8_t);
110+
inline size_t write(unsigned long n) { return write((uint8_t)n); }
111+
inline size_t write(long n) { return write((uint8_t)n); }
112+
inline size_t write(unsigned int n) { return write((uint8_t)n); }
113+
inline size_t write(int n) { return write((uint8_t)n); }
36114
using Print::write; // pull in write(str) and write(buf, size) from Print
37-
virtual operator bool() = 0;
115+
operator bool() { return true; }
116+
117+
// Interrupt handlers
118+
static void _rx_complete_irq(serial_t* obj);
119+
static int _tx_complete_irq(serial_t* obj);
38120
};
39121

40122
extern void serialEventRun(void) __attribute__((weak));

‎cores/arduino/chip.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@
2525
#include "hw_config.h"
2626
#include "digital_io.h"
2727
#include "clock.h"
28-
#include "uart_emul.h"
28+
#include "hal_uart_emul.h"
2929
#include "uart.h"
30+
#include "uart_emul.h"
3031
#include "analog.h"
3132
#include "interrupt.h"
3233
#include "spi_com.h"

‎cores/arduino/stm32/uart.c

Lines changed: 387 additions & 501 deletions
Large diffs are not rendered by default.

‎cores/arduino/stm32/uart.h

Lines changed: 33 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -41,65 +41,53 @@
4141

4242
/* Includes ------------------------------------------------------------------*/
4343
#include "stm32_def.h"
44-
#include "timer.h"
44+
#include "PeripheralPins.h"
4545

4646
#ifdef __cplusplus
4747
extern "C" {
4848
#endif
4949

5050
/* Exported types ------------------------------------------------------------*/
51-
typedef enum {
52-
#if defined (STM32F0xx) || defined (STM32F3xx)
53-
USART1_E = 0,
54-
USART2_E = 1,
55-
#ifdef STM32F0xx
56-
USART4_E = 2,
57-
#endif
58-
#else
59-
USART3_E = 0,
60-
USART6_E = 1,
61-
#endif
62-
NB_UART_MANAGED,
63-
} uart_id_e;
64-
65-
typedef enum {
66-
UART1_EMUL_E = 0,
67-
NB_UART_EMUL_MANAGED
68-
} uart_emul_id_e;
51+
typedef struct serial_s serial_t;
6952

70-
typedef enum {
71-
NATIVE_UART_E = 0,
72-
EMULATED_UART_E = 1,
73-
NB_UART_OPTION
74-
} uart_option_e;
53+
struct serial_s {
54+
USART_TypeDef *uart;
55+
UART_HandleTypeDef handle;
56+
int index;
57+
uint32_t baudrate;
58+
uint32_t databits;
59+
uint32_t stopbits;
60+
uint32_t parity;
61+
PinName pin_tx;
62+
PinName pin_rx;
63+
IRQn_Type irq;
64+
uint8_t *rx_buff;
65+
uint16_t rx_head;
66+
uint16_t rx_tail;
67+
uint8_t *tx_buff;
68+
uint16_t tx_head;
69+
uint16_t tx_tail;
70+
};
7571

7672
/* Exported constants --------------------------------------------------------*/
77-
#define UART_OPTIMIZED 0 // 1 to enable optimization = do not use HAL
73+
#define TX_TIMEOUT 1000
7874

79-
#define UART_RCV_SIZE 128
75+
#define DEBUG_UART ((USART_TypeDef *) USART3)
8076

8177
/* Exported macro ------------------------------------------------------------*/
8278
/* Exported functions ------------------------------------------------------- */
83-
void uart_init(uart_id_e uart_id, uint32_t baudRate);
84-
void uart_deinit(uart_id_e uart_id);
85-
int uart_available(uart_id_e uart_id);
86-
int8_t uart_peek(uart_id_e uart_id);
87-
int8_t uart_read(uart_id_e uart_id);
88-
void uart_flush(uart_id_e uart_id);
89-
size_t uart_write(uart_id_e uart_id, uint8_t data);
79+
void uart_init(serial_t *obj);
80+
void uart_deinit(serial_t *obj);
81+
size_t uart_write(serial_t *obj, uint8_t data, uint16_t size);
82+
int uart_getc(serial_t *obj);
83+
void uart_attach_rx_callback(serial_t *obj, void (*callback)(serial_t*));
84+
void uart_attach_tx_callback(serial_t *obj, int (*callback)(serial_t*));
85+
86+
uint8_t serial_tx_active(serial_t *obj);
87+
uint8_t serial_rx_active(serial_t *obj);
88+
89+
size_t uart_debug_write(uint8_t *data, uint32_t size);
9090

91-
void uart_emul_init(uart_emul_id_e uart_id, uint32_t baudRate);
92-
void uart_emul_deinit(uart_emul_id_e uart_id);
93-
int uart_emul_available(uart_emul_id_e uart_id);
94-
int8_t uart_emul_read(uart_emul_id_e uart_id);
95-
size_t uart_emul_write(uart_emul_id_e uart_id, uint8_t data);
96-
int8_t uart_emul_peek(uart_emul_id_e uart_id);
97-
void uart_emul_flush(uart_emul_id_e uart_id);
98-
#if defined (STM32F0xx) || defined (STM32F3xx)
99-
void uart_emul_attached_handler(void (*irqHandle)(void));
100-
#else
101-
void uart_emul_attached_handler(stimer_t *obj, void (*irqHandle)(void));
102-
#endif
10391
#ifdef __cplusplus
10492
}
10593
#endif

‎cores/arduino/syscalls_stm32.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,9 @@ extern int _read(UNUSED(int file), UNUSED(char *ptr), UNUSED(int len) )
112112

113113
extern int _write( UNUSED(int file), char *ptr, int len )
114114
{
115-
int iIndex = 0;
115+
uart_debug_write(ptr, len);
116116

117-
for ( iIndex=0 ; iIndex < len ; iIndex++) {
118-
#if defined (STM32F0xx) || defined (STM32F3xx)
119-
uart_write(USART2_E, ptr[iIndex]);
120-
#else
121-
uart_write(USART3_E, ptr[iIndex]);
122-
#endif
123-
}
124-
return iIndex ;
117+
return len ;
125118
}
126119

127120
extern void _exit( int status )

‎variants/NUCLEO_F429ZI/variant.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,24 @@ const PinName digital_arduino[] = {
117117
/*
118118
* UART objects
119119
*/
120-
121-
UARTClass Serial(USART3_E); //available on PD8/PD9
122-
UARTClass Serial1(USART6_E); //available on PG14/PG9
123-
USARTClass Serial2(USART3_E); //available on PD8/PD9
120+
HardwareSerial Serial(PD9, PD8); //available on PD8/PD9 - Connected to ST-Link
121+
HardwareSerial Serial1(PG9, PG14); //available on PG14/PG9
122+
HardwareSerial Serial2(PD6, PD5); //available on PD5/PD6
124123

125124
void serialEvent() __attribute__((weak));
126125
void serialEvent() { }
127126

127+
void serialEvent1() __attribute__((weak));
128+
void serialEvent1() { }
129+
130+
void serialEvent2() __attribute__((weak));
131+
void serialEvent2() { }
132+
128133
void serialEventRun(void)
129134
{
130135
if (Serial.available()) serialEvent();
136+
if (Serial1.available()) serialEvent1();
137+
if (Serial2.available()) serialEvent2();
131138
}
132139

133140
// ----------------------------------------------------------------------------

‎variants/NUCLEO_F429ZI/variant.h

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@
3434
*----------------------------------------------------------------------------*/
3535

3636
#include "Arduino.h"
37-
#ifdef __cplusplus
38-
#include "UARTClass.h"
39-
#include "USARTClass.h"
40-
#endif
4137

4238
#ifdef __cplusplus
4339
extern "C"{
@@ -156,10 +152,27 @@ uint32_t pinNametoPinNumber(PinName p);
156152
*----------------------------------------------------------------------------*/
157153

158154
#ifdef __cplusplus
159-
extern UARTClass Serial;
160-
extern UARTClass Serial1;
161-
extern USARTClass Serial2;
162-
155+
extern HardwareSerial Serial;
156+
extern HardwareSerial Serial1;
157+
extern HardwareSerial Serial2;
158+
159+
// These serial port names are intended to allow libraries and architecture-neutral
160+
// sketches to automatically default to the correct port name for a particular type
161+
// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
162+
// the first hardware serial port whose RX/TX pins are not dedicated to another use.
163+
//
164+
// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor
165+
//
166+
// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial
167+
//
168+
// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library
169+
//
170+
// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins.
171+
//
172+
// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
173+
// pins are NOT connected to anything by default.
174+
#define SERIAL_PORT_MONITOR Serial
175+
#define SERIAL_PORT_HARDWARE Serial
163176
#endif
164177

165178
#endif /* _VARIANT_ARDUINO_STM32_ */

0 commit comments

Comments
 (0)
Please sign in to comment.