Skip to content

Commit 67609c0

Browse files
committed
aa
1 parent d7074c5 commit 67609c0

File tree

10 files changed

+991
-1
lines changed

10 files changed

+991
-1
lines changed

cores/arduino/UART.cpp

+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
UART.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+
Created: 09.11.2017 07:29:09
20+
Author: M44307
21+
*/
22+
23+
#include <stdlib.h>
24+
#include <stdio.h>
25+
#include <string.h>
26+
#include <inttypes.h>
27+
#include "Arduino.h"
28+
29+
#include "UART.h"
30+
31+
32+
#include "include/StreamMock.h"
33+
34+
/*
35+
void serialEventRun(void)
36+
{
37+
#if defined(HAVE_HWSERIAL0)
38+
if (Serial0_available && serialEvent && Serial0_available()) serialEvent();
39+
#endif
40+
#if defined(HAVE_HWSERIAL1)
41+
if (Serial1_available && serialEvent1 && Serial1_available()) serialEvent1();
42+
#endif
43+
#if defined(HAVE_HWSERIAL2)
44+
if (Serial2_available && serialEvent2 && Serial2_available()) serialEvent2();
45+
#endif
46+
#if defined(HAVE_HWSERIAL3)
47+
if (Serial3_available && serialEvent3 && Serial3_available()) serialEvent3();
48+
#endif
49+
}
50+
*/
51+
// macro to guard critical sections when needed for large TX buffer sizes
52+
#if (SERIAL_TX_BUFFER_SIZE > 256)
53+
#define TX_BUFFER_ATOMIC ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
54+
#else
55+
#define TX_BUFFER_ATOMIC
56+
#endif
57+
58+
// Actual interrupt handlers //////////////////////////////////////////////////////////////
59+
60+
void UartClass::_tx_data_empty_irq(void)
61+
{
62+
;
63+
}
64+
65+
// To invoke data empty "interrupt" via a call, use this method
66+
void UartClass::_poll_tx_data_empty(void)
67+
{
68+
;
69+
}
70+
71+
// Public Methods //////////////////////////////////////////////////////////////
72+
73+
void UartClass::begin(unsigned long baud, uint16_t config)
74+
{
75+
// Make sure no transmissions are ongoing and USART is disabled in case begin() is called by accident
76+
// without first calling end()
77+
if(_written) {
78+
this->end();
79+
}
80+
81+
// Setup port mux
82+
83+
int32_t baud_setting = 0;
84+
85+
//Make sure global interrupts are disabled during initialization
86+
//uint8_t oldSREG = SREG;
87+
88+
baud_setting = (((8 * F_CPU) / baud) + 1) / 2;
89+
90+
_written = false;
91+
92+
int8_t sigrow_val = 0;
93+
baud_setting += (baud_setting * sigrow_val) / 1024;
94+
95+
}
96+
97+
void UartClass::end()
98+
{
99+
// wait for transmission of outgoing data
100+
flush();
101+
102+
// Disable receiver and transmitter as well as the RX complete and
103+
// data register empty interrupts.
104+
// clear any received data
105+
_rx_buffer_head = _rx_buffer_tail;
106+
107+
_written = false;
108+
}
109+
110+
int UartClass::available(void)
111+
{
112+
return mockstream.available();
113+
// return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) % SERIAL_RX_BUFFER_SIZE;
114+
}
115+
116+
int UartClass::peek(void)
117+
{
118+
/* if (_rx_buffer_head == _rx_buffer_tail) {
119+
return -1;
120+
} else {
121+
return _rx_buffer[_rx_buffer_tail];
122+
}*/
123+
return mockstream.peek();
124+
}
125+
126+
int UartClass::read(void)
127+
{
128+
// if the head isn't ahead of the tail, we don't have any characters
129+
/*if (_rx_buffer_head == _rx_buffer_tail) {
130+
return -1;
131+
} else {
132+
unsigned char c = _rx_buffer[_rx_buffer_tail];
133+
_rx_buffer_tail = (rx_buffer_index_t)(_rx_buffer_tail + 1) % SERIAL_RX_BUFFER_SIZE;
134+
return c;
135+
}*/
136+
return mockstream.read();
137+
}
138+
139+
int UartClass::availableForWrite(void)
140+
{
141+
/*tx_buffer_index_t head;
142+
tx_buffer_index_t tail;
143+
144+
TX_BUFFER_ATOMIC {
145+
head = _tx_buffer_head;
146+
tail = _tx_buffer_tail;
147+
}
148+
if (head >= tail) return SERIAL_TX_BUFFER_SIZE - 1 - head + tail;
149+
return tail - head - 1;*/
150+
return 0;
151+
}
152+
153+
void UartClass::flush()
154+
{
155+
// If we have never written a byte, no need to flush. This special
156+
// case is needed since there is no way to force the TXCIF (transmit
157+
// complete) bit to 1 during initialization
158+
if (!_written) {
159+
return;
160+
}
161+
162+
163+
164+
165+
166+
}
167+
168+
size_t UartClass::write(uint8_t c)
169+
{
170+
_written = true;
171+
172+
// If the buffer and the data register is empty, just write the byte
173+
// to the data register and be done. This shortcut helps
174+
// significantly improve the effective data rate at high (>
175+
// 500kbit/s) bit rates, where interrupt overhead becomes a slowdown.
176+
177+
178+
179+
180+
//Check if we are inside an ISR already (could be from by a source other than UART),
181+
// in which case the UART ISRs will be blocked.
182+
mockstream.write(c);
183+
184+
return 1;
185+
}

