Skip to content

Commit 6b15965

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

File tree

7 files changed

+91
-0
lines changed

7 files changed

+91
-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: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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+
import "C"
9+
import (
10+
"sync"
11+
"unsafe"
12+
13+
"internal/task"
14+
)
15+
16+
type Semaphore struct {
17+
lock sync.Mutex // the lock itself
18+
task *task.Task // the task currently locking this semaphore
19+
count uint32 // how many times this semaphore is locked
20+
}
21+
22+
//export xSemaphoreCreateRecursiveMutex
23+
func xSemaphoreCreateRecursiveMutex() C.SemaphoreHandle_t {
24+
var mutex Semaphore
25+
return (C.SemaphoreHandle_t)(unsafe.Pointer(&mutex))
26+
}
27+
28+
//export vSemaphoreDelete
29+
func vSemaphoreDelete(xSemaphore C.SemaphoreHandle_t) {
30+
mutex := (*Semaphore)(unsafe.Pointer(xSemaphore))
31+
if mutex.task != nil {
32+
panic("vSemaphoreDelete: still locked")
33+
}
34+
}
35+
36+
//export xSemaphoreTakeRecursive
37+
func xSemaphoreTakeRecursive(xMutex C.SemaphoreHandle_t, xTicksToWait C.TickType_t) C.BaseType_t {
38+
// TODO: implement xTickToWait, or at least when xTicksToWait equals 0.
39+
mutex := (*Semaphore)(unsafe.Pointer(xMutex))
40+
if mutex.task == task.Current() {
41+
// Already locked.
42+
mutex.count++
43+
return 1 // pdTRUE
44+
}
45+
// Not yet locked.
46+
mutex.lock.Lock()
47+
mutex.task = task.Current()
48+
return 1 // pdTRUE
49+
}
50+
51+
//export xSemaphoreGiveRecursive
52+
func xSemaphoreGiveRecursive(xMutex C.SemaphoreHandle_t) C.BaseType_t {
53+
mutex := (*Semaphore)(unsafe.Pointer(xMutex))
54+
if mutex.task == task.Current() {
55+
// Already locked.
56+
mutex.count--
57+
if mutex.count == 0 {
58+
mutex.lock.Unlock()
59+
}
60+
return 1 // pdTRUE
61+
}
62+
panic("xSemaphoreGiveRecursive: not locked by this task")
63+
}
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);

src/compat/freertos/include/freertos/task.h

Whitespace-only changes.

0 commit comments

Comments
 (0)