Skip to content

Commit 7bc16b6

Browse files
committed
Use IPM for cdc-acm
-use the IPM instead of shared memory for passing data between ARC and x86 cores for cdc-acm.
1 parent be920e7 commit 7bc16b6

File tree

4 files changed

+90
-30
lines changed

4 files changed

+90
-30
lines changed

cores/arduino/CDCSerialClass.cpp

+81-25
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,35 @@
3030
#include "wiring_digital.h"
3131
#include "variant.h"
3232

33-
#define CDCACM_FIXED_DELAY 120
33+
#define CDC_MAILBOX_TX_CHANNEL 7
34+
#define CDC_MAILBOX_RX_CHANNEL 6
3435

3536
extern void CDCSerial_Handler(void);
3637
extern void serialEventRun1(void) __attribute__((weak));
3738
extern void serialEvent1(void) __attribute__((weak));
3839

40+
static void cdc_mbox_isr(CurieMailboxMsg msg)
41+
{
42+
char *rxbuffptr = (char*)msg.data;
43+
int new_head;
44+
for(int i = 0; i < MBOX_BYTES; i++)
45+
{
46+
if((uint8_t)(*(rxbuffptr+i)) != '\0')
47+
{
48+
new_head = (Serial._rx_buffer->head +1) % CDCACM_BUFFER_SIZE;
49+
if(new_head != Serial._rx_buffer->tail)
50+
{
51+
Serial._rx_buffer->data[Serial._rx_buffer->head] = *(rxbuffptr+i);
52+
Serial._rx_buffer->head = new_head;
53+
}
54+
}
55+
else
56+
{
57+
break;
58+
}
59+
}
60+
}
61+
3962
// Constructors ////////////////////////////////////////////////////////////////
4063

4164
CDCSerialClass::CDCSerialClass(uart_init_info *info)
@@ -47,9 +70,9 @@ CDCSerialClass::CDCSerialClass(uart_init_info *info)
4770

4871
void CDCSerialClass::setSharedData(struct cdc_acm_shared_data *cdc_acm_shared_data)
4972
{
50-
this->_shared_data = cdc_acm_shared_data;
51-
this->_rx_buffer = cdc_acm_shared_data->rx_buffer;
52-
this->_tx_buffer = cdc_acm_shared_data->tx_buffer;
73+
_shared_data = cdc_acm_shared_data;
74+
_rx_buffer = cdc_acm_shared_data->rx_buffer;
75+
_tx_buffer = cdc_acm_shared_data->tx_buffer;
5376
}
5477

5578
void CDCSerialClass::begin(const uint32_t dwBaudRate)
@@ -73,7 +96,9 @@ void CDCSerialClass::init(const uint32_t dwBaudRate, const uint8_t modeReg)
7396
* Empty the Rx buffer but don't touch Tx buffer: it is drained by the
7497
* LMT one way or another */
7598
_rx_buffer->tail = _rx_buffer->head;
76-
99+
100+
mailbox_register(CDC_MAILBOX_RX_CHANNEL, cdc_mbox_isr);
101+
mailbox_enable_receive(CDC_MAILBOX_RX_CHANNEL);
77102
_shared_data->device_open = true;
78103
}
79104

@@ -84,12 +109,10 @@ void CDCSerialClass::end( void )
84109

85110
int CDCSerialClass::available( void )
86111
{
87-
#define SBS CDCACM_BUFFER_SIZE
88-
89112
if (!_shared_data->device_open)
90113
return (0);
91114
else
92-
return (int)(SBS + _rx_buffer->head - _rx_buffer->tail) % SBS;
115+
return (int)(CDCACM_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % CDCACM_BUFFER_SIZE;
93116
}
94117

95118
int CDCSerialClass::availableForWrite(void)
@@ -131,28 +154,61 @@ void CDCSerialClass::flush( void )
131154
}
132155
}
133156

