aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2021-09-29 01:22:36 +0200
committerAyke van Laethem <[email protected]>2021-09-29 02:31:12 +0200
commit426c1935402d0b7357d31161dafd22eff729fe51 (patch)
treebb7ca82c840d8c542cc3d18f45b8ea8815a04842
parentdcfa42c6ff19e5c3d2add4e6021aa0aaa0189b9b (diff)
downloadtinygo-426c1935402d0b7357d31161dafd22eff729fe51.tar.gz
tinygo-426c1935402d0b7357d31161dafd22eff729fe51.zip
cgo: add more FreeRTOS compatibility
This commit implements: * xTaskCreate * vTaskDelay * xSemaphoreCreateCounting (partially) * xSemaphoreTake * xSemaphoreGive * xQueueCreate * vQueueDelete * xQueueReceive * xQueueSend * uxQueueMessagesWaiting
-rw-r--r--src/compat/freertos/freertos.c6
-rw-r--r--src/compat/freertos/freertos.go95
-rw-r--r--src/compat/freertos/include/freertos/FreeRTOS.h4
-rw-r--r--src/compat/freertos/include/freertos/queue.h9
-rw-r--r--src/compat/freertos/include/freertos/semphr.h7
-rw-r--r--src/compat/freertos/include/freertos/task.h5
-rw-r--r--src/runtime/chan.go14
7 files changed, 133 insertions, 7 deletions
diff --git a/src/compat/freertos/freertos.c b/src/compat/freertos/freertos.c
new file mode 100644
index 000000000..bab472eb8
--- /dev/null
+++ b/src/compat/freertos/freertos.c
@@ -0,0 +1,6 @@
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+void freertos_callFunction(void (*function)(void *), void *parameter) {
+ function(parameter);
+}
diff --git a/src/compat/freertos/freertos.go b/src/compat/freertos/freertos.go
index 920d8fd1e..392b32259 100644
--- a/src/compat/freertos/freertos.go
+++ b/src/compat/freertos/freertos.go
@@ -4,11 +4,14 @@
package freertos
// #include <freertos/FreeRTOS.h>
+// #include <freertos/queue.h>
// #include <freertos/semphr.h>
// #include <freertos/task.h>
+// void freertos_callFunction(void (*function)(void *), void *parameter);
import "C"
import (
"sync"
+ "time"
"unsafe"
"internal/task"
@@ -19,30 +22,66 @@ func xTaskGetCurrentTaskHandle() C.TaskHandle_t {
return C.TaskHandle_t(task.Current())
}
+//export xTaskCreate
+func xTaskCreate(pvTaskCode C.TaskFunction_t, pcName *C.char, usStackDepth uintptr, pvParameters unsafe.Pointer, uxPriority C.UBaseType_t, pxCreatedTask *C.TaskHandle_t) C.BaseType_t {
+ go func() {
+ C.freertos_callFunction(pvTaskCode, pvParameters)
+ }()
+ if pxCreatedTask != nil {
+ // Code expectes there to be *something*.
+ var tcb int
+ *pxCreatedTask = unsafe.Pointer(&tcb)
+ }
+ return 1 // pdPASS
+}
+
+//export vTaskDelay
+func vTaskDelay(xTicksToDelay C.TickType_t) {
+ // The default tick rate appears to be 100Hz (10ms per tick).
+ time.Sleep(time.Duration(xTicksToDelay) * C.portTICK_PERIOD_MS * time.Millisecond)
+}
+
type Semaphore struct {
lock sync.Mutex // the lock itself
task *task.Task // the task currently locking this semaphore
count uint32 // how many times this semaphore is locked
}
+//export xSemaphoreCreateCounting
+func xSemaphoreCreateCounting(uxMaxCount C.UBaseType_t, uxInitialCount C.UBaseType_t) C.SemaphoreHandle_t {
+ if uxMaxCount != 1 || uxInitialCount != 0 {
+ println("TODO: xSemaphoreCreateCounting that's not a mutex")
+ return nil
+ }
+ mutex := Semaphore{}
+ return C.SemaphoreHandle_t(&mutex)
+}
+
//export xSemaphoreCreateRecursiveMutex
func xSemaphoreCreateRecursiveMutex() C.SemaphoreHandle_t {
var mutex Semaphore
- return (C.SemaphoreHandle_t)(unsafe.Pointer(&mutex))
+ return (C.SemaphoreHandle_t)(&mutex)
}
//export vSemaphoreDelete
func vSemaphoreDelete(xSemaphore C.SemaphoreHandle_t) {
- mutex := (*Semaphore)(unsafe.Pointer(xSemaphore))
+ mutex := (*Semaphore)(xSemaphore)
if mutex.task != nil {
panic("vSemaphoreDelete: still locked")
}
}
+//export xSemaphoreTake
+func xSemaphoreTake(xSemaphore C.QueueHandle_t, xTicksToWait C.TickType_t) C.BaseType_t {
+ mutex := (*Semaphore)(xSemaphore)
+ mutex.lock.Lock()
+ return 1 // pdTRUE
+}
+
//export xSemaphoreTakeRecursive
func xSemaphoreTakeRecursive(xMutex C.SemaphoreHandle_t, xTicksToWait C.TickType_t) C.BaseType_t {
// TODO: implement xTickToWait, or at least when xTicksToWait equals 0.
- mutex := (*Semaphore)(unsafe.Pointer(xMutex))
+ mutex := (*Semaphore)(xMutex)
if mutex.task == task.Current() {
// Already locked.
mutex.count++
@@ -54,9 +93,16 @@ func xSemaphoreTakeRecursive(xMutex C.SemaphoreHandle_t, xTicksToWait C.TickType
return 1 // pdTRUE
}
+//export xSemaphoreGive
+func xSemaphoreGive(xSemaphore C.QueueHandle_t) C.BaseType_t {
+ mutex := (*Semaphore)(xSemaphore)
+ mutex.lock.Unlock()
+ return 1 // pdTRUE
+}
+
//export xSemaphoreGiveRecursive
func xSemaphoreGiveRecursive(xMutex C.SemaphoreHandle_t) C.BaseType_t {
- mutex := (*Semaphore)(unsafe.Pointer(xMutex))
+ mutex := (*Semaphore)(xMutex)
if mutex.task == task.Current() {
// Already locked.
mutex.count--
@@ -67,3 +113,44 @@ func xSemaphoreGiveRecursive(xMutex C.SemaphoreHandle_t) C.BaseType_t {
}
panic("xSemaphoreGiveRecursive: not locked by this task")
}
+
+//export xQueueCreate
+func xQueueCreate(uxQueueLength C.UBaseType_t, uxItemSize C.UBaseType_t) C.QueueHandle_t {
+ return chanMakeUnsafePointer(uintptr(uxItemSize), uintptr(uxQueueLength))
+}
+
+//export vQueueDelete
+func vQueueDelete(xQueue C.QueueHandle_t) {
+ // TODO: close the channel
+}
+
+//export xQueueReceive
+func xQueueReceive(xQueue C.QueueHandle_t, pvBuffer unsafe.Pointer, xTicksToWait C.TickType_t) C.BaseType_t {
+ // Note: xTicksToWait is ignored.
+ chanRecvUnsafePointer(xQueue, pvBuffer)
+ return 1 // pdTRUE
+}
+
+//export xQueueSend
+func xQueueSend(xQueue C.QueueHandle_t, pvBuffer unsafe.Pointer, xTicksToWait C.TickType_t) C.BaseType_t {
+ // Note: xTicksToWait is ignored.
+ chanSendUnsafePointer(xQueue, pvBuffer)
+ return 1 // pdTRUE
+}
+
+//export uxQueueMessagesWaiting
+func uxQueueMessagesWaiting(xQueue C.QueueHandle_t) C.UBaseType_t {
+ return C.UBaseType_t(chanLenUnsafePointer(xQueue))
+}
+
+//go:linkname chanMakeUnsafePointer runtime.chanMakeUnsafePointer
+func chanMakeUnsafePointer(elementSize uintptr, bufSize uintptr) unsafe.Pointer
+
+//go:linkname chanLenUnsafePointer runtime.chanLenUnsafePointer
+func chanLenUnsafePointer(ch unsafe.Pointer) int
+
+//go:linkname chanSendUnsafePointer runtime.chanSendUnsafePointer
+func chanSendUnsafePointer(ch, value unsafe.Pointer)
+
+//go:linkname chanRecvUnsafePointer runtime.chanRecvUnsafePointer
+func chanRecvUnsafePointer(ch, value unsafe.Pointer)
diff --git a/src/compat/freertos/include/freertos/FreeRTOS.h b/src/compat/freertos/include/freertos/FreeRTOS.h
index 3e46754e3..4758e2fd9 100644
--- a/src/compat/freertos/include/freertos/FreeRTOS.h
+++ b/src/compat/freertos/include/freertos/FreeRTOS.h
@@ -6,4 +6,6 @@ typedef uint32_t TickType_t;
typedef int BaseType_t;
typedef unsigned int UBaseType_t;
-#define portMAX_DELAY (TickType_t)0xffffffffUL
+#define portMAX_DELAY (TickType_t)0xffffffffUL
+#define portTICK_PERIOD_MS (10)
+#define configMAX_PRIORITIES (25)
diff --git a/src/compat/freertos/include/freertos/queue.h b/src/compat/freertos/include/freertos/queue.h
index 53d759546..d50ddc37c 100644
--- a/src/compat/freertos/include/freertos/queue.h
+++ b/src/compat/freertos/include/freertos/queue.h
@@ -1,3 +1,10 @@
#pragma once
-typedef struct QueueDefinition * QueueHandle_t;
+typedef void * QueueHandle_t;
+
+QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
+void vQueueDelete(QueueHandle_t xQueue);
+
+BaseType_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);
+BaseType_t xQueueSend(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);
+UBaseType_t uxQueueMessagesWaiting(QueueHandle_t xQueue);
diff --git a/src/compat/freertos/include/freertos/semphr.h b/src/compat/freertos/include/freertos/semphr.h
index e394ad771..672c51b33 100644
--- a/src/compat/freertos/include/freertos/semphr.h
+++ b/src/compat/freertos/include/freertos/semphr.h
@@ -1,8 +1,9 @@
#pragma once
// Note: in FreeRTOS, SemaphoreHandle_t is an alias for QueueHandle_t.
-typedef struct SemaphoreDefinition * SemaphoreHandle_t;
+typedef void * SemaphoreHandle_t;
+SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, UBaseType_t uxInitialCount);
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex(void);
void vSemaphoreDelete(SemaphoreHandle_t xSemaphore);
@@ -10,3 +11,7 @@ void vSemaphoreDelete(SemaphoreHandle_t xSemaphore);
// Note: these two functions are macros in FreeRTOS.
BaseType_t xSemaphoreTakeRecursive(SemaphoreHandle_t xMutex, TickType_t xTicksToWait);
BaseType_t xSemaphoreGiveRecursive(SemaphoreHandle_t xMutex);
+
+// Note: these functions are macros in FreeRTOS.
+BaseType_t xSemaphoreTake(QueueHandle_t xSemaphore, TickType_t xTicksToWait);
+BaseType_t xSemaphoreGive(QueueHandle_t xSemaphore);
diff --git a/src/compat/freertos/include/freertos/task.h b/src/compat/freertos/include/freertos/task.h
index 76a31228f..040ee316e 100644
--- a/src/compat/freertos/include/freertos/task.h
+++ b/src/compat/freertos/include/freertos/task.h
@@ -1,5 +1,10 @@
#pragma once
typedef void * TaskHandle_t;
+typedef void (*TaskFunction_t)(void *);
TaskHandle_t xTaskGetCurrentTaskHandle(void);
+
+BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char * const pcName, uintptr_t usStackDepth, void *pvParameters, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask);
+
+void vTaskDelay(const TickType_t xTicksToDelay);
diff --git a/src/runtime/chan.go b/src/runtime/chan.go
index c2da4f05c..2209d42c6 100644
--- a/src/runtime/chan.go
+++ b/src/runtime/chan.go
@@ -127,6 +127,10 @@ type channel struct {
buf unsafe.Pointer // pointer to first element of buffer
}
+func chanMakeUnsafePointer(elementSize, bufSize uintptr) unsafe.Pointer {
+ return unsafe.Pointer(chanMake(elementSize, bufSize))
+}
+
// chanMake creates a new channel with the given element size and buffer length in number of elements.
// This is a compiler intrinsic.
func chanMake(elementSize uintptr, bufSize uintptr) *channel {
@@ -495,6 +499,11 @@ func chanSend(ch *channel, value unsafe.Pointer, blockedlist *channelBlockedList
sender.Ptr = nil
}
+func chanSendUnsafePointer(ch, value unsafe.Pointer) {
+ var blockedlist channelBlockedList
+ chanSend((*channel)(ch), value, &blockedlist)
+}
+
// chanRecv receives a single value over a channel.
// It blocks if there is no available value to recieve.
// The recieved value is copied into the value pointer.
@@ -532,6 +541,11 @@ func chanRecv(ch *channel, value unsafe.Pointer, blockedlist *channelBlockedList
return ok
}
+func chanRecvUnsafePointer(ch, value unsafe.Pointer) {
+ var blockedlist channelBlockedList
+ chanRecv((*channel)(ch), value, &blockedlist)
+}
+
// chanClose closes the given channel. If this channel has a receiver or is
// empty, it closes the channel. Else, it panics.
func chanClose(ch *channel) {