mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 10:38:41 +00:00
WIP continuing
This commit now requires tinygo_task_current which I've patched in my local TinyGo build.
This commit is contained in:
+19
-47
@@ -6,10 +6,6 @@
|
|||||||
// Documentation for these functions:
|
// Documentation for these functions:
|
||||||
// https://github.com/esp-rs/esp-wifi/blob/main/esp-wifi/src/wifi/os_adapter.rs
|
// https://github.com/esp-rs/esp-wifi/blob/main/esp-wifi/src/wifi/os_adapter.rs
|
||||||
|
|
||||||
// Fake task handle. Used for espradio_task_get_current_task.
|
|
||||||
// TODO: get the real task handle somehow.
|
|
||||||
static uint8_t current_task = 1;
|
|
||||||
|
|
||||||
__attribute__((noreturn))
|
__attribute__((noreturn))
|
||||||
void espradio_panic(char *s);
|
void espradio_panic(char *s);
|
||||||
|
|
||||||
@@ -45,13 +41,9 @@ void *espradio_spin_lock_create(void);
|
|||||||
|
|
||||||
void espradio_spin_lock_delete(void *lock);
|
void espradio_spin_lock_delete(void *lock);
|
||||||
|
|
||||||
static uint32_t espradio_wifi_int_disable(void *wifi_int_mux) {
|
uint32_t espradio_wifi_int_disable(void *wifi_int_mux);
|
||||||
espradio_panic("todo: _wifi_int_disable");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void espradio_wifi_int_restore(void *wifi_int_mux, uint32_t tmp) {
|
void espradio_wifi_int_restore(void *wifi_int_mux, uint32_t tmp);
|
||||||
espradio_panic("todo: _wifi_int_restore");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void espradio_task_yield_from_isr(void) {
|
static void espradio_task_yield_from_isr(void) {
|
||||||
espradio_panic("todo: _task_yield_from_isr");
|
espradio_panic("todo: _task_yield_from_isr");
|
||||||
@@ -59,21 +51,13 @@ static void espradio_task_yield_from_isr(void) {
|
|||||||
|
|
||||||
void *espradio_semphr_create(uint32_t max, uint32_t init);
|
void *espradio_semphr_create(uint32_t max, uint32_t init);
|
||||||
|
|
||||||
static void espradio_semphr_delete(void *semphr) {
|
void espradio_semphr_delete(void *semphr);
|
||||||
espradio_panic("todo: _semphr_delete");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t espradio_semphr_take(void *semphr, uint32_t block_time_tick) {
|
int32_t espradio_semphr_take(void *semphr, uint32_t block_time_tick);
|
||||||
espradio_panic("todo: _semphr_take");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t espradio_semphr_give(void *semphr) {
|
int32_t espradio_semphr_give(void *semphr);
|
||||||
espradio_panic("todo: _semphr_give");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *espradio_wifi_thread_semphr_get(void) {
|
void *espradio_wifi_thread_semphr_get(void);
|
||||||
espradio_panic("todo: _wifi_thread_semphr_get");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *espradio_mutex_create(void) {
|
static void *espradio_mutex_create(void) {
|
||||||
espradio_panic("todo: _mutex_create");
|
espradio_panic("todo: _mutex_create");
|
||||||
@@ -97,9 +81,7 @@ static void espradio_queue_delete(void *queue) {
|
|||||||
espradio_panic("todo: _queue_delete");
|
espradio_panic("todo: _queue_delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t espradio_queue_send(void *queue, void *item, uint32_t block_time_tick) {
|
int32_t espradio_queue_send(void *queue, void *item, uint32_t block_time_tick);
|
||||||
espradio_panic("todo: _queue_send");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t espradio_queue_send_from_isr(void *queue, void *item, void *hptw) {
|
static int32_t espradio_queue_send_from_isr(void *queue, void *item, void *hptw) {
|
||||||
espradio_panic("todo: _queue_send_from_isr");
|
espradio_panic("todo: _queue_send_from_isr");
|
||||||
@@ -113,9 +95,7 @@ static int32_t espradio_queue_send_to_front(void *queue, void *item, uint32_t bl
|
|||||||
espradio_panic("todo: _queue_send_to_front");
|
espradio_panic("todo: _queue_send_to_front");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t espradio_queue_recv(void *queue, void *item, uint32_t block_time_tick) {
|
int32_t espradio_queue_recv(void *queue, void *item, uint32_t block_time_tick);
|
||||||
espradio_panic("todo: _queue_recv");
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t espradio_queue_msg_waiting(void *queue) {
|
static uint32_t espradio_queue_msg_waiting(void *queue) {
|
||||||
espradio_panic("todo: _queue_msg_waiting");
|
espradio_panic("todo: _queue_msg_waiting");
|
||||||
@@ -141,30 +121,24 @@ static uint32_t espradio_event_group_wait_bits(void *event, uint32_t bits_to_wai
|
|||||||
espradio_panic("todo: _event_group_wait_bits");
|
espradio_panic("todo: _event_group_wait_bits");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t espradio_task_create_pinned_to_core(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id) {
|
void espradio_run_task(void *task_func, void *task_handle) {
|
||||||
espradio_panic("todo: _task_create_pinned_to_core");
|
void (*fn)(void *task_handle) = task_func;
|
||||||
|
fn(task_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t espradio_task_create_pinned_to_core(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id);
|
||||||
|
|
||||||
static int32_t espradio_task_create(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle) {
|
static int32_t espradio_task_create(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle) {
|
||||||
espradio_panic("todo: _task_create");
|
espradio_panic("todo: _task_create");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void espradio_task_delete(void *task_handle) {
|
void espradio_task_delete(void *task_handle);
|
||||||
espradio_panic("todo: _task_delete");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void espradio_task_delay(uint32_t tick) {
|
void espradio_task_delay(uint32_t tick);
|
||||||
espradio_panic("todo: _task_delay");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t espradio_task_ms_to_tick(uint32_t ms) {
|
int32_t espradio_task_ms_to_tick(uint32_t ms);
|
||||||
espradio_panic("todo: _task_ms_to_tick");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *espradio_task_get_current_task(void) {
|
void *espradio_task_get_current_task(void);
|
||||||
int task_num = current_task;
|
|
||||||
return (void*)task_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t espradio_task_get_max_priority(void) {
|
static int32_t espradio_task_get_max_priority(void) {
|
||||||
return 255; // arbitrary number
|
return 255; // arbitrary number
|
||||||
@@ -373,14 +347,12 @@ static void * espradio_wifi_calloc(size_t n, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void * espradio_wifi_zalloc(size_t size) {
|
static void * espradio_wifi_zalloc(size_t size) {
|
||||||
espradio_panic("todo: _wifi_zalloc");
|
return calloc(1, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void * espradio_wifi_create_queue(int queue_len, int item_size);
|
void * espradio_wifi_create_queue(int queue_len, int item_size);
|
||||||
|
|
||||||
static void espradio_wifi_delete_queue(void * queue) {
|
void espradio_wifi_delete_queue(void * queue);
|
||||||
espradio_panic("todo: _wifi_delete_queue");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int espradio_coex_init(void) {
|
static int espradio_coex_init(void) {
|
||||||
espradio_panic("todo: _coex_init");
|
espradio_panic("todo: _coex_init");
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import "C"
|
|||||||
import (
|
import (
|
||||||
"runtime/interrupt"
|
"runtime/interrupt"
|
||||||
"time"
|
"time"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LogLevel uint8
|
type LogLevel uint8
|
||||||
@@ -60,6 +61,14 @@ func Enable(config Config) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func millisecondsToTicks(ms uint32) uint32 {
|
||||||
|
return ms * (ticksPerSecond / 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ticksToMilliseconds(ticks uint32) uint32 {
|
||||||
|
return ticks / (ticksPerSecond / 1000)
|
||||||
|
}
|
||||||
|
|
||||||
//export espradio_panic
|
//export espradio_panic
|
||||||
func espradio_panic(msg *C.char) {
|
func espradio_panic(msg *C.char) {
|
||||||
panic("espradio: " + C.GoString(msg))
|
panic("espradio: " + C.GoString(msg))
|
||||||
@@ -69,3 +78,56 @@ func espradio_panic(msg *C.char) {
|
|||||||
func espradio_log_timestamp() uint32 {
|
func espradio_log_timestamp() uint32 {
|
||||||
return uint32(time.Now().UnixMilli())
|
return uint32(time.Now().UnixMilli())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export espradio_run_task
|
||||||
|
func espradio_run_task(task_func, param unsafe.Pointer)
|
||||||
|
|
||||||
|
//export espradio_task_create_pinned_to_core
|
||||||
|
func espradio_task_create_pinned_to_core(task_func unsafe.Pointer, name *C.char, stack_depth uint32, param unsafe.Pointer, prio uint32, task_handle *unsafe.Pointer, core_id uint32) int32 {
|
||||||
|
ch := make(chan struct{}, 1)
|
||||||
|
go func() {
|
||||||
|
*task_handle = tinygo_task_current()
|
||||||
|
close(ch)
|
||||||
|
espradio_run_task(task_func, unsafe.Pointer(task_handle))
|
||||||
|
}()
|
||||||
|
<-ch
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
//export espradio_task_delete
|
||||||
|
func espradio_task_delete(task_handle unsafe.Pointer) {
|
||||||
|
println("espradio TODO: delete task", task_handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export tinygo_task_current
|
||||||
|
func tinygo_task_current() unsafe.Pointer
|
||||||
|
|
||||||
|
//export espradio_task_get_current_task
|
||||||
|
func espradio_task_get_current_task() unsafe.Pointer {
|
||||||
|
return tinygo_task_current()
|
||||||
|
}
|
||||||
|
|
||||||
|
//export espradio_task_delay
|
||||||
|
func espradio_task_delay(ticks uint32) {
|
||||||
|
const ticksPerMillisecond = ticksPerSecond / 1000
|
||||||
|
// Round milliseconds up.
|
||||||
|
ms := (ticks + ticksPerMillisecond - 1) / ticksPerMillisecond
|
||||||
|
time.Sleep(time.Duration(ms) * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export espradio_task_ms_to_tick
|
||||||
|
func espradio_task_ms_to_tick(ms uint32) int32 {
|
||||||
|
return int32(millisecondsToTicks(ms))
|
||||||
|
}
|
||||||
|
|
||||||
|
//export espradio_wifi_int_disable
|
||||||
|
func espradio_wifi_int_disable(wifi_int_mux unsafe.Pointer) uint32 {
|
||||||
|
// This is portENTER_CRITICAL (or portENTER_CRITICAL_ISR).
|
||||||
|
return uint32(interrupt.Disable())
|
||||||
|
}
|
||||||
|
|
||||||
|
//export espradio_wifi_int_restore
|
||||||
|
func espradio_wifi_int_restore(wifi_int_mux unsafe.Pointer, tmp uint32) {
|
||||||
|
// This is portEXIT_CRITICAL (or portEXIT_CRITICAL_ISR).
|
||||||
|
interrupt.Restore(interrupt.State(tmp))
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import "device/esp"
|
|||||||
|
|
||||||
func initHardware() error {
|
func initHardware() error {
|
||||||
// See:
|
// See:
|
||||||
// https://github.com/esp-rs/esp-wifi/blob/main/esp-wifi/src/common_adapter/common_adapter_esp32c3.rs#L18
|
// https://github.com/esp-rs/esp-wifi/blob/v0.2.0/esp-wifi/src/common_adapter/common_adapter_esp32c3.rs#L18
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SYSTEM_WIFIBB_RST = 1 << 0
|
SYSTEM_WIFIBB_RST = 1 << 0
|
||||||
@@ -35,3 +35,7 @@ func initHardware() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is the value used for the ESP32-C3, see:
|
||||||
|
// https://github.com/esp-rs/esp-wifi/blob/v0.2.0/esp-wifi/src/timer/riscv.rs#L28
|
||||||
|
const ticksPerSecond = 16_000_000
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ package espradio
|
|||||||
|
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|
||||||
|
// This is the value used for the ESP32-C3.
|
||||||
|
const ticksPerSecond = 16_000_000
|
||||||
|
|
||||||
var errUnsupportedChip = errors.New("espradio: unsupported chip")
|
var errUnsupportedChip = errors.New("espradio: unsupported chip")
|
||||||
|
|
||||||
func initHardware() error {
|
func initHardware() error {
|
||||||
|
|||||||
+88
-6
@@ -2,9 +2,15 @@ package espradio
|
|||||||
|
|
||||||
// Various functions related to locks, mutexes, semaphores, and queues.
|
// Various functions related to locks, mutexes, semaphores, and queues.
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include "include.h"
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -57,25 +63,101 @@ func espradio_mutex_unlock(cmut unsafe.Pointer) int32 {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
var semaphores [1]uint32
|
type semaphore chan struct{}
|
||||||
|
|
||||||
|
var semaphores [2]semaphore
|
||||||
var semaphoreIndex uint32
|
var semaphoreIndex uint32
|
||||||
|
var wifiSemaphore semaphore
|
||||||
|
|
||||||
//export espradio_semphr_create
|
//export espradio_semphr_create
|
||||||
func espradio_semphr_create(max, init uint32) unsafe.Pointer {
|
func espradio_semphr_create(max, init uint32) unsafe.Pointer {
|
||||||
newIndex := atomic.AddUint32(&semaphoreIndex, 1)
|
newIndex := atomic.AddUint32(&semaphoreIndex, 1)
|
||||||
sem := &semaphores[newIndex-1]
|
sem := &semaphores[newIndex-1]
|
||||||
|
ch := make(semaphore, max)
|
||||||
|
for i := uint32(0); i < init; i++ {
|
||||||
|
ch <- struct{}{}
|
||||||
|
}
|
||||||
|
*sem = ch
|
||||||
return unsafe.Pointer(sem)
|
return unsafe.Pointer(sem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export espradio_semphr_take
|
||||||
|
func espradio_semphr_take(semphr unsafe.Pointer, block_time_tick uint32) int32 {
|
||||||
|
sem := (*semaphore)(semphr)
|
||||||
|
if block_time_tick != C.OSI_FUNCS_TIME_BLOCKING {
|
||||||
|
panic("espradio: todo: semphr_take with timeout")
|
||||||
|
}
|
||||||
|
<-*sem
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
//export espradio_semphr_give
|
||||||
|
func espradio_semphr_give(semphr unsafe.Pointer) int32 {
|
||||||
|
// Note: we might need to return 0 when sending isn't possible (e.g. using a
|
||||||
|
// non-blocking send). According to the documentation of xSemaphoreGive:
|
||||||
|
//
|
||||||
|
// > pdTRUE if the semaphore was released. pdFALSE if an error occurred.
|
||||||
|
// > Semaphores are implemented using queues. An error can occur if there is
|
||||||
|
// > no space on the queue to post a message - indicating that the semaphore
|
||||||
|
// > was not first obtained correctly.
|
||||||
|
sem := (*semaphore)(semphr)
|
||||||
|
*sem <- struct{}{}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
//export espradio_semphr_delete
|
||||||
|
func espradio_semphr_delete(semphr unsafe.Pointer) {
|
||||||
|
sem := (*semaphore)(semphr)
|
||||||
|
close(*sem)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export espradio_wifi_thread_semphr_get
|
||||||
|
func espradio_wifi_thread_semphr_get() unsafe.Pointer {
|
||||||
|
if wifiSemaphore == nil {
|
||||||
|
wifiSemaphore = make(semaphore, 1)
|
||||||
|
}
|
||||||
|
return unsafe.Pointer(&wifiSemaphore)
|
||||||
|
}
|
||||||
|
|
||||||
type queueElementType [8]byte
|
type queueElementType [8]byte
|
||||||
|
|
||||||
// TODO: I think the return type results in undefined behavior (but it's still a
|
|
||||||
// pointer so I hope LLVM won't use that fact).
|
|
||||||
//
|
|
||||||
//export espradio_wifi_create_queue
|
//export espradio_wifi_create_queue
|
||||||
func espradio_wifi_create_queue(queue_len, item_size int) chan queueElementType {
|
func espradio_wifi_create_queue(queue_len, item_size int) chan queueElementType {
|
||||||
if item_size > len(queueElementType{}) {
|
if item_size != len(queueElementType{}) {
|
||||||
panic("espradio: queue item_size too large")
|
panic("espradio: unexpected queue item_size")
|
||||||
}
|
}
|
||||||
return make(chan queueElementType, item_size)
|
return make(chan queueElementType, item_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export espradio_wifi_delete_queue
|
||||||
|
func espradio_wifi_delete_queue(queue chan queueElementType) {
|
||||||
|
// We can't really delete a channel, but we can close it.
|
||||||
|
close(queue)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export espradio_queue_recv
|
||||||
|
func espradio_queue_recv(queue chan queueElementType, item unsafe.Pointer, block_time_tick uint32) int32 {
|
||||||
|
// This is xQueueReceive.
|
||||||
|
if block_time_tick != C.OSI_FUNCS_TIME_BLOCKING {
|
||||||
|
panic("espradio: todo: queue_recv with timeout")
|
||||||
|
}
|
||||||
|
*(*[8]byte)(item) = <-queue
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
//export espradio_queue_send
|
||||||
|
func espradio_queue_send(queue chan queueElementType, item unsafe.Pointer, block_time_tick uint32) int32 {
|
||||||
|
// This is xQueueSend.
|
||||||
|
if block_time_tick != C.OSI_FUNCS_TIME_BLOCKING {
|
||||||
|
duration := time.Duration(ticksToMilliseconds(block_time_tick)) * time.Millisecond
|
||||||
|
// TODO: reuse the timer to avoid allocating a new timer on each queue send
|
||||||
|
select {
|
||||||
|
case <-time.After(duration):
|
||||||
|
return 0
|
||||||
|
case queue <- *(*[8]byte)(item):
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queue <- *(*[8]byte)(item)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user