mbv: add async app, sorta works
This commit is contained in:
141
mbv/apps/async/main.cc
Normal file
141
mbv/apps/async/main.cc
Normal file
@@ -0,0 +1,141 @@
|
||||
#include "async.h"
|
||||
#include "buffer.h"
|
||||
#include "gpio.h"
|
||||
#include "intc.h"
|
||||
#include "interrupts.h"
|
||||
#include "pol0.h"
|
||||
#include "timer.h"
|
||||
#include "trace.h"
|
||||
#include "uart.h"
|
||||
#include "uart_async.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using async::AwaitableType;
|
||||
Timer* timer0;
|
||||
|
||||
void Uart0Isr() {
|
||||
ToggleLed(7);
|
||||
HandleUartIsr();
|
||||
}
|
||||
|
||||
void Timer0Isr() {
|
||||
SetLed(6);
|
||||
__builtin_trap();
|
||||
}
|
||||
|
||||
void SetupUart() {
|
||||
InitUarts();
|
||||
|
||||
intc::SetIsr(UART0_IRQN, Uart0Isr);
|
||||
intc::SetIrqEnabled(UART0_IRQN, true);
|
||||
}
|
||||
|
||||
void SetupTimer() {
|
||||
timer0 = Timer::Instance(TIMER0_BASE);
|
||||
timer0->SetupAsWdt(100'000 * 1000);
|
||||
timer0->EnableT1();
|
||||
|
||||
intc::SetIsr(TIMER0_IRQN, Timer0Isr);
|
||||
intc::SetIrqEnabled(TIMER0_IRQN, true);
|
||||
}
|
||||
|
||||
void SetupInterrupts() {
|
||||
intc::EnableInterrupts();
|
||||
SetExternalInterruptHandler(intc::InterruptHandler);
|
||||
EnableExternalInterrupts();
|
||||
EnableInterrupts(true);
|
||||
}
|
||||
|
||||
async::task<> echo() {
|
||||
async::task<uint8_t> reader = UartReadLoop();
|
||||
async::gimme<std::span<const std::byte>> feeder;
|
||||
async::task<> writer = UartWriteLoop(feeder);
|
||||
writer.h.resume(); // advance to first yield
|
||||
while (1) {
|
||||
SetLed(1);
|
||||
uint8_t c = co_await reader;
|
||||
ClearLed(1);
|
||||
ToggleLed(2);
|
||||
feeder.feed(std::as_bytes(std::span{&c, 1}));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#define XUL_SR_RX_FIFO_FULL 0x02 /* receive FIFO full */
|
||||
#define XUL_SR_RX_FIFO_VALID_DATA 0x01 /* data in receive FIFO */
|
||||
|
||||
int main() {
|
||||
SetupUart();
|
||||
UartWriteCrash("uart setup done\r\n");
|
||||
SetupTimer();
|
||||
UartWriteCrash("timer setup done\r\n");
|
||||
|
||||
gpio0->data = 0;
|
||||
SetupInterrupts();
|
||||
|
||||
async::schedule(echo().h);
|
||||
|
||||
UartWriteCrash("init done. starting main loop\r\n");
|
||||
|
||||
async::main_loop([]() {
|
||||
static int cnt = 0;
|
||||
timer0->Pet();
|
||||
if ((cnt++ % 100000) == 0) {
|
||||
ToggleLed(0);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
// should never get here
|
||||
}
|
||||
|
||||
/// stdlib stuff
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "itoa.h"
|
||||
#include "lock.h"
|
||||
|
||||
#ifndef SBRK_STATS
|
||||
#define SBRK_STATS 0
|
||||
#endif
|
||||
|
||||
extern unsigned char _heap_begin, _heap_end;
|
||||
|
||||
extern "C" void* _sbrk(int increment) {
|
||||
static unsigned char* heap = &_heap_begin;
|
||||
unsigned char* prev_heap = heap;
|
||||
if (heap + increment >= &_heap_end) {
|
||||
UartWriteCrash("Heap overflow!\r\n");
|
||||
return reinterpret_cast<void*>(-1);
|
||||
}
|
||||
heap += increment;
|
||||
return prev_heap;
|
||||
}
|
||||
|
||||
extern "C" int _gettimeofday(struct timeval* tv, void* tzvp) {
|
||||
(void)tzvp;
|
||||
uint32_t ticks = timer0->GetT1Ticks();
|
||||
tv->tv_sec = ticks / 100000000;
|
||||
tv->tv_usec = (ticks % 100000000) / 100;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" uint8_t __atomic_exchange_1(volatile void* ptr, uint8_t val,
|
||||
int memorder) {
|
||||
(void)memorder;
|
||||
auto* dest = reinterpret_cast<volatile uint8_t*>(ptr);
|
||||
bool ret;
|
||||
|
||||
{
|
||||
InterruptLock lock;
|
||||
ret = *dest;
|
||||
*dest = val;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user