134-
size_t CDCSerialClass::write( const uint8_t uc_data )
157+
size_t CDCSerialClass::write(uint8_t uc_data )
135158
{
136-
uint32_t retries = 2;
159+
CurieMailboxMsg cdcacm_msg;
137160

138161
if (!_shared_data->device_open || !_shared_data->host_open)
139162
return(0);
140163

141-
do {
142-
int i = (uint32_t)(_tx_buffer->head + 1) % CDCACM_BUFFER_SIZE;
143-
// if we should be storing the received character into the location
144-
// just before the tail (meaning that the head would advance to the
145-
// current location of the tail), we're about to overflow the buffer
146-
// and so we don't write the character or advance the head.
147-
if (i != _tx_buffer->tail) {
148-
_tx_buffer->data[_tx_buffer->head] = uc_data;
149-
_tx_buffer->head = i;
150-
151-
// Just use a fixed delay to make it compatible with the CODK-M based firmware
152-
delayMicroseconds(CDCACM_FIXED_DELAY);
153-
break;
164+
cdcacm_msg.channel = CDC_MAILBOX_TX_CHANNEL;
165+
cdcacm_msg.data[0] = uc_data;
166+
mailbox_write(cdcacm_msg);
167+
delayMicroseconds(_writeDelayUsec);
168+
return 1;
169+
}
170+
171+
size_t CDCSerialClass::write(const uint8_t *buffer, size_t size)
172+
{
173+
CurieMailboxMsg cdcacm_msg;
174+
cdcacm_msg.channel = CDC_MAILBOX_TX_CHANNEL;
175+
if (!_shared_data->device_open || !_shared_data->host_open)
176+
return(0);
177+
178+
int msg_len = size;
179+
180+
for(int i = 0;msg_len > 0; msg_len -= MBOX_BYTES, i += MBOX_BYTES)
181+
{
182+
/* Copy data into mailbox message */
183+
memset(cdcacm_msg.data, 0, MBOX_BYTES);
184+
if(msg_len >= MBOX_BYTES)
185+
{
186+
memcpy(cdcacm_msg.data, buffer+i, MBOX_BYTES);
154187
}
155-
} while (retries--);
188+
else
189+
{
190+
memcpy(cdcacm_msg.data, buffer+i, msg_len);
191+
}
192+
/* Write to mailbox*/
193+
mailbox_write(cdcacm_msg);
194+
}
156195

157-
return 1;
196+
// Mimick the throughput of a typical UART by throttling the data
197+
// flow according to the configured baud rate
198+
delayMicroseconds(_writeDelayUsec * size);
199+
200+
return size;
201+
}
202+
203+
size_t CDCSerialClass::write(const char *str)
204+
{
205+
if (str == NULL) return 0;
206+
CurieMailboxMsg cdcacm_msg;
207+
cdcacm_msg.channel = CDC_MAILBOX_TX_CHANNEL;
208+
if (!_shared_data->device_open || !_shared_data->host_open)
209+
return(0);
210+
211+
int msg_len = strlen(str);
212+
213+
return write((const uint8_t *)str, msg_len);
158214
}

cores/arduino/CDCSerialClass.h

+7-4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "HardwareSerial.h"
2727
#include "platform.h"
2828
#include "wiring.h"
29+
#include "mailbox.h"
2930

3031
#include <board.h>
3132
#include <uart.h>
@@ -36,6 +37,10 @@ class CDCSerialClass : public HardwareSerial
3637
CDCSerialClass(uart_init_info *info);
3738

3839
void setSharedData(struct cdc_acm_shared_data *cdc_acm_shared_data);
40+
41+
struct cdc_acm_shared_data *_shared_data;
42+
struct cdc_ring_buffer *_rx_buffer;
43+
struct cdc_ring_buffer *_tx_buffer;
3944

4045
void begin(const uint32_t dwBaudRate);
4146
void begin(const uint32_t dwBaudRate, const uint8_t config);
@@ -46,6 +51,8 @@ class CDCSerialClass : public HardwareSerial
4651
int read(void);
4752
void flush(void);
4853
size_t write(const uint8_t c);
54+
size_t write(const char *str);
55+
size_t write(const uint8_t *buffer, size_t size);
4956
using Print::write; // pull in write(str) and write(buf, size) from Print
5057

5158
operator bool() {
@@ -58,10 +65,6 @@ class CDCSerialClass : public HardwareSerial
5865
protected:
5966
void init(const uint32_t dwBaudRate, const uint8_t config);
6067

61-
struct cdc_acm_shared_data *_shared_data;
62-
struct cdc_ring_buffer *_rx_buffer;
63-
struct cdc_ring_buffer *_tx_buffer;
64-
6568
uart_init_info *info;
6669
uint32_t _writeDelayUsec;
6770
uint32_t _dwId;

cores/arduino/Print.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class Print
4747
void clearWriteError() { setWriteError(0); }
4848

4949
virtual size_t write(uint8_t) = 0;
50-
size_t write(const char *str) {
50+
virtual size_t write(const char *str) {
5151
if (str == NULL) return 0;
5252
return write((const uint8_t *)str, strlen(str));
5353
}

cores/arduino/mailbox.h

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#define NUM_MAILBOX_CHANNELS 8
55
#define CHANNEL_DATA_WORDS 4
6+
#define MBOX_BYTES 16
67

78
class CurieMailboxMsg {
89
public:

0 commit comments

Comments
 (0)