Skip to content

Commit 936a638

Browse files
eriknyquistbigdinotech
authored andcommitted
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 936a638

File tree

3 files changed

+188
-0
lines changed

3 files changed

+188
-0
lines changed

cores/arduino/mailbox.cpp

Lines changed: 163 additions & 0 deletions
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

Lines changed: 21 additions & 0 deletions
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

Lines changed: 4 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy