| template <typename T, std::size_t N>
struct queue {
std::array<T, N> data;
volatile std::size_t put_idx;
volatile std::size_t get_idx;
async_flag put_flag;
async_flag get_flag;
constexpr std::size_t _inc(std::size_t n) {
return n + 1 < N ? n + 1 : 0;
}
bool empty() {
return put_idx == get_idx;
}
bool full() {
return _inc(put_idx) == get_idx;
}
bool put(T v) {
if(full()) {
return false;
}
data[put_idx] = v;
put_idx = _inc(put_idx);
put_flag.set();
return true;
}
bool get(T& v) {
if(empty()) {
return false;
}
v = data[get_idx];
get_idx = _inc(get_idx);
get_flag.set();
return true;
}
async<> async_put(T v) {
while(!put(v)) {
co_await get_flag;
}
}
async<T> async_get() {
T v;
while(!get(v)) {
co_await put_flag;
}
co_return v;
}
};
queue<char, 8> uart1_rx;
queue<char, 8> uart1_tx;
template <>
void interrupt::handler<interrupt::irq::USART1>() {
if(USART1.reg.SR & (1 << 5)) { // RXNE
char c = USART1.reg.DR;
//printf("USART1 ISR RX: %c\n", c);
uart1_rx.put(c);
}
if(USART1.reg.SR & (1 << 7)) { // TXE
char c;
if(uart1_tx.get(c)) {
USART1.reg.DR = c;
} else {
USART1.reg.CR1 &= ~(1 << 7); // TXEIE
}
}
}
struct shell_io_t {
async<char> getchar() {
return uart1_rx.async_get();
}
async<> putchar(char c) {
co_await uart1_tx.async_put(c);
USART1.reg.CR1 |= 1 << 7; // TXEIE
}
async<> print(std::string_view s) {
for(auto c : s) {
co_await putchar(c);
}
}
template<typename ...T>
async<> print(T... args) {
auto s = std::format(args...);
co_await print(std::string_view(s));
}
};
task shell_task(shell_io_t& io, std::span<shell_cmd> cmds) {
std::array<char, 80> buf;
std::size_t idx = 0;
while(1) {
char c = co_await io.getchar();
if(c >= 0x20) {
if(idx >= buf.size()) {
continue;
}
buf[idx++] = c;
co_await io.putchar(c);
}
if(c == '\r') {
if(!idx) {
continue;
}
co_await io.putchar('\n');
auto [name, args] = split_first(std::string_view(buf.data(), idx));
bool found = false;
for(auto cmd : cmds) {
if(name != cmd.name) {
continue;
}
co_await cmd.cmd(io);
found = true;
break;
}
if(!found) {
buf[name.size()] = 0;
co_await io.print("No such command: {}\n", name);
}
idx = 0;
}
}
}
shell_cmd shell_cmds[] = {
{
"foo",
[](auto io) -> async<> {
co_await io.print("Hello world!\n");
},
},
};
|