Skip to content

Commit dcfa42c

Browse files
committed
cgo: add FreeRTOS compatibility headers
This is especially useful if we ever want to support the ESP-IDF. Currently implemented: - xTaskGetCurrentTaskHandle - xSemaphoreCreateRecursiveMutex - xSemaphoreDelete - xSemaphoreTakeRecursive - xSemaphoreGiveRecursive
1 parent 6542220 commit dcfa42c

File tree

7 files changed

+102
-0
lines changed

7 files changed

+102
-0
lines changed

compileopts/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ func (c *Config) RP2040BootPatch() bool {
201201
// preprocessing.
202202
func (c *Config) CFlags() []string {
203203
var cflags []string
204+
// Compatibility CFlags.
205+
cflags = append(cflags, "-I"+filepath.Join(goenv.Get("TINYGOROOT"), "src/compat/freertos/include"))
206+
// CFlags for the target.
204207
for _, flag := range c.Target.CFlags {
205208
cflags = append(cflags, strings.ReplaceAll(flag, "{root}", goenv.Get("TINYGOROOT")))
206209
}

loader/goroot.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ func needsSyscallPackage(buildTags []string) bool {
220220
func pathsToOverride(needsSyscallPackage bool) map[string]bool {
221221
paths := map[string]bool{
222222
"/": true,
223+
"compat/": false,
223224
"crypto/": true,
224225
"crypto/rand/": false,
225226
"device/": false,

src/compat/freertos/freertos.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Package freertos provides a compatibility layer on top of the TinyGo
2+
// scheduler for C code that wants to call FreeRTOS functions. One example is
3+
// the ESP-IDF, which expects there to be a FreeRTOS-like RTOS.
4+
package freertos
5+
6+
// #include <freertos/FreeRTOS.h>
7+
// #include <freertos/semphr.h>
8+
// #include <freertos/task.h>
9+
import "C"
10+
import (
11+
"sync"
12+
"unsafe"
13+
14+
"internal/task"
15+
)
16+
17+
//export xTaskGetCurrentTaskHandle
18+
func xTaskGetCurrentTaskHandle() C.TaskHandle_t {
19+
return C.TaskHandle_t(task.Current())
20+
}
21+
22+
type Semaphore struct {
23+
lock sync.Mutex // the lock itself
24+
task *task.Task // the task currently locking this semaphore
25+
count uint32 // how many times this semaphore is locked
26+
}
27+
28+
//export xSemaphoreCreateRecursiveMutex
29+
func xSemaphoreCreateRecursiveMutex() C.SemaphoreHandle_t {
30+
var mutex Semaphore
31+
return (C.SemaphoreHandle_t)(unsafe.Pointer(&mutex))
32+
}
33+
34+
//export vSemaphoreDelete
35+
func vSemaphoreDelete(xSemaphore C.SemaphoreHandle_t) {
36+
mutex := (*Semaphore)(unsafe.Pointer(xSemaphore))
37+
if mutex.task != nil {
38+
panic("vSemaphoreDelete: still locked")
39+
}
40+
}
41+
42+
//export xSemaphoreTakeRecursive
43+
func xSemaphoreTakeRecursive(xMutex C.SemaphoreHandle_t, xTicksToWait C.TickType_t) C.BaseType_t {
44+
// TODO: implement xTickToWait, or at least when xTicksToWait equals 0.
45+
mutex := (*Semaphore)(unsafe.Pointer(xMutex))
46+
if mutex.task == task.Current() {
47+
// Already locked.
48+
mutex.count++
49+
return 1 // pdTRUE
50+
}
51+
// Not yet locked.
52+
mutex.lock.Lock()
53+
mutex.task = task.Current()
54+
return 1 // pdTRUE
55+
}
56+
57+
//export xSemaphoreGiveRecursive
58+
func xSemaphoreGiveRecursive(xMutex C.SemaphoreHandle_t) C.BaseType_t {
59+
mutex := (*Semaphore)(unsafe.Pointer(xMutex))
60+
if mutex.task == task.Current() {
61+
// Already locked.
62+
mutex.count--
63+
if mutex.count == 0 {
64+
mutex.lock.Unlock()
65+
}
66+
return 1 // pdTRUE
67+
}
68+
panic("xSemaphoreGiveRecursive: not locked by this task")
69+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
3+
#include <stdint.h>
4+
5+
typedef uint32_t TickType_t;
6+
typedef int BaseType_t;
7+
typedef unsigned int UBaseType_t;
8+
9+
#define portMAX_DELAY (TickType_t)0xffffffffUL
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
typedef struct QueueDefinition * QueueHandle_t;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
// Note: in FreeRTOS, SemaphoreHandle_t is an alias for QueueHandle_t.
4+
typedef struct SemaphoreDefinition * SemaphoreHandle_t;
5+
6+
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex(void);
7+
8+
void vSemaphoreDelete(SemaphoreHandle_t xSemaphore);
9+
10+
// Note: these two functions are macros in FreeRTOS.
11+
BaseType_t xSemaphoreTakeRecursive(SemaphoreHandle_t xMutex, TickType_t xTicksToWait);
12+
BaseType_t xSemaphoreGiveRecursive(SemaphoreHandle_t xMutex);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#pragma once
2+
3+
typedef void * TaskHandle_t;
4+
5+
TaskHandle_t xTaskGetCurrentTaskHandle(void);

0 commit comments

Comments
 (0)