Skip to content

Commit 7ef4fe8

Browse files
committed
add RP2040 PIO Serial
1 parent 12b7248 commit 7ef4fe8

File tree

12 files changed

+1060
-133
lines changed

12 files changed

+1060
-133
lines changed

src/madflight/bar/BarGizmoHP203B.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class BarGizmoHP203B: public BarGizmo {
4848
//only read device when dev_rdy and pa_rdy
4949
//FIXME: put timeout on waiting for pa_rdy
5050
const uint8_t mask = HP203B_INT_SRC_DEV_RDY | HP203B_INT_SRC_DEV_RDY;
51-
if( dev->readReg(HP203B_INT_SRC) & mask != mask) return false;
51+
if( (dev->readReg(HP203B_INT_SRC) & mask) != mask) return false;
5252

5353
uint8_t d[6];
5454
dev->readReg(HP203B_READ_PT, d, 6); //READ_PT pressure [Pa] + temp [0.01*C]

src/madflight/hal/RP2040/RP2040_SerialIRQ.h renamed to src/madflight/hal/RP2040/Serial/SerialIRQ.h

Lines changed: 4 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*==========================================================================================
2-
RP2040_SerialIRQ.h - High Performance RP2040 Buffered RX/TX UART Driver
2+
SerialIRQ.h - High Performance RP2 Buffered RX/TX UART Driver
33
44
MIT License
55
@@ -28,79 +28,7 @@ SOFTWARE.
2828
// https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_uart/include/hardware/uart.h
2929
// https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_uart/uart.c
3030

31-
32-
// Ring buffer class for SerialIRQ
33-
class SerialRingBuf {
34-
35-
private:
36-
public:
37-
uint8_t *buf;
38-
uint32_t bufsize = 0; //buffer can hold bufsize-1 bytes
39-
uint32_t head = 0; //previous push position
40-
uint32_t tail = 0; //next pop position
41-
42-
public:
43-
void begin(uint8_t *buf, uint32_t bufsize) {
44-
this->buf = buf;
45-
this->bufsize = bufsize;
46-
clear();
47-
}
48-
49-
//clear buffer
50-
void clear() {
51-
tail = head;
52-
}
53-
54-
//number of bytes in buffer
55-
uint32_t len() {
56-
return (head >= tail ? head - tail : bufsize + head - tail);
57-
}
58-
59-
//number of bytes free in buffer
60-
uint32_t available() {
61-
return bufsize - 1 - len();
62-
}
63-
64-
//increase a buffer position - used in IRQ so store in RAM
65-
uint32_t __not_in_flash_func(inc)( uint32_t v) {
66-
return (v < bufsize - 1 ? v + 1 : 0 );
67-
}
68-
69-
//push a byte in to the buffer - used in IRQ so store in RAM
70-
size_t __not_in_flash_func(push)(uint8_t c) {
71-
uint32_t next = inc(head);
72-
if(next == tail) return 0; //buffer full
73-
buf[head] = c;
74-
head = next;
75-
return 1;
76-
}
77-
78-
//pop a byte from the buffer - used in IRQ so store in RAM
79-
size_t __not_in_flash_func(pop)(uint8_t *c) {
80-
if(head == tail) return 0; //buffer empty
81-
*c = buf[tail];
82-
tail = inc(tail);
83-
return 1;
84-
}
85-
86-
/*
87-
//optimized push
88-
void push(uint8_t *data, size_t len) {
89-
if(head + len < bufsize && (head >= tail || head + len < tail )) {
90-
memcpy(buf+head+1, data, len);
91-
head+=len;
92-
return len;
93-
}else{
94-
//TODO - optimize using two memcpy() calls
95-
size_t push_len = 0;
96-
for(int i=0;i<len;i++)
97-
push_len += push(data[i]);
98-
return push_len;
99-
}
100-
}
101-
*/
102-
103-
};
31+
#include "SerialRingBuf.h"
10432

10533
//global buffers for two uarts
10634
SerialRingBuf _uart_rxbuf[2];
@@ -220,7 +148,7 @@ class SerialIRQ {
220148
}
221149

222150
uint32_t availableForWrite() {
223-
return tbuf->available();
151+
return tbuf->free_space();
224152
}
225153

226154
int read() {
@@ -258,4 +186,4 @@ class SerialIRQ {
258186
size_t readBytes(uint8_t *buf, size_t len) {
259187
return read(buf, len);
260188
}
261-
};
189+
};
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*==========================================================================================
2+
SerialPioIRQ.h - High Performance RP2 Buffered RX/TX PIO UART Driver
3+
4+
MIT License
5+
6+
Copyright (c) 2025 https://github.com/qqqlab
7+
8+
Permission is hereby granted, free of charge, to any person obtaining a copy
9+
of this software and associated documentation files (the "Software"), to deal
10+
in the Software without restriction, including without limitation the rights
11+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
copies of the Software, and to permit persons to whom the Software is
13+
furnished to do so, subject to the following conditions:
14+
15+
The above copyright notice and this permission notice shall be included in all
16+
copies or substantial portions of the Software.
17+
18+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
SOFTWARE.
25+
==========================================================================================*/
26+
#pragma once
27+
28+
#include "UartTxPioIrq.h"
29+
#include "UartRxPioIrq.h"
30+
31+
// Serial PIO IRQ class
32+
class SerialPioIRQ {
33+
private:
34+
UartTxPioIrq tx;
35+
UartRxPioIrq rx;
36+
public:
37+
SerialPioIRQ(uint8_t txpin, uint8_t rxpin, uint16_t txbuflen = 256, uint16_t rxbuflen = 256) : tx(txpin, txbuflen), rx(rxpin, rxbuflen) {}
38+
39+
void begin(int baud) {
40+
tx.begin(baud);
41+
rx.begin(baud);
42+
}
43+
44+
int available() {
45+
return rx.available();
46+
}
47+
48+
int availableForWrite() {
49+
return tx.availableForWrite();
50+
}
51+
52+
int readBytes(uint8_t *buf, int len) {
53+
return rx.read(buf, len);
54+
}
55+
56+
int write(uint8_t *buf, int len) {
57+
return tx.write(buf, len);
58+
}
59+
};
60+
61+
62+
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*==========================================================================================
2+
SerialRingBuf.h - Ring Buffer for Serial I/O
3+
4+
MIT License
5+
6+
Copyright (c) 2025 https://github.com/qqqlab
7+
8+
Permission is hereby granted, free of charge, to any person obtaining a copy
9+
of this software and associated documentation files (the "Software"), to deal
10+
in the Software without restriction, including without limitation the rights
11+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
copies of the Software, and to permit persons to whom the Software is
13+
furnished to do so, subject to the following conditions:
14+
15+
The above copyright notice and this permission notice shall be included in all
16+
copies or substantial portions of the Software.
17+
18+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
SOFTWARE.
25+
==========================================================================================*/
26+
27+
#pragma once
28+
29+
// Ring buffer class
30+
class SerialRingBuf {
31+
32+
private:
33+
public:
34+
uint8_t *buf;
35+
uint16_t bufsize = 0; //buffer can hold bufsize-1 bytes
36+
volatile uint16_t head = 0; //previous push position - NOTE: volatile to prevent compiler to optimize things away
37+
volatile uint16_t tail = 0; //next pop position - NOTE: volatile to prevent compiler to optimize things away
38+
39+
public:
40+
void begin(uint8_t *buf, uint16_t bufsize) {
41+
this->buf = buf;
42+
this->bufsize = bufsize;
43+
clear();
44+
}
45+
46+
//clear buffer
47+
void clear() {
48+
tail = head;
49+
}
50+
51+
//number of bytes in buffer
52+
uint16_t len() {
53+
return (head >= tail ? head - tail : bufsize + head - tail);
54+
}
55+
56+
//number of bytes free in buffer
57+
uint16_t free_space() {
58+
return bufsize - 1 - len();
59+
}
60+
61+
//push 1 byte in to the buffer - used in IRQ so store in RAM
62+
uint16_t __not_in_flash_func(push)(uint8_t c) {
63+
uint16_t next = inc(head);
64+
if(next == tail) return 0; //buffer full
65+
buf[head] = c;
66+
head = next;
67+
return 1;
68+
}
69+
70+
//push up to data_len bytes
71+
uint16_t push(const uint8_t *data, size_t data_len)
72+
{
73+
//exit if no data
74+
if (data_len == 0 || data == nullptr) return 0;
75+
76+
//get number of bytes available in ringbuf
77+
volatile uint16_t avail = free_space(); //volatile to prevent race conditions, available space could increase while this thread is processing
78+
if(data_len > avail) data_len = avail;
79+
80+
if(data_len == 0) return 0;
81+
82+
//get number of bytes before buf wraps
83+
uint16_t remaining = bufsize - head; //no need for volatile here, this thread is the only thread writing to head - NOTE: remaining can be larger than data_len, but this is normal
84+
85+
if (data_len <= remaining) {
86+
memcpy(buf + head, data, data_len);
87+
if(data_len == remaining) {
88+
//Serial.printf("nowrap1 data_len=%d head=%d tail=%d remaining=%d\n", data_len, head, tail, remaining);
89+
head = 0;
90+
}else{
91+
//Serial.printf("nowrap2 data_len=%d head=%d tail=%d remaining=%d\n", data_len, head, tail, remaining);
92+
head += data_len;
93+
}
94+
}else{
95+
//Serial.printf("wrap data_len=%d head=%d tail=%d remaining=%d\n", data_len, head, tail, remaining);
96+
memcpy(buf + head, data, remaining);
97+
memcpy(buf, data + remaining, data_len - remaining);
98+
head = data_len - remaining;
99+
}
100+
return data_len;
101+
}
102+
103+
//pop 1 byte from the buffer - used in IRQ so store in RAM
104+
uint16_t __not_in_flash_func(pop)(uint8_t *c) {
105+
if(head == tail) return 0; //buffer empty
106+
*c = buf[tail];
107+
tail = inc(tail);
108+
return 1;
109+
}
110+
111+
//pop up to data_len bytes
112+
uint16_t pop(uint8_t *data, size_t data_len)
113+
{
114+
//exit if no data
115+
if (data_len == 0 || data == nullptr) return 0;
116+
117+
//get number of bytes in ringbuf
118+
volatile uint16_t avail = len(); //volatile to prevent race conditions, number of bytes in ringbuf could increase while this thread is processing
119+
if(data_len > avail) data_len = avail;
120+
121+
if(data_len == 0) return 0;
122+
123+
//get number of bytes before buf wraps
124+
uint16_t remaining = bufsize - tail; //no need for volatile here, this thread is the only thread writing to tail - NOTE: remaining can be larger than data_len, but this is normal
125+
126+
if (data_len <= remaining) {
127+
memcpy(data, buf + tail, data_len);
128+
if(data_len == remaining) {
129+
//Serial.printf("nowrap1 data_len=%d head=%d tail=%d remaining=%d\n", data_len, head, tail, remaining);
130+
tail = 0;
131+
}else{
132+
//Serial.printf("nowrap2 data_len=%d head=%d tail=%d remaining=%d\n", data_len, head, tail, remaining);
133+
tail += data_len;
134+
}
135+
}else{
136+
//Serial.printf("wrap data_len=%d head=%d tail=%d remaining=%d\n", data_len, head, tail, remaining);
137+
memcpy(data, buf + tail, remaining);
138+
memcpy(data + remaining, buf, data_len - remaining);
139+
tail = data_len - remaining;
140+
}
141+
return data_len;
142+
}
143+
144+
private:
145+
//increase a buffer position - used in IRQ so store in RAM
146+
uint16_t __not_in_flash_func(inc)( uint16_t v) {
147+
return (v < bufsize - 1 ? v + 1 : 0 );
148+
}
149+
};

0 commit comments

Comments
 (0)