Skip to content

Commit 1e20130

Browse files
committed
Add IPM (Inter-Processor-Mailbox) driver to cores/arduino
This allows the mailbox to be used for Serial (instead of polling shared memory). The CurieMailbox library, in the codk-m-corelibs branch, will not require any API changes, but will now just be a thin wrapper around the methods in mailbox.cpp
1 parent 50f30b3 commit 1e20130

File tree

3 files changed

+188
-0
lines changed

3 files changed

+188
-0
lines changed

cores/arduino/mailbox.cpp

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#include <string.h>
2+
#include "interrupt.h"
3+
#include "scss_registers.h"
4+
#include "mailbox.h"
5+
6+
#define CHANNEL_STS_MASK 0x1
7+
#define CHANNEL_INT_MASK 0x2
8+
#define CTRL_WORD_MASK 0x7FFFFFFF
9+
#define CHALL_STATUS_MASK 0xFFFF
10+
#define CHANNEL_STS_BITS (CHANNEL_STS_MASK | CHANNEL_INT_MASK)
11+
12+
/* Mailbox channel status register */
13+
#define IO_REG_MAILBOX_CHALL_STS (SCSS_REGISTER_BASE + 0xAC0)
14+
15+
typedef struct mbox_channel mbox_channel_t;
16+
typedef struct mbox_intmask mbox_intmask_t;
17+
18+
/* Represents the registers for a single mailbox channel */
19+
struct mbox_channel {
20+
uint32_t ctrl;
21+
uint32_t data[CHANNEL_DATA_WORDS];
22+
uint32_t sts;
23+
};
24+
25+
/* Mailbox interrupt mask; right now we only care about the
26+
* second byte, for SS mailbox interrupts (one bit per mailbox channel) */
27+
struct mbox_intmask {
28+
uint8_t lmt_intmask;
29+
uint8_t ss_intmask;
30+
uint8_t lmt_halt;
31+
uint8_t ss_halt;
32+
};
33+
34+
static volatile mbox_intmask_t *intmask;
35+
static volatile mbox_channel_t *mbox;
36+
static void (*callbacks[NUM_MAILBOX_CHANNELS])(CurieMailboxMsg);
37+
38+
void mailbox_register (int channel, void(*callback)(CurieMailboxMsg))
39+
{
40+
if (channel >= 0 && channel < NUM_MAILBOX_CHANNELS) {
41+
callbacks[channel] = callback;
42+
}
43+
}
44+
45+
void mailbox_unregister (int channel)
46+
{
47+
if (channel >= 0 && channel < NUM_MAILBOX_CHANNELS) {
48+
callbacks[channel] = 0;
49+
}
50+
}
51+
52+
void mailbox_disable_receive (int channel)
53+
{
54+
intmask->ss_intmask |= 1 << channel;
55+
}
56+
57+
void mailbox_enable_receive (int channel)
58+
{
59+
intmask->ss_intmask &= ~(1 << channel);
60+
}
61+
62+
static void do_callback (int channel, CurieMailboxMsg& msg)
63+
{
64+
void (*cb)(CurieMailboxMsg) = callbacks[channel];
65+
if (cb) {
66+
cb(msg);
67+
}
68+
}
69+
70+
static void mailbox_read (int channel, CurieMailboxMsg& msg)
71+
{
72+
unsigned int i;
73+
74+
/* Copy channel data into CurieMailboxMsg object */
75+
msg.id = mbox[channel].ctrl & CTRL_WORD_MASK;
76+
msg.channel = channel;
77+
78+
for (i = 0; i < CHANNEL_DATA_WORDS; ++i) {
79+
msg.data[i] = mbox[channel].data[i];
80+
}
81+
82+
/* Clear channel status & interrupt flags */
83+
mbox[channel].sts |= CHANNEL_STS_BITS;
84+
}
85+
86+
void mailbox_write (CurieMailboxMsg& msg)
87+
{
88+
int i;
89+
uint32_t key;
90+
91+
/* Can't write if channel status flag is set */
92+
while ((mbox[msg.channel].sts & CHANNEL_STS_MASK));
93+
key = interrupt_lock();
94+
95+
/* Poplate channel payload */
96+
mbox[msg.channel].ctrl |= (msg.id & CTRL_WORD_MASK);
97+
for (i = 0; i < CHANNEL_DATA_WORDS; ++i) {
98+
mbox[msg.channel].data[i] = msg.data[i];
99+
}
100+
101+
/* Trigger interupt to host */
102+
mbox[msg.channel].ctrl |= ~(CTRL_WORD_MASK);
103+
104+
/* Wait for HW to set the channel status bit */
105+
while (!(mbox[msg.channel].sts & CHANNEL_STS_MASK));
106+
107+
/* Wait for destination processor to clear channel status bit */
108+
while ((mbox[msg.channel].sts & CHANNEL_STS_MASK));
109+
interrupt_unlock(key);
110+
}
111+
112+
static uint16_t get_chall_sts (void)
113+
{
114+
return MMIO_REG_VAL(IO_REG_MAILBOX_CHALL_STS) & CHALL_STATUS_MASK;
115+
}
116+
117+
static void mailbox_isr (void)
118+
{
119+
int i;
120+
uint32_t sts;
121+
CurieMailboxMsg msg;
122+
123+
sts = get_chall_sts();
124+
/* Get channel number */
125+
for (i = 0; i < NUM_MAILBOX_CHANNELS; ++i) {
126+
if (sts & (1 << (i * 2 + 1))) {
127+
break;
128+
}
129+
}
130+
131+
mailbox_read(i, msg);
132+
do_callback(i, msg);
133+
}
134+
135+
static void mailbox_hardware_init (void)
136+
{
137+
int i;
138+
139+
for (i = 0; i < NUM_MAILBOX_CHANNELS; ++i) {
140+
mbox[i].sts &= ~(CHANNEL_STS_BITS);
141+
}
142+
}
143+
144+
static void mailbox_interrupts_init (bool master)
145+
{
146+
interrupt_disable(SOC_MBOX_INTERRUPT);
147+
148+
/* Mask SS mailbox interrupts for all channels;
149+
* Unmasking is done by enableReceive */
150+
intmask->ss_intmask = 0xFF;
151+
152+
if (master) mailbox_hardware_init();
153+
interrupt_connect(SOC_MBOX_INTERRUPT, mailbox_isr);
154+
interrupt_enable(SOC_MBOX_INTERRUPT);
155+
}
156+
157+
void mailbox_init (bool master)
158+
{
159+
intmask = (mbox_intmask_t *)IO_REG_MAILBOX_INT_MASK;
160+
mbox = (mbox_channel_t *)IO_REG_MAILBOX_BASE;
161+
memset(callbacks, 0, sizeof(callbacks));
162+
mailbox_interrupts_init(master);
163+
}

