235 lines
4.3 KiB
C++
235 lines
4.3 KiB
C++
|
#include "pxt.h"
|
||
|
#include <stdarg.h>
|
||
|
|
||
|
PXT_ABI(__aeabi_dadd)
|
||
|
PXT_ABI(__aeabi_dcmplt)
|
||
|
PXT_ABI(__aeabi_dcmpgt)
|
||
|
PXT_ABI(__aeabi_dsub)
|
||
|
PXT_ABI(__aeabi_ddiv)
|
||
|
PXT_ABI(__aeabi_dmul)
|
||
|
|
||
|
extern "C" void target_panic(int error_code)
|
||
|
{
|
||
|
// wait for serial to flush
|
||
|
wait_us(300000);
|
||
|
microbit_panic(error_code);
|
||
|
}
|
||
|
|
||
|
extern "C" void target_reset()
|
||
|
{
|
||
|
microbit_reset();
|
||
|
}
|
||
|
|
||
|
namespace pxt {
|
||
|
|
||
|
MicroBit uBit;
|
||
|
MicroBitEvent lastEvent;
|
||
|
|
||
|
void platform_init() {}
|
||
|
|
||
|
void platform_init();
|
||
|
void usb_init();
|
||
|
|
||
|
struct FreeList {
|
||
|
FreeList *next;
|
||
|
};
|
||
|
|
||
|
static void initCodal() {
|
||
|
|
||
|
uBit.init();
|
||
|
|
||
|
// repeat error 4 times and restart as needed
|
||
|
microbit_panic_timeout(4);
|
||
|
}
|
||
|
|
||
|
void dumpDmesg() {}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// An adapter for the API expected by the run-time.
|
||
|
// ---------------------------------------------------------------------------
|
||
|
|
||
|
// We have the invariant that if [dispatchEvent] is registered against the DAL
|
||
|
// for a given event, then [handlersMap] contains a valid entry for that
|
||
|
// event.
|
||
|
void dispatchEvent(MicroBitEvent e) {
|
||
|
lastEvent = e;
|
||
|
|
||
|
auto curr = findBinding(e.source, e.value);
|
||
|
auto value = fromInt(e.value);
|
||
|
if (curr)
|
||
|
runAction1(curr->action, value);
|
||
|
|
||
|
curr = findBinding(e.source, DEVICE_EVT_ANY);
|
||
|
if (curr)
|
||
|
runAction1(curr->action, value);
|
||
|
}
|
||
|
|
||
|
void registerWithDal(int id, int event, Action a, int flags) {
|
||
|
// first time?
|
||
|
if (!findBinding(id, event))
|
||
|
uBit.messageBus.listen(id, event, dispatchEvent, flags);
|
||
|
setBinding(id, event, a);
|
||
|
}
|
||
|
|
||
|
void fiberDone(void *a) {
|
||
|
decr((Action)a);
|
||
|
release_fiber();
|
||
|
}
|
||
|
|
||
|
void releaseFiber() {
|
||
|
release_fiber();
|
||
|
}
|
||
|
|
||
|
void sleep_ms(unsigned ms) {
|
||
|
fiber_sleep(ms);
|
||
|
}
|
||
|
|
||
|
void sleep_us(uint64_t us) {
|
||
|
wait_us(us);
|
||
|
}
|
||
|
|
||
|
void forever_stub(void *a) {
|
||
|
while (true) {
|
||
|
runAction0((Action)a);
|
||
|
fiber_sleep(20);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void runForever(Action a) {
|
||
|
if (a != 0) {
|
||
|
incr(a);
|
||
|
create_fiber(forever_stub, (void *)a);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void runInParallel(Action a) {
|
||
|
if (a != 0) {
|
||
|
incr(a);
|
||
|
create_fiber((void (*)(void *))runAction0, (void *)a, fiberDone);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void waitForEvent(int id, int event) {
|
||
|
fiber_wait_for_event(id, event);
|
||
|
}
|
||
|
|
||
|
void initRuntime() {
|
||
|
initCodal();
|
||
|
platform_init();
|
||
|
}
|
||
|
|
||
|
//%
|
||
|
unsigned afterProgramPage() {
|
||
|
unsigned ptr = (unsigned)&bytecode[0];
|
||
|
ptr += programSize();
|
||
|
ptr = (ptr + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
|
||
|
int current_time_ms() {
|
||
|
return system_timer_current_time();
|
||
|
}
|
||
|
|
||
|
static void logwriten(const char *msg, int l)
|
||
|
{
|
||
|
uBit.serial.send((uint8_t*)msg, l);
|
||
|
}
|
||
|
|
||
|
static void logwrite(const char *msg)
|
||
|
{
|
||
|
logwriten(msg, strlen(msg));
|
||
|
}
|
||
|
|
||
|
|
||
|
static void writeNum(char *buf, uint32_t n, bool full)
|
||
|
{
|
||
|
int i = 0;
|
||
|
int sh = 28;
|
||
|
while (sh >= 0)
|
||
|
{
|
||
|
int d = (n >> sh) & 0xf;
|
||
|
if (full || d || sh == 0 || i)
|
||
|
{
|
||
|
buf[i++] = d > 9 ? 'A' + d - 10 : '0' + d;
|
||
|
}
|
||
|
sh -= 4;
|
||
|
}
|
||
|
buf[i] = 0;
|
||
|
}
|
||
|
|
||
|
static void logwritenum(uint32_t n, bool full, bool hex)
|
||
|
{
|
||
|
char buff[20];
|
||
|
|
||
|
if (hex)
|
||
|
{
|
||
|
writeNum(buff, n, full);
|
||
|
logwrite("0x");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
itoa(n, buff);
|
||
|
}
|
||
|
|
||
|
logwrite(buff);
|
||
|
}
|
||
|
|
||
|
void vdebuglog(const char *format, va_list ap)
|
||
|
{
|
||
|
const char *end = format;
|
||
|
|
||
|
while (*end)
|
||
|
{
|
||
|
if (*end++ == '%')
|
||
|
{
|
||
|
logwriten(format, end - format - 1);
|
||
|
uint32_t val = va_arg(ap, uint32_t);
|
||
|
switch (*end++)
|
||
|
{
|
||
|
case 'c':
|
||
|
logwriten((const char *)&val, 1);
|
||
|
break;
|
||
|
case 'd':
|
||
|
logwritenum(val, false, false);
|
||
|
break;
|
||
|
case 'x':
|
||
|
logwritenum(val, false, true);
|
||
|
break;
|
||
|
case 'p':
|
||
|
case 'X':
|
||
|
logwritenum(val, true, true);
|
||
|
break;
|
||
|
case 's':
|
||
|
logwrite((char *)(void *)val);
|
||
|
break;
|
||
|
case '%':
|
||
|
logwrite("%");
|
||
|
break;
|
||
|
default:
|
||
|
logwrite("???");
|
||
|
break;
|
||
|
}
|
||
|
format = end;
|
||
|
}
|
||
|
}
|
||
|
logwriten(format, end - format);
|
||
|
logwrite("\n");
|
||
|
}
|
||
|
|
||
|
void debuglog(const char *format, ...)
|
||
|
{
|
||
|
va_list arg;
|
||
|
va_start(arg, format);
|
||
|
vdebuglog(format, arg);
|
||
|
va_end(arg);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
} // namespace pxt
|
||
|
|
||
|
|
||
|
|