Skip to content

Commit fa37aaa

Browse files
committed
VirtIoSerial: support multi instances
1 parent 0e57b19 commit fa37aaa

File tree

2 files changed

+78
-29
lines changed

2 files changed

+78
-29
lines changed

cores/arduino/VirtIOSerial.cpp

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,39 +23,45 @@
2323

2424
#if defined (VIRTIOCON)
2525

26-
#include "openamp.h"
27-
#include "openamp_log.h"
28-
#include "wiring.h"
29-
#include "virtio_buffer.h"
26+
#include "VirtIOSerial.h"
27+
#if !defined(VIRTIOSERIAL_NUM)
28+
#define VIRTIOSERIAL_NUM 1
29+
#endif
3030

31-
VirtIOSerial SerialVirtIO;
32-
void serialEventVirtIO() __attribute__((weak));
31+
VirtIOSerialObj_t *VirtIOSerial_Handle[VIRTIOSERIAL_NUM] = {NULL};
3332

34-
static VIRT_UART_HandleTypeDef huart;
35-
static bool initialized = false;
36-
static bool first_message_discarded = false;
37-
static virtio_buffer_t ring;
33+
uint32_t VirtIOSerial::VirtIOSerial_index = 0;
34+
35+
// Default instance
36+
VirtIOSerial SerialVirtIO;
3837

39-
void rxCallback(VIRT_UART_HandleTypeDef *huart);
38+
void serialEventVirtIO() __attribute__((weak));
39+
VirtIOSerialObj_t *get_VirtIOSerial_obj(VIRT_UART_HandleTypeDef *huart);
4040

