Skip to content

Commit a6473d1

Browse files
Dan-LightsourceBogdan Pricop
authored and
Bogdan Pricop
committed
CDC-ACM: move allocation of cdc-acm shared buffers to LMT
LMT shall now be responsible for allocating shared data buffers used to exchange CDC-ACM data between ARC and LMT. Defined a revised set of structures to allow the pointers to be passed from LMT to ARC during initialisation. NOTE THAT THIS DEPENDS ON A CORRESPONDING CHANGE IN THUNDERDOME FIRMWARE Signed-off-by: Dan O'Donovan <dan@emutex.com>
1 parent 6f196e1 commit a6473d1

File tree

4 files changed

+83
-70
lines changed

4 files changed

+83
-70
lines changed

cores/arduino/CDCSerialClass.cpp

+48-23
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,20 @@ extern void serialEvent1(void) __attribute__((weak));
3737

3838
// Constructors ////////////////////////////////////////////////////////////////
3939

40-
CDCSerialClass::CDCSerialClass( uart_init_info *info, RingBuffer *pRx_buffer,
41-
RingBuffer *pTx_buffer )
40+
CDCSerialClass::CDCSerialClass(uart_init_info *info)
4241
{
4342
this->info = info;
44-
this->_rx_buffer = pRx_buffer;
45-
this->_tx_buffer = pTx_buffer;
4643
}
4744

4845
// Public Methods //////////////////////////////////////////////////////////////
4946