cores/arduino/UART.h

+206
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/*
2+
UART.h - 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 28 September 2010 by Mark Sproul
20+
Modified 14 August 2012 by Alarus
21+
Modified 3 December 2013 by Matthijs Kooijman
22+
*/
23+
24+
#pragma once
25+
26+
#include <inttypes.h>
27+
#include "api/HardwareSerial.h"
28+
#include "pins_arduino.h"
29+
#include "include/StreamMock.h"
30+
31+
32+
using namespace arduino;
33+
34+
// Define constants and variables for buffering incoming serial data. We're
35+
// using a ring buffer (I think), in which head is the index of the location
36+
// to which to write the next incoming character and tail is the index of the
37+
// location from which to read.
38+
// NOTE: a "power of 2" buffer size is reccomended to dramatically
39+
// optimize all the modulo operations for ring buffers.
40+
// WARNING: When buffer sizes are increased to > 256, the buffer index
41+
// variables are automatically increased in size, but the extra
42+
// atomicity guards needed for that are not implemented. This will
43+
// often work, but occasionally a race condition can occur that makes
44+
// Serial behave erratically. See https://github.com/arduino/Arduino/issues/2405
45+
46+
//#if !defined(SERIAL_TX_BUFFER_SIZE)
47+
48+
49+
50+
#if !defined(SERIAL_TX_BUFFER_SIZE)
51+
#if ((RAMEND - RAMSTART) < 1023)
52+
#define SERIAL_TX_BUFFER_SIZE 16
53+
#else
54+
#define SERIAL_TX_BUFFER_SIZE 64
55+
#endif
56+
#endif
57+
#if !defined(SERIAL_RX_BUFFER_SIZE)
58+
#if ((RAMEND - RAMSTART) < 1023)
59+
#define SERIAL_RX_BUFFER_SIZE 16
60+
#else
61+
#define SERIAL_RX_BUFFER_SIZE 64
62+
#endif
63+
#endif
64+
#if (SERIAL_TX_BUFFER_SIZE>256)
65+
typedef uint16_t tx_buffer_index_t;
66+
#else
67+
typedef uint8_t tx_buffer_index_t;
68+
#endif
69+
#if (SERIAL_RX_BUFFER_SIZE>256)
70+
typedef uint16_t rx_buffer_index_t;
71+
#else
72+
typedef uint8_t rx_buffer_index_t;
73+
#endif
74+
75+
76+
77+
#define USART_CMODE_ASYNCHRONOUS_gc 1
78+
#define USART_CHSIZE_5BIT_gc 0
79+
80+
81+
82+
/* Universal Synchronous and Asynchronous Receiver and Transmitter */
83+
84+
typedef volatile uint8_t register8_t;
85+
typedef volatile uint16_t register16_t;
86+
typedef volatile uint32_t register32_t;
87+
88+
#define _WORDREGISTER(regname) __extension__ union { register16_t regname; struct { register8_t regname##L; register8_t regname##H; }; }
89+
90+
typedef struct USART_struct
91+
{
92+
register8_t RXDATAL; /* Receive Data Low Byte */
93+
register8_t RXDATAH; /* Receive Data High Byte */
94+
register8_t TXDATAL; /* Transmit Data Low Byte */
95+
register8_t TXDATAH; /* Transmit Data High Byte */
96+
register8_t STATUS; /* Status */
97+
register8_t CTRLA; /* Control A */
98+
register8_t CTRLB; /* Control B */
99+
register8_t CTRLC; /* Control C */
100+
_WORDREGISTER(BAUD); /* Baud Rate */
101+
register8_t CTRLD; /* Control D */
102+
register8_t DBGCTRL; /* Debug Control */
103+
register8_t EVCTRL; /* Event Control */
104+
register8_t TXPLCTRL; /* IRCOM Transmitter Pulse Length Control */
105+
register8_t RXPLCTRL; /* IRCOM Receiver Pulse Length Control */
106+
register8_t reserved_1[1];
107+
} USART_t;
108+
109+
class UartClass : public HardwareSerial
110+
{
111+
112+
protected:
113+
StreamMock mockstream;
114+
volatile USART_t * const _hwserial_module;
115+
116+
volatile uint8_t const _hwserial_rx_pin;
117+
volatile uint8_t const _hwserial_tx_pin;
118+
119+
volatile uint8_t const _uart_mux;
120+
121+
// Has any byte been written to the UART since begin()
122+
bool _written;
123+
124+
volatile rx_buffer_index_t _rx_buffer_head;
125+
volatile rx_buffer_index_t _rx_buffer_tail;
126+
volatile tx_buffer_index_t _tx_buffer_head;
127+
volatile tx_buffer_index_t _tx_buffer_tail;
128+
129+
volatile uint8_t _hwserial_dre_interrupt_vect_num;
130+
volatile uint8_t _hwserial_dre_interrupt_elevated;
131+
volatile uint8_t _prev_lvl1_interrupt_vect;
132+
133+
// Don't put any members after these buffers, since only the first
134+
// 32 bytes of this struct can be accessed quickly using the ldd
135+
// instruction.
136+
unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE];
137+
unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE];
138+
139+
public:
140+
//UartClass(){;}
141+
//inline UartClass(volatile USART_t *hwserial_module, uint8_t hwserial_rx_pin, uint8_t hwserial_tx_pin, uint8_t dre_vect_num, uint8_t uart_mux);
142+
UartClass(
143+
volatile USART_t *hwserial_module,
144+
volatile uint8_t hwserial_rx_pin,
145+
volatile uint8_t hwserial_tx_pin,
146+
volatile uint8_t hwserial_dre_interrupt_vect_num,
147+
volatile uint8_t uart_mux) :
148+
_hwserial_module(hwserial_module),
149+
_hwserial_rx_pin(hwserial_rx_pin),
150+
_hwserial_tx_pin(hwserial_tx_pin),
151+
_uart_mux(uart_mux),
152+
_rx_buffer_head(0), _rx_buffer_tail(0),
153+
_tx_buffer_head(0), _tx_buffer_tail(0),
154+
_hwserial_dre_interrupt_vect_num(hwserial_dre_interrupt_vect_num),
155+
_hwserial_dre_interrupt_elevated(0),
156+
_prev_lvl1_interrupt_vect(0)
157+
{
158+
};
159+
160+
161+
void begin(unsigned long baud) { begin(baud, SERIAL_8N1); }
162+
void begin(unsigned long, uint16_t);
163+
void end();
164+
virtual int available(void);
165+
virtual int peek(void);
166+
virtual int read(void);
167+
virtual int availableForWrite(void);
168+
virtual void flush(void);
169+
virtual size_t write(uint8_t);
170+
inline size_t write(unsigned long n) { return write((uint8_t)n); };
171+
inline size_t write(long n) { return write((uint8_t)n); };
172+
inline size_t write(unsigned int n) { return write((uint8_t)n); };
173+
inline size_t write(int n) { return write((uint8_t)n); };
174+
using Print::write; // pull in write(str) and write(buf, size) from Print
175+
explicit operator bool() { return true; }
176+
bool operator! () { return true; };
177+
178+
179+
void bind(UartClass& ser) {bound = &ser; }
180+
181+
// Interrupt handlers - Not intended to be called externally
182+
inline void _rx_complete_irq(void);
183+
void _tx_data_empty_irq(void);
184+
private:
185+
void _poll_tx_data_empty(void);
186+
UartClass* bound = NULL;
187+
};
188+
189+
#if defined(HWSERIAL0)
190+
extern UartClass Serial;
191+
#define HAVE_HWSERIAL0
192+
#endif
193+
#if defined(HWSERIAL1)
194+
extern UartClass Serial1;
195+
#define HAVE_HWSERIAL1
196+
#endif
197+
#if defined(HWSERIAL2)
198+
extern UartClass Serial2;
199+
#define HAVE_HWSERIAL2
200+
#endif
201+
#if defined(HWSERIAL3)
202+
extern UartClass Serial3;
203+
#define HAVE_HWSERIAL3
204+
#endif
205+
206+

0 commit comments

Comments
 (0)