cores/arduino/mailbox.h

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef _MAILBOX_H_
2+
#define _MAILBOX_H_
3+
4+
#define NUM_MAILBOX_CHANNELS 8
5+
#define CHANNEL_DATA_WORDS 4
6+
7+
class CurieMailboxMsg {
8+
public:
9+
uint32_t data[CHANNEL_DATA_WORDS];
10+
uint32_t id;
11+
int channel = 0;
12+
};
13+
14+
void mailbox_init (bool master);
15+
void mailbox_register (int channel, void(*callback)(CurieMailboxMsg));
16+
void mailbox_unregister (int channel);
17+
void mailbox_enable_receive (int channel);
18+
void mailbox_disable_receive (int channel);
19+
void mailbox_write(CurieMailboxMsg& msg);
20+
21+
#endif

variants/arduino_101/variant.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "cfw_platform.h"
2323
#include "platform.h"
24+
#include "mailbox.h"
2425

2526
// Add for debug corelib
2627
#ifdef CONFIGURE_DEBUG_CORELIB_ENABLED
@@ -254,6 +255,9 @@ void initVariant( void )
254255
*SYS_CLK_CTL |= 1 << CCU_RTC_CLK_DIV_EN;
255256

256257
cfw_platform_init();
258+
259+
/* Ready the mailbox for use (but don't initialise HW; x86 does that) */
260+
mailbox_init(false);
257261

258262
// Add for debug corelib
259263
#ifdef CONFIGURE_DEBUG_CORELIB_ENABLED

0 commit comments

Comments
 (0)