47+
void CDCSerialClass::setSharedData(struct cdc_acm_shared_data *cdc_acm_shared_data)
48+
{
49+
this->_shared_data = cdc_acm_shared_data;
50+
this->_rx_buffer = cdc_acm_shared_data->rx_buffer;
51+
this->_tx_buffer = cdc_acm_shared_data->tx_buffer;
52+
}
53+
5054
void CDCSerialClass::begin(const uint32_t dwBaudRate)
5155
{
5256
begin(dwBaudRate, (uint8_t)SERIAL_8N1 );
@@ -55,37 +59,43 @@ void CDCSerialClass::begin(const uint32_t dwBaudRate)
5559
void CDCSerialClass::begin(const uint32_t dwBaudRate, const uint8_t config)
5660
{
5761
init(dwBaudRate, config );
58-
opened = true;
5962
}
6063

6164

6265
void CDCSerialClass::init(const uint32_t dwBaudRate, const uint8_t modeReg)
6366
{
67+
/* Set a per-byte write delay approximately equal to the time it would
68+
* take to clock out a byte on a standard UART at this baud rate */
69+
_writeDelayUsec = 8000000 / dwBaudRate;
70+
6471
// Make sure both ring buffers are initialized back to empty.
65-
_rx_buffer->_iHead = _rx_buffer->_iTail = 0;
66-
_tx_buffer->_iHead = _tx_buffer->_iTail = 0;
72+
_rx_buffer->head = _rx_buffer->tail = 0;
73+
_tx_buffer->head = _tx_buffer->tail = 0;
74+
75+
_shared_data->device_open = true;
6776
}
6877

6978
void CDCSerialClass::end( void )
7079
{
71-
opened = false;
72-
_rx_buffer->_iHead = 0;
73-
_rx_buffer->_iTail = 0;
80+
_shared_data->device_open = false;
81+
82+
_rx_buffer->head = 0;
83+
_rx_buffer->tail = 0;
7484
}
7585

7686
int CDCSerialClass::available( void )
7787
{
7888
#define SBS SERIAL_BUFFER_SIZE
79-
return (int)(SBS + _rx_buffer->_iHead - _rx_buffer->_iTail) % SBS;
89+
return (int)(SBS + _rx_buffer->head - _rx_buffer->tail) % SBS;
8090
}
8191

8292
int CDCSerialClass::availableForWrite(void)
8393
{
84-
if (!opened)
94+
if (!_shared_data->device_open || !_shared_data->host_open)
8595
return(0);
8696

87-
int head = _tx_buffer->_iHead;
88-
int tail = _tx_buffer->_iTail;
97+
int head = _tx_buffer->head;
98+
int tail = _tx_buffer->tail;
8999

90100
if (head >= tail)
91101
return SERIAL_BUFFER_SIZE - head + tail - 1;
@@ -94,37 +104,52 @@ int CDCSerialClass::availableForWrite(void)
94104

95105
int CDCSerialClass::peek(void)
96106
{
97-
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
107+
if ( _rx_buffer->head == _rx_buffer->tail )
98108
return -1;
99109

100-
return _rx_buffer->_aucBuffer[_rx_buffer->_iTail];
110+
return _rx_buffer->data[_rx_buffer->tail];
101111
}
102112

103113
int CDCSerialClass::read( void )
104114
{
105-
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
115+
if ( _rx_buffer->head == _rx_buffer->tail )
106116
return -1;
107117

108-
uint8_t uc = _rx_buffer->_aucBuffer[_rx_buffer->_iTail];
109-
_rx_buffer->_iTail = (_rx_buffer->_iTail + 1) % SERIAL_BUFFER_SIZE;
118+
uint8_t uc = _rx_buffer->data[_rx_buffer->tail];
119+
_rx_buffer->tail = (_rx_buffer->tail + 1) % SERIAL_BUFFER_SIZE;
110120
return uc;
111121
}
112122

113123
void CDCSerialClass::flush( void )
114124
{
115-
while (_tx_buffer->_iTail != _tx_buffer->_iHead) {
125+
while (_tx_buffer->tail != _tx_buffer->head) {
116126
delayMicroseconds(1);
117127
}
118128
}
119129

120130
size_t CDCSerialClass::write( const uint8_t uc_data )
121131
{
122-
if (!opened)
132+
uint32_t retries = 1;
133+
134+
if (!_shared_data->device_open || !_shared_data->host_open)
123135
return(0);
124136

125137
do {
126-
_tx_buffer->store_char(uc_data);
127-
} while (_tx_buffer->_buffer_overflow);
138+
int i = (uint32_t)(_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE;
139+
// if we should be storing the received character into the location
140+
// just before the tail (meaning that the head would advance to the
141+
// current location of the tail), we're about to overflow the buffer
142+
// and so we don't write the character or advance the head.
143+
if (i != _tx_buffer->tail) {
144+
_tx_buffer->data[_tx_buffer->head] = uc_data;
145+
_tx_buffer->head = i;
146+
147+
// Mimick the throughput of a typical UART by throttling the data
148+
// flow according to the configured baud rate
149+
delayMicroseconds(_writeDelayUsec);
150+
break;
151+
}
152+
} while (retries--);
128153

129154
return 1;
130155
}

cores/arduino/CDCSerialClass.h

+9-8
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,17 @@
2424
#define _CFWSERIAL_CLASS_
2525

2626
#include "HardwareSerial.h"
27-
#include "RingBuffer.h"
27+
#include "platform.h"
2828

2929
#include <board.h>
3030
#include <uart.h>
3131

3232
class CDCSerialClass : public HardwareSerial
3333
{
3434
public:
35-
CDCSerialClass(uart_init_info *info, RingBuffer *pRx_buffer, RingBuffer *pTx_buffer );
35+
CDCSerialClass(uart_init_info *info);
36+
37+
void setSharedData(struct cdc_acm_shared_data *cdc_acm_shared_data);
3638

3739
void begin(const uint32_t dwBaudRate);
3840
void begin(const uint32_t dwBaudRate, const uint8_t config);
@@ -45,19 +47,18 @@ class CDCSerialClass : public HardwareSerial
4547
size_t write(const uint8_t c);
4648
using Print::write; // pull in write(str) and write(buf, size) from Print
4749

48-
49-
operator bool() { return true; }; // CDCSerial always active
50+
operator bool() { return (_shared_data && _shared_data->host_open); };
5051

5152
protected:
5253
void init(const uint32_t dwBaudRate, const uint8_t config);
5354

54-
RingBuffer *_rx_buffer;
55-
RingBuffer *_tx_buffer;
55+
struct cdc_acm_shared_data *_shared_data;
56+
struct cdc_ring_buffer *_rx_buffer;
57+
struct cdc_ring_buffer *_tx_buffer;
5658

5759
uart_init_info *info;
60+
uint32_t _writeDelayUsec;
5861
uint32_t _dwId;
59-
uint32_t opened;
60-
6162
};
6263

6364
#endif // _CDCSerial_CLASS_

system/libarc32_edu/framework/include/platform.h

+22-21
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,27 @@
3939
#define CPU_ID_HOST 3
4040
#define NUM_CPU 4
4141

42+
#define SERIAL_BUFFER_SIZE 256
43+
44+
struct cdc_ring_buffer
45+
{
46+
/** Ring buffer data */
47+
uint8_t data[SERIAL_BUFFER_SIZE];
48+
/** Ring buffer head pointer, modified by producer */
49+
int head;
50+
/** Ring buffer head pointer, modified by consumer */
51+
int tail;
52+
};
53+
4254
struct cdc_acm_shared_data {
43-
uint8_t * rx_buffer;
44-
int * rx_head;
45-
int * rx_tail;
46-
uint8_t * tx_buffer;
47-
int * tx_head;
48-
int * tx_tail;
49-
uint32_t serial_buffer_size;
55+
/** Ring buffer to pass CDC-ACM data from LMT to ARC */
56+
struct cdc_ring_buffer *rx_buffer;
57+
/** Ring buffer to pass CDC-ACM data from ARC to LMT */
58+
struct cdc_ring_buffer *tx_buffer;
59+
/** Boolean flag set by LMT when CDC-ACM host connection is opened */
60+
int host_open;
61+
/** Boolean flag set by ARC when CDC-ACM endpoint connection is opened */
62+
int device_open;
5063
};
5164

5265
/**
@@ -91,21 +104,9 @@ struct platform_shared_block_ {
91104

92105
/* Pointer to shared structure used by CDC-ACM.
93106
*
94-
* The ARC core is responsible for allocating memory and initialising the
107+
* The QRK core is responsible for allocating memory and initialising the
95108
* pointers of this structure.
96-
* The LMT core counts on ARC to find valid pointers in place.
97-
*
98-
* It embeds pointers to following:
99-
* Rx Buffer and its Head and Tail
100-
* Tx Buffer and its Head and Tail
101-
*
102-
* Tx Buffer = buffer used by ARC to Send data out to CDC-ACM
103-
* Rx Buffer = buffer used by LMT to put data read from CDC-ACM
104-
*
105-
* LMT updates:
106-
* Rx Head index every time an acm_read and a rx_buffer write are
107-
* successfully done.
108-
* Tx Tail index when some bytes are queued to CDC-ACM.
109+
* The ARC core counts on QRK to find valid pointers in place.
109110
*/
110111
struct cdc_acm_shared_data * cdc_acm_buffers;
111112
};

variants/intel_edu_x/variant.cpp

+4-18
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,9 @@ uint32_t sizeof_g_APinDescription;
9898

9999
// Serial - CDC-ACM port
100100

101-
RingBuffer rx_buffer_cdc;
102-
RingBuffer tx_buffer_cdc;
103101
uart_init_info info_cdc;
104102

105-
CDCSerialClass Serial(&info_cdc, &rx_buffer_cdc, &tx_buffer_cdc);
103+
CDCSerialClass Serial(&info_cdc);
106104

107105
void serialEvent() __attribute__((weak));
108106
void serialEvent() { }
@@ -219,28 +217,16 @@ void variantAdcInit(void)
219217

220218
void initVariant( void )
221219
{
220+
/* Initialise CDC-ACM shared buffers pointers, provided by LMT */
221+
Serial.setSharedData(shared_data->cdc_acm_buffers);
222+
222223
/* For now, lets enable clocks for all interfaces we need
223224
* TODO - Consider only enabling as needed later to reduce power consumption
224225
*/
225226
variantGpioInit();
226227
variantPwmInit();
227228
variantAdcInit();
228229

229-
/* TODO: REMOVE ME! */
230-
Serial1.begin(115200);
231-
232-
/* Initialise CDC-ACM shared buffers pointers */
233-
shared_data->cdc_acm_buffers =
234-
(struct cdc_acm_shared_data *)malloc(sizeof(struct cdc_acm_shared_data));
235-
236-
shared_data->cdc_acm_buffers->rx_buffer = rx_buffer_cdc._aucBuffer;
237-
shared_data->cdc_acm_buffers->rx_head = &(rx_buffer_cdc._iHead);
238-
shared_data->cdc_acm_buffers->rx_tail = &(rx_buffer_cdc._iTail);
239-
shared_data->cdc_acm_buffers->tx_buffer = tx_buffer_cdc._aucBuffer;
240-
shared_data->cdc_acm_buffers->tx_head = &(tx_buffer_cdc._iHead);
241-
shared_data->cdc_acm_buffers->tx_tail = &(tx_buffer_cdc._iTail);
242-
shared_data->cdc_acm_buffers->serial_buffer_size = SERIAL_BUFFER_SIZE;
243-
244230
cfw_platform_init();
245231
}
246232

0 commit comments

Comments
 (0)