4141
void VirtIOSerial::begin(void)
4242
{
43-
virtio_buffer_init(&ring);
44-
if (initialized) {
43+
virtio_buffer_init(&_VirtIOSerialObj.ring);
44+
if (_VirtIOSerialObj.initialized) {
4545
return;
4646
}
4747
if (OPENAMP_Init() != 0) {
4848
Error_Handler();
4949
}
50-
if (VIRT_UART_Init(&huart) != VIRT_UART_OK) {
50+
if (VIRT_UART_Init(&_VirtIOSerialObj.handle) != VIRT_UART_OK) {
5151
Error_Handler();
5252
}
53+
54+
VirtIOSerial_index ++;
55+
_VirtIOSerialObj.__this = (void *)this;
56+
5357
/* Need to register callback for message reception by channels */
54-
if (VIRT_UART_RegisterCallback(&huart, VIRT_UART_RXCPLT_CB_ID, rxCallback) != VIRT_UART_OK) {
58+
if (VIRT_UART_RegisterCallback(&_VirtIOSerialObj.handle, VIRT_UART_RXCPLT_CB_ID, rxGenericCallback) != VIRT_UART_OK) {
5559
Error_Handler();
5660
}
57-
initialized = true;
58-
first_message_discarded = false;
61+
62+
VirtIOSerial_Handle[VirtIOSerial_index] = &_VirtIOSerialObj;
63+
_VirtIOSerialObj.initialized = true;
64+
_VirtIOSerialObj.first_message_discarded = false;
5965
}
6066

6167
void VirtIOSerial::begin(uint32_t /* baud_count */)
@@ -73,13 +79,13 @@ void VirtIOSerial::begin(uint32_t /* baud_count */, uint8_t /* config */)
7379
void VirtIOSerial::end()
7480
{
7581
OPENAMP_DeInit();
76-
virtio_buffer_init(&ring);
77-
initialized = false;
82+
virtio_buffer_init(&_VirtIOSerialObj.ring);
83+
_VirtIOSerialObj.initialized = false;
7884
}
7985

8086
int VirtIOSerial::available(void)
8187
{
82-
return virtio_buffer_read_available(&ring);
88+
return virtio_buffer_read_available(&_VirtIOSerialObj.ring);
8389
}
8490

8591
int VirtIOSerial::availableForWrite()
@@ -91,9 +97,9 @@ int VirtIOSerial::availableForWrite()
9197

9298
int VirtIOSerial::peek(void)
9399
{
94-
if (virtio_buffer_read_available(&ring) > 0) {
100+
if (virtio_buffer_read_available(&_VirtIOSerialObj.ring) > 0) {
95101
uint8_t tmp;
96-
virtio_buffer_peek(&ring, &tmp, 1);
102+
virtio_buffer_peek(&_VirtIOSerialObj.ring, &tmp, 1);
97103
return tmp;
98104
} else {
99105
return -1;
@@ -134,7 +140,7 @@ size_t VirtIOSerial::write(uint8_t ch)
134140
// until all bytes are sent.
135141
size_t VirtIOSerial::write(const uint8_t *buffer, size_t size)
136142
{
137-
if (VIRT_UART_Transmit(&huart, const_cast<uint8_t *>(buffer), size) == VIRT_UART_ERROR) {
143+
if (VIRT_UART_Transmit(&_VirtIOSerialObj.handle, const_cast<uint8_t *>(buffer), size) == VIRT_UART_ERROR) {
138144
// This error usually happens when rpmsg is not ready for
139145
return 0;
140146
}
@@ -148,26 +154,44 @@ void VirtIOSerial::flush(void)
148154
return;
149155
}
150156

151-
void rxCallback(VIRT_UART_HandleTypeDef *huart)
157+
void VirtIOSerial::rxGenericCallback(VIRT_UART_HandleTypeDef *huart)
152158
{
159+
VirtIOSerialObj_t *obj = get_VirtIOSerial_obj(huart);
160+
VirtIOSerial *VIOS = (VirtIOSerial *)(obj->__this);
161+
162+
VIOS->rxCallback(huart);
163+
}
164+
165+
void VirtIOSerial::rxCallback(VIRT_UART_HandleTypeDef *huart)
166+
{
167+
153168
// Linux host must send a dummy data first to finish initialization of rpmsg
154169
// on the coprocessor side. This message should be discarded.
155170
// run_arduino_gen.sh script will send dummy data: "DUMMY".
156171
// See: https://github.com/OpenAMP/open-amp/issues/182
157172
// See: run_arduino_gen.sh
158-
if (!first_message_discarded) {
173+
if (!_VirtIOSerialObj.first_message_discarded) {
159174
huart->RxXferSize = 0;
160-
first_message_discarded = true;
175+
_VirtIOSerialObj.first_message_discarded = true;
161176
}
162177

163178
/* copy received msg in a variable to sent it back to master processor in main infinite loop*/
164-
size_t size = min(huart->RxXferSize, virtio_buffer_write_available(&ring));
179+
size_t size = min(huart->RxXferSize, virtio_buffer_write_available(&_VirtIOSerialObj.ring));
165180
while (size > 0) {
166-
size -= virtio_buffer_write(&ring, huart->pRxBuffPtr, size);
181+
size -= virtio_buffer_write(&_VirtIOSerialObj.ring, huart->pRxBuffPtr, size);
167182
}
168-
if (virtio_buffer_write_available(&ring) >= RPMSG_BUFFER_SIZE) {
183+
if (virtio_buffer_write_available(&_VirtIOSerialObj.ring) >= RPMSG_BUFFER_SIZE) {
169184
MAILBOX_Notify_Rx_Buf_Free();
170185
}
171186
}
172187

188+
/* Aim of the function is to get _VirtIOSerialObj pointer using huart pointer */
189+
/* Highly inspired from magical linux kernel's "container_of" */
190+
VirtIOSerialObj_t *get_VirtIOSerial_obj(VIRT_UART_HandleTypeDef *huart)
191+
{
192+
VirtIOSerialObj_t *obj;
193+
obj = (VirtIOSerialObj_t *)((char *)huart - offsetof(VirtIOSerialObj_t, handle));
194+
return (obj);
195+
}
196+
173197
#endif /* VIRTIOCON */

cores/arduino/VirtIOSerial.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,26 @@
2626

2727
#if defined (VIRTIOCON)
2828
#include "Stream.h"
29+
#include "openamp.h"
30+
#include "openamp_log.h"
31+
#include "wiring.h"
32+
#include "virtio_buffer.h"
2933

3034
//================================================================================
3135
// Serial over OpenAmp
36+
37+
// This structure is used to be able to get VirtIOSerial instance (C++ class)
38+
// from handler (C structure) specially for interrupt management
39+
typedef struct {
40+
// Those 2 first fields must remain in this order at the beginning of the structure
41+
void *__this;
42+
VIRT_UART_HandleTypeDef handle;
43+
bool initialized;
44+
bool first_message_discarded;
45+
virtio_buffer_t ring;
46+
} VirtIOSerialObj_t;
47+
48+
3249
class VirtIOSerial : public Stream {
3350
public:
3451
void begin(void);
@@ -44,11 +61,19 @@ class VirtIOSerial : public Stream {
4461
virtual size_t write(uint8_t);
4562
virtual size_t write(const uint8_t *buffer, size_t size);
4663
virtual void flush(void);
64+
65+
static void rxGenericCallback(VIRT_UART_HandleTypeDef *huart);
66+
void rxCallback(VIRT_UART_HandleTypeDef *huart);
67+
4768
using Print::write; // pull in write(str) from Print
4869
operator bool(void)
4970
{
5071
return true;
5172
}
73+
74+
private:
75+
static uint32_t VirtIOSerial_index;
76+
VirtIOSerialObj_t _VirtIOSerialObj;
5277
};
5378

5479
extern VirtIOSerial SerialVirtIO;

0 commit comments

Comments
 (0)