[FL-2591] Furi: remove CMSIS thread api, migrate to FuriThread, remove unused CMSIS APIs (#1333)
* Furi: remove CMSIS thread api, migrate to FuriThread, remove unused CMSIS APIs * Furi: magic thread catcher validating thread completion; backtrace improver * Furi: allow furi_thread_get_current_id outside of thread context * Furi: use IRQ instead of ISR for core primitives
This commit is contained in:
parent
7618c8ba6f
commit
839e52ac32
@ -440,9 +440,9 @@ static void bad_usb_hid_state_callback(bool state, void* context) {
|
||||
BadUsbScript* bad_usb = context;
|
||||
|
||||
if(state == true)
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(bad_usb->thread), WorkerEvtConnect);
|
||||
furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtConnect);
|
||||
else
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(bad_usb->thread), WorkerEvtDisconnect);
|
||||
furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtDisconnect);
|
||||
}
|
||||
|
||||
static int32_t bad_usb_worker(void* context) {
|
||||
@ -483,8 +483,8 @@ static int32_t bad_usb_worker(void* context) {
|
||||
bad_usb->st.state = worker_state;
|
||||
|
||||
} else if(worker_state == BadUsbStateNotConnected) { // State: USB not connected
|
||||
uint32_t flags =
|
||||
osThreadFlagsWait(WorkerEvtEnd | WorkerEvtConnect, osFlagsWaitAny, osWaitForever);
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtConnect, osFlagsWaitAny, osWaitForever);
|
||||
furi_check((flags & osFlagsError) == 0);
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
@ -494,7 +494,7 @@ static int32_t bad_usb_worker(void* context) {
|
||||
bad_usb->st.state = worker_state;
|
||||
|
||||
} else if(worker_state == BadUsbStateIdle) { // State: ready to start
|
||||
uint32_t flags = osThreadFlagsWait(
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect,
|
||||
osFlagsWaitAny,
|
||||
osWaitForever);
|
||||
@ -518,7 +518,7 @@ static int32_t bad_usb_worker(void* context) {
|
||||
|
||||
} else if(worker_state == BadUsbStateRunning) { // State: running
|
||||
uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val);
|
||||
uint32_t flags = osThreadFlagsWait(
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, osFlagsWaitAny, delay_cur);
|
||||
delay_val -= delay_cur;
|
||||
if(!(flags & osFlagsError)) {
|
||||
@ -561,7 +561,7 @@ static int32_t bad_usb_worker(void* context) {
|
||||
} else if(
|
||||
(worker_state == BadUsbStateFileError) ||
|
||||
(worker_state == BadUsbStateScriptError)) { // State: error
|
||||
uint32_t flags = osThreadFlagsWait(
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd, osFlagsWaitAny, osWaitForever); // Waiting for exit command
|
||||
furi_check((flags & osFlagsError) == 0);
|
||||
if(flags & WorkerEvtEnd) {
|
||||
@ -605,7 +605,7 @@ BadUsbScript* bad_usb_script_open(string_t file_path) {
|
||||
|
||||
void bad_usb_script_close(BadUsbScript* bad_usb) {
|
||||
furi_assert(bad_usb);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(bad_usb->thread), WorkerEvtEnd);
|
||||
furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtEnd);
|
||||
furi_thread_join(bad_usb->thread);
|
||||
furi_thread_free(bad_usb->thread);
|
||||
string_clear(bad_usb->file_path);
|
||||
@ -614,7 +614,7 @@ void bad_usb_script_close(BadUsbScript* bad_usb) {
|
||||
|
||||
void bad_usb_script_toggle(BadUsbScript* bad_usb) {
|
||||
furi_assert(bad_usb);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(bad_usb->thread), WorkerEvtToggle);
|
||||
furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtToggle);
|
||||
}
|
||||
|
||||
BadUsbState* bad_usb_script_get_state(BadUsbScript* bad_usb) {
|
||||
|
@ -255,19 +255,19 @@ void cli_command_ps(Cli* cli, string_t args, void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
const uint8_t threads_num_max = 32;
|
||||
osThreadId_t threads_id[threads_num_max];
|
||||
uint8_t thread_num = osThreadEnumerate(threads_id, threads_num_max);
|
||||
FuriThreadId threads_ids[threads_num_max];
|
||||
uint8_t thread_num = furi_thread_enumerate(threads_ids, threads_num_max);
|
||||
printf(
|
||||
"%-20s %-14s %-8s %-8s %s\r\n", "Name", "Stack start", "Heap", "Stack", "Stack min free");
|
||||
for(uint8_t i = 0; i < thread_num; i++) {
|
||||
TaskControlBlock* tcb = (TaskControlBlock*)threads_id[i];
|
||||
TaskControlBlock* tcb = (TaskControlBlock*)threads_ids[i];
|
||||
printf(
|
||||
"%-20s 0x%-12lx %-8d %-8ld %-8ld\r\n",
|
||||
osThreadGetName(threads_id[i]),
|
||||
furi_thread_get_name(threads_ids[i]),
|
||||
(uint32_t)tcb->pxStack,
|
||||
memmgr_heap_get_thread_memory(threads_id[i]),
|
||||
memmgr_heap_get_thread_memory(threads_ids[i]),
|
||||
(uint32_t)(tcb->pxEndOfStack - tcb->pxStack + 1) * sizeof(StackType_t),
|
||||
osThreadGetStackSpace(threads_id[i]));
|
||||
furi_thread_get_stack_space(threads_ids[i]));
|
||||
}
|
||||
printf("\r\nTotal: %d", thread_num);
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ static void cli_vcp_init() {
|
||||
}
|
||||
|
||||
static void cli_vcp_deinit() {
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStop);
|
||||
furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtStop);
|
||||
furi_thread_join(vcp->thread);
|
||||
furi_thread_free(vcp->thread);
|
||||
vcp->thread = NULL;
|
||||
@ -102,7 +102,8 @@ static int32_t vcp_worker(void* context) {
|
||||
vcp->running = true;
|
||||
|
||||
while(1) {
|
||||
uint32_t flags = osThreadFlagsWait(VCP_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
||||
uint32_t flags =
|
||||
furi_thread_flags_wait(VCP_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
||||
furi_assert((flags & osFlagsError) == 0);
|
||||
|
||||
// VCP session opened
|
||||
@ -232,7 +233,7 @@ static size_t cli_vcp_rx(uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
FURI_LOG_D(TAG, "rx %u ", batch_size);
|
||||
#endif
|
||||
if(len == 0) break;
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStreamRx);
|
||||
furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtStreamRx);
|
||||
size -= len;
|
||||
buffer += len;
|
||||
rx_cnt += len;
|
||||
@ -261,7 +262,7 @@ static void cli_vcp_tx(const uint8_t* buffer, size_t size) {
|
||||
if(batch_size > USB_CDC_PKT_LEN) batch_size = USB_CDC_PKT_LEN;
|
||||
|
||||
xStreamBufferSend(vcp->tx_stream, buffer, batch_size, osWaitForever);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStreamTx);
|
||||
furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtStreamTx);
|
||||
#ifdef CLI_VCP_DEBUG
|
||||
FURI_LOG_D(TAG, "tx %u", batch_size);
|
||||
#endif
|
||||
@ -283,7 +284,7 @@ static void cli_vcp_tx_stdout(void* _cookie, const char* data, size_t size) {
|
||||
static void vcp_state_callback(void* context, uint8_t state) {
|
||||
UNUSED(context);
|
||||
if(state == 0) {
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect);
|
||||
furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtDisconnect);
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,21 +294,21 @@ static void vcp_on_cdc_control_line(void* context, uint8_t state) {
|
||||
bool dtr = state & (1 << 0);
|
||||
|
||||
if(dtr == true) {
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtConnect);
|
||||
furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtConnect);
|
||||
} else {
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect);
|
||||
furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtDisconnect);
|
||||
}
|
||||
}
|
||||
|
||||
static void vcp_on_cdc_rx(void* context) {
|
||||
UNUSED(context);
|
||||
uint32_t ret = osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtRx);
|
||||
uint32_t ret = furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtRx);
|
||||
furi_check((ret & osFlagsError) == 0);
|
||||
}
|
||||
|
||||
static void vcp_on_cdc_tx_complete(void* context) {
|
||||
UNUSED(context);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtTx);
|
||||
furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtTx);
|
||||
}
|
||||
|
||||
static bool cli_vcp_is_connected(void) {
|
||||
|
@ -97,7 +97,7 @@ static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
||||
|
||||
if(ev == UartIrqEventRXNE) {
|
||||
xStreamBufferSendFromISR(app->rx_stream, &data, 1, &xHigherPriorityTaskWoken);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(app->worker_thread), WorkerEventRx);
|
||||
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
@ -149,7 +149,8 @@ static int32_t uart_echo_worker(void* context) {
|
||||
UartEchoApp* app = context;
|
||||
|
||||
while(1) {
|
||||
uint32_t events = osThreadFlagsWait(WORKER_EVENTS_MASK, osFlagsWaitAny, osWaitForever);
|
||||
uint32_t events =
|
||||
furi_thread_flags_wait(WORKER_EVENTS_MASK, osFlagsWaitAny, osWaitForever);
|
||||
furi_check((events & osFlagsError) == 0);
|
||||
|
||||
if(events & WorkerEventStop) break;
|
||||
@ -234,7 +235,7 @@ static UartEchoApp* uart_echo_app_alloc() {
|
||||
static void uart_echo_app_free(UartEchoApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(app->worker_thread), WorkerEventStop);
|
||||
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop);
|
||||
furi_thread_join(app->worker_thread);
|
||||
furi_thread_free(app->worker_thread);
|
||||
|
||||
|
@ -78,7 +78,7 @@ static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
||||
|
||||
if(ev == UartIrqEventRXNE) {
|
||||
xStreamBufferSendFromISR(usb_uart->rx_stream, &data, 1, &xHigherPriorityTaskWoken);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtRxDone);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtRxDone);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
@ -181,12 +181,13 @@ static int32_t usb_uart_worker(void* context) {
|
||||
usb_uart_update_ctrl_lines(usb_uart);
|
||||
}
|
||||
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->tx_thread), WorkerEvtCdcRx);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->tx_thread), WorkerEvtCdcRx);
|
||||
|
||||
furi_thread_start(usb_uart->tx_thread);
|
||||
|
||||
while(1) {
|
||||
uint32_t events = osThreadFlagsWait(WORKER_ALL_RX_EVENTS, osFlagsWaitAny, osWaitForever);
|
||||
uint32_t events =
|
||||
furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, osFlagsWaitAny, osWaitForever);
|
||||
furi_check((events & osFlagsError) == 0);
|
||||
if(events & WorkerEvtStop) break;
|
||||
if(events & WorkerEvtRxDone) {
|
||||
@ -205,7 +206,7 @@ static int32_t usb_uart_worker(void* context) {
|
||||
}
|
||||
if(events & WorkerEvtCfgChange) {
|
||||
if(usb_uart->cfg.vcp_ch != usb_uart->cfg_new.vcp_ch) {
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->tx_thread), WorkerEvtTxStop);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->tx_thread), WorkerEvtTxStop);
|
||||
furi_thread_join(usb_uart->tx_thread);
|
||||
|
||||
usb_uart_vcp_deinit(usb_uart, usb_uart->cfg.vcp_ch);
|
||||
@ -217,7 +218,7 @@ static int32_t usb_uart_worker(void* context) {
|
||||
events |= WorkerEvtLineCfgSet;
|
||||
}
|
||||
if(usb_uart->cfg.uart_ch != usb_uart->cfg_new.uart_ch) {
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->tx_thread), WorkerEvtTxStop);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->tx_thread), WorkerEvtTxStop);
|
||||
furi_thread_join(usb_uart->tx_thread);
|
||||
|
||||
usb_uart_serial_deinit(usb_uart, usb_uart->cfg.uart_ch);
|
||||
@ -266,7 +267,7 @@ static int32_t usb_uart_worker(void* context) {
|
||||
furi_hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog);
|
||||
}
|
||||
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->tx_thread), WorkerEvtTxStop);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->tx_thread), WorkerEvtTxStop);
|
||||
furi_thread_join(usb_uart->tx_thread);
|
||||
furi_thread_free(usb_uart->tx_thread);
|
||||
|
||||
@ -288,7 +289,8 @@ static int32_t usb_uart_tx_thread(void* context) {
|
||||
|
||||
uint8_t data[USB_CDC_PKT_LEN];
|
||||
while(1) {
|
||||
uint32_t events = osThreadFlagsWait(WORKER_ALL_TX_EVENTS, osFlagsWaitAny, osWaitForever);
|
||||
uint32_t events =
|
||||
furi_thread_flags_wait(WORKER_ALL_TX_EVENTS, osFlagsWaitAny, osWaitForever);
|
||||
furi_check((events & osFlagsError) == 0);
|
||||
if(events & WorkerEvtTxStop) break;
|
||||
if(events & WorkerEvtCdcRx) {
|
||||
@ -314,7 +316,7 @@ static void vcp_on_cdc_tx_complete(void* context) {
|
||||
|
||||
static void vcp_on_cdc_rx(void* context) {
|
||||
UsbUartBridge* usb_uart = (UsbUartBridge*)context;
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->tx_thread), WorkerEvtCdcRx);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->tx_thread), WorkerEvtCdcRx);
|
||||
}
|
||||
|
||||
static void vcp_state_callback(void* context, uint8_t state) {
|
||||
@ -325,13 +327,13 @@ static void vcp_state_callback(void* context, uint8_t state) {
|
||||
static void vcp_on_cdc_control_line(void* context, uint8_t state) {
|
||||
UNUSED(state);
|
||||
UsbUartBridge* usb_uart = (UsbUartBridge*)context;
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtCtrlLineSet);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtCtrlLineSet);
|
||||
}
|
||||
|
||||
static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) {
|
||||
UNUSED(config);
|
||||
UsbUartBridge* usb_uart = (UsbUartBridge*)context;
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtLineCfgSet);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtLineCfgSet);
|
||||
}
|
||||
|
||||
UsbUartBridge* usb_uart_enable(UsbUartConfig* cfg) {
|
||||
@ -351,7 +353,7 @@ UsbUartBridge* usb_uart_enable(UsbUartConfig* cfg) {
|
||||
|
||||
void usb_uart_disable(UsbUartBridge* usb_uart) {
|
||||
furi_assert(usb_uart);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtStop);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtStop);
|
||||
furi_thread_join(usb_uart->thread);
|
||||
furi_thread_free(usb_uart->thread);
|
||||
free(usb_uart);
|
||||
@ -361,7 +363,7 @@ void usb_uart_set_config(UsbUartBridge* usb_uart, UsbUartConfig* cfg) {
|
||||
furi_assert(usb_uart);
|
||||
furi_assert(cfg);
|
||||
memcpy(&(usb_uart->cfg_new), cfg, sizeof(UsbUartConfig));
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtCfgChange);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtCfgChange);
|
||||
}
|
||||
|
||||
void usb_uart_get_config(UsbUartBridge* usb_uart, UsbUartConfig* cfg) {
|
||||
|
@ -19,7 +19,7 @@ ViewPort* gui_view_port_find_enabled(ViewPortArray_t array) {
|
||||
|
||||
void gui_update(Gui* gui) {
|
||||
furi_assert(gui);
|
||||
osThreadFlagsSet(gui->thread, GUI_THREAD_FLAG_DRAW);
|
||||
furi_thread_flags_set(gui->thread_id, GUI_THREAD_FLAG_DRAW);
|
||||
}
|
||||
|
||||
void gui_input_events_callback(const void* value, void* ctx) {
|
||||
@ -29,7 +29,7 @@ void gui_input_events_callback(const void* value, void* ctx) {
|
||||
Gui* gui = ctx;
|
||||
|
||||
osMessageQueuePut(gui->input_queue, value, 0, osWaitForever);
|
||||
osThreadFlagsSet(gui->thread, GUI_THREAD_FLAG_INPUT);
|
||||
furi_thread_flags_set(gui->thread_id, GUI_THREAD_FLAG_INPUT);
|
||||
}
|
||||
|
||||
// Only Fullscreen supports vertical display for now
|
||||
@ -471,7 +471,7 @@ void gui_set_lockdown(Gui* gui, bool lockdown) {
|
||||
Gui* gui_alloc() {
|
||||
Gui* gui = malloc(sizeof(Gui));
|
||||
// Thread ID
|
||||
gui->thread = osThreadGetId();
|
||||
gui->thread_id = furi_thread_get_current_id();
|
||||
// Allocate mutex
|
||||
gui->mutex = osMutexNew(NULL);
|
||||
furi_check(gui->mutex);
|
||||
@ -500,7 +500,8 @@ int32_t gui_srv(void* p) {
|
||||
furi_record_create("gui", gui);
|
||||
|
||||
while(1) {
|
||||
uint32_t flags = osThreadFlagsWait(GUI_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
||||
uint32_t flags =
|
||||
furi_thread_flags_wait(GUI_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
||||
// Process and dispatch input
|
||||
if(flags & GUI_THREAD_FLAG_INPUT) {
|
||||
// Process till queue become empty
|
||||
@ -512,7 +513,7 @@ int32_t gui_srv(void* p) {
|
||||
// Process and dispatch draw call
|
||||
if(flags & GUI_THREAD_FLAG_DRAW) {
|
||||
// Clear flags that arrived on input step
|
||||
osThreadFlagsClear(GUI_THREAD_FLAG_DRAW);
|
||||
furi_thread_flags_clear(GUI_THREAD_FLAG_DRAW);
|
||||
gui_redraw(gui);
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ ALGO_DEF(CanvasCallbackPairArray, CanvasCallbackPairArray_t);
|
||||
/** Gui structure */
|
||||
struct Gui {
|
||||
// Thread and lock
|
||||
osThreadId_t thread;
|
||||
FuriThreadId thread_id;
|
||||
osMutexId_t mutex;
|
||||
|
||||
// Layers and Canvas
|
||||
|
@ -259,10 +259,10 @@ static int32_t browser_worker(void* context) {
|
||||
string_t filename;
|
||||
string_init(filename);
|
||||
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtConfigChange);
|
||||
furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtConfigChange);
|
||||
|
||||
while(1) {
|
||||
uint32_t flags = osThreadFlagsWait(WORKER_FLAGS_ALL, osFlagsWaitAny, osWaitForever);
|
||||
uint32_t flags = furi_thread_flags_wait(WORKER_FLAGS_ALL, osFlagsWaitAny, osWaitForever);
|
||||
furi_assert((flags & osFlagsError) == 0);
|
||||
|
||||
if(flags & WorkerEvtConfigChange) {
|
||||
@ -272,7 +272,7 @@ static int32_t browser_worker(void* context) {
|
||||
}
|
||||
idx_last_array_reset(browser->idx_last);
|
||||
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtFolderEnter);
|
||||
furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtFolderEnter);
|
||||
}
|
||||
|
||||
if(flags & WorkerEvtFolderEnter) {
|
||||
@ -369,7 +369,7 @@ BrowserWorker* file_browser_worker_alloc(string_t path, const char* filter_ext,
|
||||
void file_browser_worker_free(BrowserWorker* browser) {
|
||||
furi_assert(browser);
|
||||
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtStop);
|
||||
furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtStop);
|
||||
furi_thread_join(browser->thread);
|
||||
furi_thread_free(browser->thread);
|
||||
|
||||
@ -423,30 +423,30 @@ void file_browser_worker_set_config(
|
||||
string_set(browser->path_next, path);
|
||||
string_set_str(browser->filter_extension, filter_ext);
|
||||
browser->skip_assets = skip_assets;
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtConfigChange);
|
||||
furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtConfigChange);
|
||||
}
|
||||
|
||||
void file_browser_worker_folder_enter(BrowserWorker* browser, string_t path, int32_t item_idx) {
|
||||
furi_assert(browser);
|
||||
string_set(browser->path_next, path);
|
||||
browser->item_sel_idx = item_idx;
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtFolderEnter);
|
||||
furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtFolderEnter);
|
||||
}
|
||||
|
||||
void file_browser_worker_folder_exit(BrowserWorker* browser) {
|
||||
furi_assert(browser);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtFolderExit);
|
||||
furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtFolderExit);
|
||||
}
|
||||
|
||||
void file_browser_worker_folder_refresh(BrowserWorker* browser, int32_t item_idx) {
|
||||
furi_assert(browser);
|
||||
browser->item_sel_idx = item_idx;
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtFolderRefresh);
|
||||
furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtFolderRefresh);
|
||||
}
|
||||
|
||||
void file_browser_worker_load(BrowserWorker* browser, uint32_t offset, uint32_t count) {
|
||||
furi_assert(browser);
|
||||
browser->load_offset = offset;
|
||||
browser->load_count = count;
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtLoad);
|
||||
furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtLoad);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ void input_press_timer_callback(void* arg) {
|
||||
|
||||
void input_isr(void* _ctx) {
|
||||
UNUSED(_ctx);
|
||||
osThreadFlagsSet(input->thread, INPUT_THREAD_FLAG_ISR);
|
||||
furi_thread_flags_set(input->thread_id, INPUT_THREAD_FLAG_ISR);
|
||||
}
|
||||
|
||||
const char* input_get_key_name(InputKey key) {
|
||||
@ -66,7 +66,7 @@ const char* input_get_type_name(InputType type) {
|
||||
|
||||
int32_t input_srv() {
|
||||
input = malloc(sizeof(Input));
|
||||
input->thread = osThreadGetId();
|
||||
input->thread_id = furi_thread_get_current_id();
|
||||
input->event_pubsub = furi_pubsub_alloc();
|
||||
furi_record_create("input_events", input->event_pubsub);
|
||||
|
||||
@ -129,7 +129,7 @@ int32_t input_srv() {
|
||||
if(is_changing) {
|
||||
osDelay(1);
|
||||
} else {
|
||||
osThreadFlagsWait(INPUT_THREAD_FLAG_ISR, osFlagsWaitAny, osWaitForever);
|
||||
furi_thread_flags_wait(INPUT_THREAD_FLAG_ISR, osFlagsWaitAny, osWaitForever);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ typedef struct {
|
||||
|
||||
/** Input state */
|
||||
typedef struct {
|
||||
osThreadId_t thread;
|
||||
FuriThreadId thread_id;
|
||||
FuriPubSub* event_pubsub;
|
||||
InputPinState* pin_states;
|
||||
Cli* cli;
|
||||
|
@ -29,13 +29,9 @@ static bool
|
||||
furi_thread_set_callback(
|
||||
loader_instance->application_thread, loader_instance->application->app);
|
||||
|
||||
bool result = furi_thread_start(loader_instance->application_thread);
|
||||
furi_thread_start(loader_instance->application_thread);
|
||||
|
||||
if(!result) {
|
||||
loader_instance->application = NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void loader_menu_callback(void* _ctx, uint32_t index) {
|
||||
@ -300,7 +296,7 @@ static Loader* loader_alloc() {
|
||||
UNUSED(loader_cli);
|
||||
#endif
|
||||
|
||||
instance->loader_thread = osThreadGetId();
|
||||
instance->loader_thread = furi_thread_get_current_id();
|
||||
|
||||
// Gui
|
||||
instance->gui = furi_record_open("gui");
|
||||
@ -444,7 +440,7 @@ static void loader_build_submenu() {
|
||||
|
||||
void loader_show_menu() {
|
||||
furi_assert(loader_instance);
|
||||
osThreadFlagsSet(loader_instance->loader_thread, LOADER_THREAD_FLAG_SHOW_MENU);
|
||||
furi_thread_flags_set(loader_instance->loader_thread, LOADER_THREAD_FLAG_SHOW_MENU);
|
||||
}
|
||||
|
||||
void loader_update_menu() {
|
||||
@ -474,7 +470,8 @@ int32_t loader_srv(void* p) {
|
||||
#endif
|
||||
|
||||
while(1) {
|
||||
uint32_t flags = osThreadFlagsWait(LOADER_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
||||
uint32_t flags =
|
||||
furi_thread_flags_wait(LOADER_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
||||
if(flags & LOADER_THREAD_FLAG_SHOW_MENU) {
|
||||
menu_set_selected_item(loader_instance->primary_menu, 0);
|
||||
view_dispatcher_switch_to_view(
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <assets_icons.h>
|
||||
|
||||
struct Loader {
|
||||
osThreadId_t loader_thread;
|
||||
FuriThreadId loader_thread;
|
||||
|
||||
const FlipperApplication* application;
|
||||
FuriThread* application_thread;
|
||||
|
@ -408,7 +408,7 @@ size_t
|
||||
furi_assert(session);
|
||||
size_t bytes_sent = xStreamBufferSend(session->stream, encoded_bytes, size, timeout);
|
||||
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(session->thread), RpcEvtNewData);
|
||||
furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtNewData);
|
||||
|
||||
return bytes_sent;
|
||||
}
|
||||
@ -441,7 +441,7 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
|
||||
if(count == bytes_received) {
|
||||
break;
|
||||
} else {
|
||||
flags = osThreadFlagsWait(RPC_ALL_EVENTS, osFlagsWaitAny, osWaitForever);
|
||||
flags = furi_thread_flags_wait(RPC_ALL_EVENTS, osFlagsWaitAny, osWaitForever);
|
||||
if(flags & RpcEvtDisconnect) {
|
||||
if(xStreamBufferIsEmpty(session->stream)) {
|
||||
session->terminate = true;
|
||||
@ -450,7 +450,7 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
|
||||
break;
|
||||
} else {
|
||||
/* Save disconnect flag and continue reading buffer */
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(session->thread), RpcEvtDisconnect);
|
||||
furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtDisconnect);
|
||||
}
|
||||
} else if(flags & RpcEvtNewData) {
|
||||
// Just wake thread up
|
||||
@ -643,7 +643,7 @@ void rpc_session_close(RpcSession* session) {
|
||||
rpc_session_set_send_bytes_callback(session, NULL);
|
||||
rpc_session_set_close_callback(session, NULL);
|
||||
rpc_session_set_buffer_is_empty_callback(session, NULL);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(session->thread), RpcEvtDisconnect);
|
||||
furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtDisconnect);
|
||||
}
|
||||
|
||||
int32_t rpc_srv(void* p) {
|
||||
|
@ -40,8 +40,7 @@ static void
|
||||
|
||||
memcpy(buffer, data, size);
|
||||
|
||||
osThreadFlagsSet(
|
||||
furi_thread_get_thread_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagTransmit);
|
||||
furi_thread_flags_set(furi_thread_get_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagTransmit);
|
||||
}
|
||||
|
||||
static int32_t rpc_system_gui_screen_stream_frame_transmit_thread(void* context) {
|
||||
@ -50,7 +49,8 @@ static int32_t rpc_system_gui_screen_stream_frame_transmit_thread(void* context)
|
||||
RpcGuiSystem* rpc_gui = (RpcGuiSystem*)context;
|
||||
|
||||
while(true) {
|
||||
uint32_t flags = osThreadFlagsWait(RpcGuiWorkerFlagAny, osFlagsWaitAny, osWaitForever);
|
||||
uint32_t flags =
|
||||
furi_thread_flags_wait(RpcGuiWorkerFlagAny, osFlagsWaitAny, osWaitForever);
|
||||
if(flags & RpcGuiWorkerFlagTransmit) {
|
||||
rpc_send(rpc_gui->session, rpc_gui->transmit_frame);
|
||||
}
|
||||
@ -117,8 +117,7 @@ static void rpc_system_gui_stop_screen_stream_process(const PB_Main* request, vo
|
||||
gui_remove_framebuffer_callback(
|
||||
rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context);
|
||||
// Stop and release worker thread
|
||||
osThreadFlagsSet(
|
||||
furi_thread_get_thread_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagExit);
|
||||
furi_thread_flags_set(furi_thread_get_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagExit);
|
||||
furi_thread_join(rpc_gui->transmit_thread);
|
||||
furi_thread_free(rpc_gui->transmit_thread);
|
||||
// Release frame
|
||||
@ -367,8 +366,7 @@ void rpc_system_gui_free(void* context) {
|
||||
gui_remove_framebuffer_callback(
|
||||
rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context);
|
||||
// Stop and release worker thread
|
||||
osThreadFlagsSet(
|
||||
furi_thread_get_thread_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagExit);
|
||||
furi_thread_flags_set(furi_thread_get_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagExit);
|
||||
furi_thread_join(rpc_gui->transmit_thread);
|
||||
furi_thread_free(rpc_gui->transmit_thread);
|
||||
// Release frame
|
||||
|
@ -92,7 +92,9 @@ bool subghz_chat_worker_start(SubGhzChatWorker* instance, uint32_t frequency) {
|
||||
instance->worker_running = true;
|
||||
instance->last_time_rx_data = 0;
|
||||
|
||||
res = furi_thread_start(instance->thread);
|
||||
furi_thread_start(instance->thread);
|
||||
|
||||
res = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -72,18 +72,18 @@ static void u2f_hid_event_callback(HidU2fEvent ev, void* context) {
|
||||
U2fHid* u2f_hid = context;
|
||||
|
||||
if(ev == HidU2fDisconnected)
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(u2f_hid->thread), WorkerEvtDisconnect);
|
||||
furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtDisconnect);
|
||||
else if(ev == HidU2fConnected)
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(u2f_hid->thread), WorkerEvtConnect);
|
||||
furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtConnect);
|
||||
else if(ev == HidU2fRequest)
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(u2f_hid->thread), WorkerEvtRequest);
|
||||
furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtRequest);
|
||||
}
|
||||
|
||||
static void u2f_hid_lock_timeout_callback(void* context) {
|
||||
furi_assert(context);
|
||||
U2fHid* u2f_hid = context;
|
||||
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(u2f_hid->thread), WorkerEvtUnlock);
|
||||
furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtUnlock);
|
||||
}
|
||||
|
||||
static void u2f_hid_send_response(U2fHid* u2f_hid) {
|
||||
@ -198,7 +198,7 @@ static int32_t u2f_hid_worker(void* context) {
|
||||
furi_hal_hid_u2f_set_callback(u2f_hid_event_callback, u2f_hid);
|
||||
|
||||
while(1) {
|
||||
uint32_t flags = osThreadFlagsWait(
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtStop | WorkerEvtConnect | WorkerEvtDisconnect | WorkerEvtRequest,
|
||||
osFlagsWaitAny,
|
||||
osWaitForever);
|
||||
@ -292,7 +292,7 @@ U2fHid* u2f_hid_start(U2fData* u2f_inst) {
|
||||
|
||||
void u2f_hid_stop(U2fHid* u2f_hid) {
|
||||
furi_assert(u2f_hid);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(u2f_hid->thread), WorkerEvtStop);
|
||||
furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtStop);
|
||||
furi_thread_join(u2f_hid->thread);
|
||||
furi_thread_free(u2f_hid->thread);
|
||||
free(u2f_hid);
|
||||
|
@ -40,91 +40,3 @@ void test_furi_valuemutex() {
|
||||
|
||||
mu_check(delete_mutex(&valuemutex));
|
||||
}
|
||||
|
||||
/*
|
||||
TEST: concurrent access
|
||||
|
||||
1. Create holding record
|
||||
2. Open it twice
|
||||
3. Change value simultaneously in two app and check integrity
|
||||
*/
|
||||
|
||||
// TODO this test broke because mutex in furi is not implemented
|
||||
|
||||
typedef struct {
|
||||
// a and b must be equal
|
||||
uint8_t a;
|
||||
uint8_t b;
|
||||
} ConcurrentValue;
|
||||
|
||||
void furi_concurent_app(void* p) {
|
||||
ValueMutex* mutex = (ValueMutex*)p;
|
||||
if(mutex == NULL) {
|
||||
printf("cannot open mutex\r\n");
|
||||
osThreadExit();
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < 10; i++) {
|
||||
ConcurrentValue* value = (ConcurrentValue*)acquire_mutex_block(mutex);
|
||||
|
||||
if(value == NULL) {
|
||||
printf("cannot take record\r\n");
|
||||
release_mutex(mutex, value);
|
||||
osThreadExit();
|
||||
}
|
||||
|
||||
// emulate read-modify-write broken by context switching
|
||||
uint8_t a = value->a;
|
||||
uint8_t b = value->b;
|
||||
a++;
|
||||
b++;
|
||||
furi_hal_delay_ms(2);
|
||||
value->a = a;
|
||||
value->b = b;
|
||||
release_mutex(mutex, value);
|
||||
}
|
||||
|
||||
osThreadExit();
|
||||
}
|
||||
|
||||
void test_furi_concurrent_access() {
|
||||
// TODO: reimplement or delete test
|
||||
return;
|
||||
/*
|
||||
// 1. Create holding record
|
||||
ConcurrentValue value = {.a = 0, .b = 0};
|
||||
ValueMutex mutex;
|
||||
mu_check(init_mutex(&mutex, &value, sizeof(value)));
|
||||
|
||||
// 3. Create second app for interact with it
|
||||
FuriApp* second_app = furiac_start(furi_concurent_app, "furi concurent app", (void*)&mutex);
|
||||
|
||||
// 4. multiply ConcurrentValue::a
|
||||
for(size_t i = 0; i < 4; i++) {
|
||||
ConcurrentValue* value = (ConcurrentValue*)acquire_mutex_block(&mutex);
|
||||
|
||||
if(value == NULL) {
|
||||
release_mutex(&mutex, value);
|
||||
mu_fail("cannot take record\r\n");
|
||||
}
|
||||
|
||||
// emulate read-modify-write broken by context switching
|
||||
uint8_t a = value->a;
|
||||
uint8_t b = value->b;
|
||||
a++;
|
||||
b++;
|
||||
value->a = a;
|
||||
furi_hal_delay_ms(10); // this is only for test, do not add delay between take/give in prod!
|
||||
value->b = b;
|
||||
release_mutex(&mutex, value);
|
||||
}
|
||||
|
||||
furi_hal_delay_ms(50);
|
||||
|
||||
mu_assert_pointers_eq(second_app->handler, NULL);
|
||||
|
||||
mu_assert_int_eq(value.a, value.b);
|
||||
|
||||
mu_check(delete_mutex(&mutex));
|
||||
*/
|
||||
}
|
||||
|
@ -33,10 +33,6 @@ MU_TEST(mu_test_furi_valuemutex) {
|
||||
test_furi_valuemutex();
|
||||
}
|
||||
|
||||
MU_TEST(mu_test_furi_concurrent_access) {
|
||||
test_furi_concurrent_access();
|
||||
}
|
||||
|
||||
MU_TEST(mu_test_furi_pubsub) {
|
||||
test_furi_pubsub();
|
||||
}
|
||||
@ -55,7 +51,6 @@ MU_TEST_SUITE(test_suite) {
|
||||
// v2 tests
|
||||
MU_RUN_TEST(mu_test_furi_create_open);
|
||||
MU_RUN_TEST(mu_test_furi_valuemutex);
|
||||
MU_RUN_TEST(mu_test_furi_concurrent_access);
|
||||
MU_RUN_TEST(mu_test_furi_pubsub);
|
||||
MU_RUN_TEST(mu_test_furi_memmgr);
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ MU_TEST(storage_file_open_lock) {
|
||||
furi_thread_set_stack_size(locker_thread, 2048);
|
||||
furi_thread_set_context(locker_thread, semaphore);
|
||||
furi_thread_set_callback(locker_thread, storage_file_locker);
|
||||
mu_check(furi_thread_start(locker_thread));
|
||||
furi_thread_start(locker_thread);
|
||||
|
||||
// wait for file lock
|
||||
osSemaphoreAcquire(semaphore, osWaitForever);
|
||||
@ -139,7 +139,7 @@ MU_TEST(storage_dir_open_lock) {
|
||||
furi_thread_set_stack_size(locker_thread, 2048);
|
||||
furi_thread_set_context(locker_thread, semaphore);
|
||||
furi_thread_set_callback(locker_thread, storage_dir_locker);
|
||||
mu_check(furi_thread_start(locker_thread));
|
||||
furi_thread_start(locker_thread);
|
||||
|
||||
// wait for dir lock
|
||||
osSemaphoreAcquire(semaphore, osWaitForever);
|
||||
|
@ -75,7 +75,7 @@ static bool subghz_decoder_test(const char* path, const char* name_decoder) {
|
||||
bool level = level_duration_get_level(level_duration);
|
||||
uint32_t duration = level_duration_get_duration(level_duration);
|
||||
// Yield, to load data inside the worker
|
||||
osThreadYield();
|
||||
furi_thread_yield();
|
||||
decoder->protocol->decoder->feed(decoder, level, duration);
|
||||
} else {
|
||||
break;
|
||||
@ -115,7 +115,7 @@ static bool subghz_decode_random_test(const char* path) {
|
||||
bool level = level_duration_get_level(level_duration);
|
||||
uint32_t duration = level_duration_get_duration(level_duration);
|
||||
// Yield, to load data inside the worker
|
||||
osThreadYield();
|
||||
furi_thread_yield();
|
||||
subghz_receiver_decode(receiver_handler, level, duration);
|
||||
} else {
|
||||
break;
|
||||
|
@ -324,9 +324,9 @@ void update_task_set_progress_cb(UpdateTask* update_task, updateProgressCb cb, v
|
||||
update_task->status_change_cb_state = state;
|
||||
}
|
||||
|
||||
bool update_task_start(UpdateTask* update_task) {
|
||||
void update_task_start(UpdateTask* update_task) {
|
||||
furi_assert(update_task);
|
||||
return furi_thread_start(update_task->thread);
|
||||
furi_thread_start(update_task->thread);
|
||||
}
|
||||
|
||||
bool update_task_is_running(UpdateTask* update_task) {
|
||||
|
@ -74,7 +74,7 @@ void update_task_free(UpdateTask* update_task);
|
||||
|
||||
void update_task_set_progress_cb(UpdateTask* update_task, updateProgressCb cb, void* state);
|
||||
|
||||
bool update_task_start(UpdateTask* update_task);
|
||||
void update_task_start(UpdateTask* update_task);
|
||||
|
||||
bool update_task_is_running(UpdateTask* update_task);
|
||||
|
||||
|
@ -6,16 +6,19 @@
|
||||
|
||||
#include <cmsis_os2.h>
|
||||
|
||||
#include <furi/common_defines.h>
|
||||
#include <furi/check.h>
|
||||
#include <furi/common_defines.h>
|
||||
#include <furi/log.h>
|
||||
#include <furi/event_flags.h>
|
||||
#include <furi/memmgr.h>
|
||||
#include <furi/memmgr_heap.h>
|
||||
#include <furi/mutex.h>
|
||||
#include <furi/pubsub.h>
|
||||
#include <furi/record.h>
|
||||
#include <furi/semaphore.h>
|
||||
#include <furi/stdglue.h>
|
||||
#include <furi/thread.h>
|
||||
#include <furi/valuemutex.h>
|
||||
#include <furi/log.h>
|
||||
|
||||
#include <furi_hal_gpio.h>
|
||||
|
||||
|
45
core/furi/base.h
Normal file
45
core/furi/base.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// FreeRTOS part
|
||||
#include <FreeRTOS.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Timeout value.
|
||||
#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.
|
||||
|
||||
// Flags options (\ref furi_thread_flags_wait and \ref osEventFlagsWait).
|
||||
#define osFlagsWaitAny 0x00000000U ///< Wait for any flag (default).
|
||||
#define osFlagsWaitAll 0x00000001U ///< Wait for all flags.
|
||||
#define osFlagsNoClear 0x00000002U ///< Do not clear flags which have been specified to wait for.
|
||||
|
||||
// Flags errors (returned by osThreadFlagsXxxx and osEventFlagsXxxx).
|
||||
#define osFlagsError 0x80000000U ///< Error indicator.
|
||||
#define osFlagsErrorUnknown 0xFFFFFFFFU ///< osError (-1).
|
||||
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).
|
||||
#define osFlagsErrorResource 0xFFFFFFFDU ///< osErrorResource (-3).
|
||||
#define osFlagsErrorParameter 0xFFFFFFFCU ///< osErrorParameter (-4).
|
||||
#define osFlagsErrorISR 0xFFFFFFFAU ///< osErrorISR (-6).
|
||||
|
||||
/// Status code values returned by CMSIS-RTOS functions.
|
||||
typedef enum {
|
||||
osOK = 0, ///< Operation completed successfully.
|
||||
osError = -1, ///< Unspecified RTOS error: run-time error but no other error message fits.
|
||||
osErrorTimeout = -2, ///< Operation not completed within the timeout period.
|
||||
osErrorResource = -3, ///< Resource not available.
|
||||
osErrorParameter = -4, ///< Parameter error.
|
||||
osErrorNoMemory =
|
||||
-5, ///< System is out of memory: it was impossible to allocate or reserve memory for the operation.
|
||||
osErrorISR =
|
||||
-6, ///< Not allowed in ISR context: the function cannot be called from interrupt service routines.
|
||||
osStatusReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
|
||||
} osStatus_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -6,11 +6,14 @@
|
||||
#include <furi_hal_rtc.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
|
||||
void __furi_print_name() {
|
||||
if(FURI_IS_ISR()) {
|
||||
furi_hal_console_puts("[ISR] ");
|
||||
} else {
|
||||
const char* name = osThreadGetName(osThreadGetId());
|
||||
const char* name = pcTaskGetName(xTaskGetCurrentTaskHandle());
|
||||
if(name == NULL) {
|
||||
furi_hal_console_puts("[main] ");
|
||||
} else {
|
||||
|
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#define FURI_NORETURN [[noreturn]]
|
||||
|
222
core/furi/event_flags.c
Normal file
222
core/furi/event_flags.c
Normal file
@ -0,0 +1,222 @@
|
||||
#include "event_flags.h"
|
||||
#include "common_defines.h"
|
||||
|
||||
#include <event_groups.h>
|
||||
|
||||
#define MAX_BITS_EVENT_GROUPS 24U
|
||||
#define EVENT_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_EVENT_GROUPS) - 1U))
|
||||
|
||||
osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t* attr) {
|
||||
EventGroupHandle_t hEventGroup;
|
||||
int32_t mem;
|
||||
|
||||
hEventGroup = NULL;
|
||||
|
||||
if(FURI_IS_IRQ_MODE() == 0U) {
|
||||
mem = -1;
|
||||
|
||||
if(attr != NULL) {
|
||||
if((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticEventGroup_t))) {
|
||||
/* The memory for control block is provided, use static object */
|
||||
mem = 1;
|
||||
} else {
|
||||
if((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
|
||||
/* Control block will be allocated from the dynamic pool */
|
||||
mem = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mem = 0;
|
||||
}
|
||||
|
||||
if(mem == 1) {
|
||||
#if(configSUPPORT_STATIC_ALLOCATION == 1)
|
||||
hEventGroup = xEventGroupCreateStatic(attr->cb_mem);
|
||||
#endif
|
||||
} else {
|
||||
if(mem == 0) {
|
||||
#if(configSUPPORT_DYNAMIC_ALLOCATION == 1)
|
||||
hEventGroup = xEventGroupCreate();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return event flags ID */
|
||||
return ((osEventFlagsId_t)hEventGroup);
|
||||
}
|
||||
|
||||
/*
|
||||
Set the specified Event Flags.
|
||||
|
||||
Limitations:
|
||||
- Event flags are limited to 24 bits.
|
||||
*/
|
||||
uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags) {
|
||||
EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
|
||||
uint32_t rflags;
|
||||
BaseType_t yield;
|
||||
|
||||
if((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
|
||||
rflags = (uint32_t)osErrorParameter;
|
||||
} else if(FURI_IS_IRQ_MODE() != 0U) {
|
||||
#if(configUSE_OS2_EVENTFLAGS_FROM_ISR == 0)
|
||||
(void)yield;
|
||||
/* Enable timers and xTimerPendFunctionCall function to support osEventFlagsSet from ISR */
|
||||
rflags = (uint32_t)osErrorResource;
|
||||
#else
|
||||
yield = pdFALSE;
|
||||
|
||||
if(xEventGroupSetBitsFromISR(hEventGroup, (EventBits_t)flags, &yield) == pdFAIL) {
|
||||
rflags = (uint32_t)osErrorResource;
|
||||
} else {
|
||||
rflags = flags;
|
||||
portYIELD_FROM_ISR(yield);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
rflags = xEventGroupSetBits(hEventGroup, (EventBits_t)flags);
|
||||
}
|
||||
|
||||
/* Return event flags after setting */
|
||||
return (rflags);
|
||||
}
|
||||
|
||||
/*
|
||||
Clear the specified Event Flags.
|
||||
|
||||
Limitations:
|
||||
- Event flags are limited to 24 bits.
|
||||
*/
|
||||
uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags) {
|
||||
EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
|
||||
uint32_t rflags;
|
||||
|
||||
if((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
|
||||
rflags = (uint32_t)osErrorParameter;
|
||||
} else if(FURI_IS_IRQ_MODE() != 0U) {
|
||||
#if(configUSE_OS2_EVENTFLAGS_FROM_ISR == 0)
|
||||
/* Enable timers and xTimerPendFunctionCall function to support osEventFlagsSet from ISR */
|
||||
rflags = (uint32_t)osErrorResource;
|
||||
#else
|
||||
rflags = xEventGroupGetBitsFromISR(hEventGroup);
|
||||
|
||||
if(xEventGroupClearBitsFromISR(hEventGroup, (EventBits_t)flags) == pdFAIL) {
|
||||
rflags = (uint32_t)osErrorResource;
|
||||
} else {
|
||||
/* xEventGroupClearBitsFromISR only registers clear operation in the timer command queue. */
|
||||
/* Yield is required here otherwise clear operation might not execute in the right order. */
|
||||
/* See https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/93 for more info. */
|
||||
portYIELD_FROM_ISR(pdTRUE);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
rflags = xEventGroupClearBits(hEventGroup, (EventBits_t)flags);
|
||||
}
|
||||
|
||||
/* Return event flags before clearing */
|
||||
return (rflags);
|
||||
}
|
||||
|
||||
/*
|
||||
Get the current Event Flags.
|
||||
|
||||
Limitations:
|
||||
- Event flags are limited to 24 bits.
|
||||
*/
|
||||
uint32_t osEventFlagsGet(osEventFlagsId_t ef_id) {
|
||||
EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
|
||||
uint32_t rflags;
|
||||
|
||||
if(ef_id == NULL) {
|
||||
rflags = 0U;
|
||||
} else if(FURI_IS_IRQ_MODE() != 0U) {
|
||||
rflags = xEventGroupGetBitsFromISR(hEventGroup);
|
||||
} else {
|
||||
rflags = xEventGroupGetBits(hEventGroup);
|
||||
}
|
||||
|
||||
/* Return current event flags */
|
||||
return (rflags);
|
||||
}
|
||||
|
||||
/*
|
||||
Wait for one or more Event Flags to become signaled.
|
||||
|
||||
Limitations:
|
||||
- Event flags are limited to 24 bits.
|
||||
- osEventFlagsWait cannot be called from an ISR.
|
||||
*/
|
||||
uint32_t
|
||||
osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout) {
|
||||
EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
|
||||
BaseType_t wait_all;
|
||||
BaseType_t exit_clr;
|
||||
uint32_t rflags;
|
||||
|
||||
if((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
|
||||
rflags = (uint32_t)osErrorParameter;
|
||||
} else if(FURI_IS_IRQ_MODE() != 0U) {
|
||||
rflags = (uint32_t)osErrorISR;
|
||||
} else {
|
||||
if(options & osFlagsWaitAll) {
|
||||
wait_all = pdTRUE;
|
||||
} else {
|
||||
wait_all = pdFAIL;
|
||||
}
|
||||
|
||||
if(options & osFlagsNoClear) {
|
||||
exit_clr = pdFAIL;
|
||||
} else {
|
||||
exit_clr = pdTRUE;
|
||||
}
|
||||
|
||||
rflags = xEventGroupWaitBits(
|
||||
hEventGroup, (EventBits_t)flags, exit_clr, wait_all, (TickType_t)timeout);
|
||||
|
||||
if(options & osFlagsWaitAll) {
|
||||
if((flags & rflags) != flags) {
|
||||
if(timeout > 0U) {
|
||||
rflags = (uint32_t)osErrorTimeout;
|
||||
} else {
|
||||
rflags = (uint32_t)osErrorResource;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if((flags & rflags) == 0U) {
|
||||
if(timeout > 0U) {
|
||||
rflags = (uint32_t)osErrorTimeout;
|
||||
} else {
|
||||
rflags = (uint32_t)osErrorResource;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return event flags before clearing */
|
||||
return (rflags);
|
||||
}
|
||||
|
||||
/*
|
||||
Delete an Event Flags object.
|
||||
*/
|
||||
osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id) {
|
||||
EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
|
||||
osStatus_t stat;
|
||||
|
||||
#ifndef USE_FreeRTOS_HEAP_1
|
||||
if(FURI_IS_IRQ_MODE() != 0U) {
|
||||
stat = osErrorISR;
|
||||
} else if(hEventGroup == NULL) {
|
||||
stat = osErrorParameter;
|
||||
} else {
|
||||
stat = osOK;
|
||||
vEventGroupDelete(hEventGroup);
|
||||
}
|
||||
#else
|
||||
stat = osError;
|
||||
#endif
|
||||
|
||||
/* Return execution status */
|
||||
return (stat);
|
||||
}
|
63
core/furi/event_flags.h
Normal file
63
core/furi/event_flags.h
Normal file
@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// Attributes structure for event flags.
|
||||
typedef struct {
|
||||
const char* name; ///< name of the event flags
|
||||
uint32_t attr_bits; ///< attribute bits
|
||||
void* cb_mem; ///< memory for control block
|
||||
uint32_t cb_size; ///< size of provided memory for control block
|
||||
} osEventFlagsAttr_t;
|
||||
|
||||
/// \details Event Flags ID identifies the event flags.
|
||||
typedef void* osEventFlagsId_t;
|
||||
|
||||
/// Create and Initialize an Event Flags object.
|
||||
/// \param[in] attr event flags attributes; NULL: default values.
|
||||
/// \return event flags ID for reference by other functions or NULL in case of error.
|
||||
osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t* attr);
|
||||
|
||||
/// Get name of an Event Flags object.
|
||||
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
|
||||
/// \return name as null-terminated string.
|
||||
const char* osEventFlagsGetName(osEventFlagsId_t ef_id);
|
||||
|
||||
/// Set the specified Event Flags.
|
||||
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
|
||||
/// \param[in] flags specifies the flags that shall be set.
|
||||
/// \return event flags after setting or error code if highest bit set.
|
||||
uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags);
|
||||
|
||||
/// Clear the specified Event Flags.
|
||||
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
|
||||
/// \param[in] flags specifies the flags that shall be cleared.
|
||||
/// \return event flags before clearing or error code if highest bit set.
|
||||
uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags);
|
||||
|
||||
/// Get the current Event Flags.
|
||||
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
|
||||
/// \return current event flags.
|
||||
uint32_t osEventFlagsGet(osEventFlagsId_t ef_id);
|
||||
|
||||
/// Wait for one or more Event Flags to become signaled.
|
||||
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
|
||||
/// \param[in] flags specifies the flags to wait for.
|
||||
/// \param[in] options specifies flags options (osFlagsXxxx).
|
||||
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
|
||||
/// \return event flags before clearing or error code if highest bit set.
|
||||
uint32_t
|
||||
osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout);
|
||||
|
||||
/// Delete an Event Flags object.
|
||||
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,5 +1,6 @@
|
||||
#include "log.h"
|
||||
#include "check.h"
|
||||
#include "mutex.h"
|
||||
#include <cmsis_os2.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
|
@ -133,7 +133,7 @@ void memmgr_heap_init() {
|
||||
MemmgrHeapThreadDict_init(memmgr_heap_thread_dict);
|
||||
}
|
||||
|
||||
void memmgr_heap_enable_thread_trace(osThreadId_t thread_id) {
|
||||
void memmgr_heap_enable_thread_trace(FuriThreadId thread_id) {
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
memmgr_heap_thread_trace_depth++;
|
||||
@ -147,7 +147,7 @@ void memmgr_heap_enable_thread_trace(osThreadId_t thread_id) {
|
||||
(void)xTaskResumeAll();
|
||||
}
|
||||
|
||||
void memmgr_heap_disable_thread_trace(osThreadId_t thread_id) {
|
||||
void memmgr_heap_disable_thread_trace(FuriThreadId thread_id) {
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
memmgr_heap_thread_trace_depth++;
|
||||
@ -158,7 +158,7 @@ void memmgr_heap_disable_thread_trace(osThreadId_t thread_id) {
|
||||
(void)xTaskResumeAll();
|
||||
}
|
||||
|
||||
size_t memmgr_heap_get_thread_memory(osThreadId_t thread_id) {
|
||||
size_t memmgr_heap_get_thread_memory(FuriThreadId thread_id) {
|
||||
size_t leftovers = MEMMGR_HEAP_UNKNOWN;
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
@ -192,7 +192,7 @@ size_t memmgr_heap_get_thread_memory(osThreadId_t thread_id) {
|
||||
|
||||
#undef traceMALLOC
|
||||
static inline void traceMALLOC(void* pointer, size_t size) {
|
||||
osThreadId_t thread_id = osThreadGetId();
|
||||
FuriThreadId thread_id = furi_thread_get_current_id();
|
||||
if(thread_id && memmgr_heap_thread_trace_depth == 0) {
|
||||
memmgr_heap_thread_trace_depth++;
|
||||
MemmgrHeapAllocDict_t* alloc_dict =
|
||||
@ -207,7 +207,7 @@ static inline void traceMALLOC(void* pointer, size_t size) {
|
||||
#undef traceFREE
|
||||
static inline void traceFREE(void* pointer, size_t size) {
|
||||
UNUSED(size);
|
||||
osThreadId_t thread_id = osThreadGetId();
|
||||
FuriThreadId thread_id = furi_thread_get_current_id();
|
||||
if(thread_id && memmgr_heap_thread_trace_depth == 0) {
|
||||
memmgr_heap_thread_trace_depth++;
|
||||
MemmgrHeapAllocDict_t* alloc_dict =
|
||||
@ -297,7 +297,7 @@ static void print_heap_init() {
|
||||
|
||||
static void print_heap_malloc(void* ptr, size_t size) {
|
||||
char tmp_str[33];
|
||||
const char* name = osThreadGetName(osThreadGetId());
|
||||
const char* name = furi_thread_get_name(furi_thread_get_current_id());
|
||||
if(!name) {
|
||||
name = "";
|
||||
}
|
||||
@ -318,7 +318,7 @@ static void print_heap_malloc(void* ptr, size_t size) {
|
||||
|
||||
static void print_heap_free(void* ptr) {
|
||||
char tmp_str[33];
|
||||
const char* name = osThreadGetName(osThreadGetId());
|
||||
const char* name = furi_thread_get_name(furi_thread_get_current_id());
|
||||
if(!name) {
|
||||
name = "";
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cmsis_os2.h>
|
||||
#include "furi/thread.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -18,13 +18,13 @@ extern "C" {
|
||||
*
|
||||
* @param thread_id - thread id to track
|
||||
*/
|
||||
void memmgr_heap_enable_thread_trace(osThreadId_t thread_id);
|
||||
void memmgr_heap_enable_thread_trace(FuriThreadId taks_handle);
|
||||
|
||||
/** Memmgr heap disable thread allocation tracking
|
||||
*
|
||||
* @param thread_id - thread id to track
|
||||
*/
|
||||
void memmgr_heap_disable_thread_trace(osThreadId_t thread_id);
|
||||
void memmgr_heap_disable_thread_trace(FuriThreadId taks_handle);
|
||||
|
||||
/** Memmgr heap get allocatred thread memory
|
||||
*
|
||||
@ -32,7 +32,7 @@ void memmgr_heap_disable_thread_trace(osThreadId_t thread_id);
|
||||
*
|
||||
* @return bytes allocated right now
|
||||
*/
|
||||
size_t memmgr_heap_get_thread_memory(osThreadId_t thread_id);
|
||||
size_t memmgr_heap_get_thread_memory(FuriThreadId taks_handle);
|
||||
|
||||
/** Memmgr heap get the max contiguous block size on the heap
|
||||
*
|
||||
|
217
core/furi/mutex.c
Normal file
217
core/furi/mutex.c
Normal file
@ -0,0 +1,217 @@
|
||||
#include "mutex.h"
|
||||
#include "check.h"
|
||||
#include "common_defines.h"
|
||||
|
||||
#include <semphr.h>
|
||||
|
||||
osMutexId_t osMutexNew(const osMutexAttr_t* attr) {
|
||||
SemaphoreHandle_t hMutex;
|
||||
uint32_t type;
|
||||
uint32_t rmtx;
|
||||
int32_t mem;
|
||||
|
||||
hMutex = NULL;
|
||||
|
||||
if(FURI_IS_IRQ_MODE() == 0U) {
|
||||
if(attr != NULL) {
|
||||
type = attr->attr_bits;
|
||||
} else {
|
||||
type = 0U;
|
||||
}
|
||||
|
||||
if((type & osMutexRecursive) == osMutexRecursive) {
|
||||
rmtx = 1U;
|
||||
} else {
|
||||
rmtx = 0U;
|
||||
}
|
||||
|
||||
if((type & osMutexRobust) != osMutexRobust) {
|
||||
mem = -1;
|
||||
|
||||
if(attr != NULL) {
|
||||
if((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticSemaphore_t))) {
|
||||
/* The memory for control block is provided, use static object */
|
||||
mem = 1;
|
||||
} else {
|
||||
if((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
|
||||
/* Control block will be allocated from the dynamic pool */
|
||||
mem = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mem = 0;
|
||||
}
|
||||
|
||||
if(mem == 1) {
|
||||
#if(configSUPPORT_STATIC_ALLOCATION == 1)
|
||||
if(rmtx != 0U) {
|
||||
#if(configUSE_RECURSIVE_MUTEXES == 1)
|
||||
hMutex = xSemaphoreCreateRecursiveMutexStatic(attr->cb_mem);
|
||||
#endif
|
||||
} else {
|
||||
hMutex = xSemaphoreCreateMutexStatic(attr->cb_mem);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if(mem == 0) {
|
||||
#if(configSUPPORT_DYNAMIC_ALLOCATION == 1)
|
||||
if(rmtx != 0U) {
|
||||
#if(configUSE_RECURSIVE_MUTEXES == 1)
|
||||
hMutex = xSemaphoreCreateRecursiveMutex();
|
||||
#endif
|
||||
} else {
|
||||
hMutex = xSemaphoreCreateMutex();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if(configQUEUE_REGISTRY_SIZE > 0)
|
||||
if(hMutex != NULL) {
|
||||
if((attr != NULL) && (attr->name != NULL)) {
|
||||
/* Only non-NULL name objects are added to the Queue Registry */
|
||||
vQueueAddToRegistry(hMutex, attr->name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if((hMutex != NULL) && (rmtx != 0U)) {
|
||||
/* Set LSB as 'recursive mutex flag' */
|
||||
hMutex = (SemaphoreHandle_t)((uint32_t)hMutex | 1U);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return mutex ID */
|
||||
return ((osMutexId_t)hMutex);
|
||||
}
|
||||
|
||||
/*
|
||||
Acquire a Mutex or timeout if it is locked.
|
||||
*/
|
||||
osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout) {
|
||||
SemaphoreHandle_t hMutex;
|
||||
osStatus_t stat;
|
||||
uint32_t rmtx;
|
||||
|
||||
hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
|
||||
|
||||
/* Extract recursive mutex flag */
|
||||
rmtx = (uint32_t)mutex_id & 1U;
|
||||
|
||||
stat = osOK;
|
||||
|
||||
if(FURI_IS_IRQ_MODE() != 0U) {
|
||||
stat = osErrorISR;
|
||||
} else if(hMutex == NULL) {
|
||||
stat = osErrorParameter;
|
||||
} else {
|
||||
if(rmtx != 0U) {
|
||||
#if(configUSE_RECURSIVE_MUTEXES == 1)
|
||||
if(xSemaphoreTakeRecursive(hMutex, timeout) != pdPASS) {
|
||||
if(timeout != 0U) {
|
||||
stat = osErrorTimeout;
|
||||
} else {
|
||||
stat = osErrorResource;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if(xSemaphoreTake(hMutex, timeout) != pdPASS) {
|
||||
if(timeout != 0U) {
|
||||
stat = osErrorTimeout;
|
||||
} else {
|
||||
stat = osErrorResource;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return execution status */
|
||||
return (stat);
|
||||
}
|
||||
|
||||
/*
|
||||
Release a Mutex that was acquired by osMutexAcquire.
|
||||
*/
|
||||
osStatus_t osMutexRelease(osMutexId_t mutex_id) {
|
||||
SemaphoreHandle_t hMutex;
|
||||
osStatus_t stat;
|
||||
uint32_t rmtx;
|
||||
|
||||
hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
|
||||
|
||||
/* Extract recursive mutex flag */
|
||||
rmtx = (uint32_t)mutex_id & 1U;
|
||||
|
||||
stat = osOK;
|
||||
|
||||
if(FURI_IS_IRQ_MODE() != 0U) {
|
||||
stat = osErrorISR;
|
||||
} else if(hMutex == NULL) {
|
||||
stat = osErrorParameter;
|
||||
} else {
|
||||
if(rmtx != 0U) {
|
||||
#if(configUSE_RECURSIVE_MUTEXES == 1)
|
||||
if(xSemaphoreGiveRecursive(hMutex) != pdPASS) {
|
||||
stat = osErrorResource;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if(xSemaphoreGive(hMutex) != pdPASS) {
|
||||
stat = osErrorResource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return execution status */
|
||||
return (stat);
|
||||
}
|
||||
|
||||
/*
|
||||
Get Thread which owns a Mutex object.
|
||||
*/
|
||||
FuriThreadId osMutexGetOwner(osMutexId_t mutex_id) {
|
||||
SemaphoreHandle_t hMutex;
|
||||
FuriThreadId owner;
|
||||
|
||||
hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
|
||||
|
||||
if((FURI_IS_IRQ_MODE() != 0U) || (hMutex == NULL)) {
|
||||
owner = 0;
|
||||
} else {
|
||||
owner = (FuriThreadId)xSemaphoreGetMutexHolder(hMutex);
|
||||
}
|
||||
|
||||
/* Return owner thread ID */
|
||||
return (owner);
|
||||
}
|
||||
|
||||
/*
|
||||
Delete a Mutex object.
|
||||
*/
|
||||
osStatus_t osMutexDelete(osMutexId_t mutex_id) {
|
||||
osStatus_t stat;
|
||||
#ifndef USE_FreeRTOS_HEAP_1
|
||||
SemaphoreHandle_t hMutex;
|
||||
|
||||
hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
|
||||
|
||||
if(FURI_IS_IRQ_MODE() != 0U) {
|
||||
stat = osErrorISR;
|
||||
} else if(hMutex == NULL) {
|
||||
stat = osErrorParameter;
|
||||
} else {
|
||||
#if(configQUEUE_REGISTRY_SIZE > 0)
|
||||
vQueueUnregisterQueue(hMutex);
|
||||
#endif
|
||||
stat = osOK;
|
||||
vSemaphoreDelete(hMutex);
|
||||
}
|
||||
#else
|
||||
stat = osError;
|
||||
#endif
|
||||
|
||||
/* Return execution status */
|
||||
return (stat);
|
||||
}
|
56
core/furi/mutex.h
Normal file
56
core/furi/mutex.h
Normal file
@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
#include "thread.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Mutex attributes (attr_bits in \ref osMutexAttr_t).
|
||||
#define osMutexRecursive 0x00000001U ///< Recursive mutex.
|
||||
#define osMutexPrioInherit 0x00000002U ///< Priority inherit protocol.
|
||||
#define osMutexRobust 0x00000008U ///< Robust mutex.
|
||||
|
||||
/// Attributes structure for mutex.
|
||||
typedef struct {
|
||||
const char* name; ///< name of the mutex
|
||||
uint32_t attr_bits; ///< attribute bits
|
||||
void* cb_mem; ///< memory for control block
|
||||
uint32_t cb_size; ///< size of provided memory for control block
|
||||
} osMutexAttr_t;
|
||||
|
||||
/// \details Mutex ID identifies the mutex.
|
||||
typedef void* osMutexId_t;
|
||||
|
||||
/// Create and Initialize a Mutex object.
|
||||
/// \param[in] attr mutex attributes; NULL: default values.
|
||||
/// \return mutex ID for reference by other functions or NULL in case of error.
|
||||
osMutexId_t osMutexNew(const osMutexAttr_t* attr);
|
||||
|
||||
/// Get name of a Mutex object.
|
||||
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
|
||||
/// \return name as null-terminated string.
|
||||
const char* osMutexGetName(osMutexId_t mutex_id);
|
||||
|
||||
/// Acquire a Mutex or timeout if it is locked.
|
||||
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
|
||||
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout);
|
||||
|
||||
/// Release a Mutex that was acquired by \ref osMutexAcquire.
|
||||
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osMutexRelease(osMutexId_t mutex_id);
|
||||
|
||||
/// Delete a Mutex object.
|
||||
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osMutexDelete(osMutexId_t mutex_id);
|
||||
|
||||
FuriThreadId osMutexGetOwner(osMutexId_t mutex_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,9 +1,9 @@
|
||||
#include "pubsub.h"
|
||||
#include "memmgr.h"
|
||||
#include "check.h"
|
||||
#include "mutex.h"
|
||||
|
||||
#include <m-list.h>
|
||||
#include <cmsis_os2.h>
|
||||
|
||||
struct FuriPubSubSubscription {
|
||||
FuriPubSubCallback callback;
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include "record.h"
|
||||
#include "check.h"
|
||||
#include "memmgr.h"
|
||||
#include "mutex.h"
|
||||
#include "event_flags.h"
|
||||
|
||||
#include <cmsis_os2.h>
|
||||
#include <m-string.h>
|
||||
#include <m-dict.h>
|
||||
|
||||
|
190
core/furi/semaphore.c
Normal file
190
core/furi/semaphore.c
Normal file
@ -0,0 +1,190 @@
|
||||
#include "semaphore.h"
|
||||
#include "check.h"
|
||||
#include "common_defines.h"
|
||||
|
||||
#include <semphr.h>
|
||||
|
||||
osSemaphoreId_t
|
||||
osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t* attr) {
|
||||
SemaphoreHandle_t hSemaphore;
|
||||
int32_t mem;
|
||||
|
||||
hSemaphore = NULL;
|
||||
|
||||
if((FURI_IS_IRQ_MODE() == 0U) && (max_count > 0U) && (initial_count <= max_count)) {
|
||||
mem = -1;
|
||||
|
||||
if(attr != NULL) {
|
||||
if((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticSemaphore_t))) {
|
||||
/* The memory for control block is provided, use static object */
|
||||
mem = 1;
|
||||
} else {
|
||||
if((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
|
||||
/* Control block will be allocated from the dynamic pool */
|
||||
mem = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mem = 0;
|
||||
}
|
||||
|
||||
if(mem != -1) {
|
||||
if(max_count == 1U) {
|
||||
if(mem == 1) {
|
||||
#if(configSUPPORT_STATIC_ALLOCATION == 1)
|
||||
hSemaphore = xSemaphoreCreateBinaryStatic((StaticSemaphore_t*)attr->cb_mem);
|
||||
#endif
|
||||
} else {
|
||||
#if(configSUPPORT_DYNAMIC_ALLOCATION == 1)
|
||||
hSemaphore = xSemaphoreCreateBinary();
|
||||
#endif
|
||||
}
|
||||
|
||||
if((hSemaphore != NULL) && (initial_count != 0U)) {
|
||||
if(xSemaphoreGive(hSemaphore) != pdPASS) {
|
||||
vSemaphoreDelete(hSemaphore);
|
||||
hSemaphore = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(mem == 1) {
|
||||
#if(configSUPPORT_STATIC_ALLOCATION == 1)
|
||||
hSemaphore = xSemaphoreCreateCountingStatic(
|
||||
max_count, initial_count, (StaticSemaphore_t*)attr->cb_mem);
|
||||
#endif
|
||||
} else {
|
||||
#if(configSUPPORT_DYNAMIC_ALLOCATION == 1)
|
||||
hSemaphore = xSemaphoreCreateCounting(max_count, initial_count);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if(configQUEUE_REGISTRY_SIZE > 0)
|
||||
if(hSemaphore != NULL) {
|
||||
if((attr != NULL) && (attr->name != NULL)) {
|
||||
/* Only non-NULL name objects are added to the Queue Registry */
|
||||
vQueueAddToRegistry(hSemaphore, attr->name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Return semaphore ID */
|
||||
return ((osSemaphoreId_t)hSemaphore);
|
||||
}
|
||||
|
||||
/*
|
||||
Acquire a Semaphore token or timeout if no tokens are available.
|
||||
*/
|
||||
osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout) {
|
||||
SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
|
||||
osStatus_t stat;
|
||||
BaseType_t yield;
|
||||
|
||||
stat = osOK;
|
||||
|
||||
if(hSemaphore == NULL) {
|
||||
stat = osErrorParameter;
|
||||
} else if(FURI_IS_IRQ_MODE() != 0U) {
|
||||
if(timeout != 0U) {
|
||||
stat = osErrorParameter;
|
||||
} else {
|
||||
yield = pdFALSE;
|
||||
|
||||
if(xSemaphoreTakeFromISR(hSemaphore, &yield) != pdPASS) {
|
||||
stat = osErrorResource;
|
||||
} else {
|
||||
portYIELD_FROM_ISR(yield);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(xSemaphoreTake(hSemaphore, (TickType_t)timeout) != pdPASS) {
|
||||
if(timeout != 0U) {
|
||||
stat = osErrorTimeout;
|
||||
} else {
|
||||
stat = osErrorResource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return execution status */
|
||||
return (stat);
|
||||
}
|
||||
|
||||
/*
|
||||
Release a Semaphore token up to the initial maximum count.
|
||||
*/
|
||||
osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id) {
|
||||
SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
|
||||
osStatus_t stat;
|
||||
BaseType_t yield;
|
||||
|
||||
stat = osOK;
|
||||
|
||||
if(hSemaphore == NULL) {
|
||||
stat = osErrorParameter;
|
||||
} else if(FURI_IS_IRQ_MODE() != 0U) {
|
||||
yield = pdFALSE;
|
||||
|
||||
if(xSemaphoreGiveFromISR(hSemaphore, &yield) != pdTRUE) {
|
||||
stat = osErrorResource;
|
||||
} else {
|
||||
portYIELD_FROM_ISR(yield);
|
||||
}
|
||||
} else {
|
||||
if(xSemaphoreGive(hSemaphore) != pdPASS) {
|
||||
stat = osErrorResource;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return execution status */
|
||||
return (stat);
|
||||
}
|
||||
|
||||
/*
|
||||
Get current Semaphore token count.
|
||||
*/
|
||||
uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id) {
|
||||
SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
|
||||
uint32_t count;
|
||||
|
||||
if(hSemaphore == NULL) {
|
||||
count = 0U;
|
||||
} else if(FURI_IS_IRQ_MODE() != 0U) {
|
||||
count = (uint32_t)uxSemaphoreGetCountFromISR(hSemaphore);
|
||||
} else {
|
||||
count = (uint32_t)uxSemaphoreGetCount(hSemaphore);
|
||||
}
|
||||
|
||||
/* Return number of tokens */
|
||||
return (count);
|
||||
}
|
||||
|
||||
/*
|
||||
Delete a Semaphore object.
|
||||
*/
|
||||
osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id) {
|
||||
SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
|
||||
osStatus_t stat;
|
||||
|
||||
#ifndef USE_FreeRTOS_HEAP_1
|
||||
if(FURI_IS_IRQ_MODE() != 0U) {
|
||||
stat = osErrorISR;
|
||||
} else if(hSemaphore == NULL) {
|
||||
stat = osErrorParameter;
|
||||
} else {
|
||||
#if(configQUEUE_REGISTRY_SIZE > 0)
|
||||
vQueueUnregisterQueue(hSemaphore);
|
||||
#endif
|
||||
|
||||
stat = osOK;
|
||||
vSemaphoreDelete(hSemaphore);
|
||||
}
|
||||
#else
|
||||
stat = osError;
|
||||
#endif
|
||||
|
||||
/* Return execution status */
|
||||
return (stat);
|
||||
}
|
57
core/furi/semaphore.h
Normal file
57
core/furi/semaphore.h
Normal file
@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
#include "thread.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// Attributes structure for semaphore.
|
||||
typedef struct {
|
||||
const char* name; ///< name of the semaphore
|
||||
uint32_t attr_bits; ///< attribute bits
|
||||
void* cb_mem; ///< memory for control block
|
||||
uint32_t cb_size; ///< size of provided memory for control block
|
||||
} osSemaphoreAttr_t;
|
||||
|
||||
/// \details Semaphore ID identifies the semaphore.
|
||||
typedef void* osSemaphoreId_t;
|
||||
|
||||
/// Create and Initialize a Semaphore object.
|
||||
/// \param[in] max_count maximum number of available tokens.
|
||||
/// \param[in] initial_count initial number of available tokens.
|
||||
/// \param[in] attr semaphore attributes; NULL: default values.
|
||||
/// \return semaphore ID for reference by other functions or NULL in case of error.
|
||||
osSemaphoreId_t
|
||||
osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t* attr);
|
||||
|
||||
/// Get name of a Semaphore object.
|
||||
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
|
||||
/// \return name as null-terminated string.
|
||||
const char* osSemaphoreGetName(osSemaphoreId_t semaphore_id);
|
||||
|
||||
/// Acquire a Semaphore token or timeout if no tokens are available.
|
||||
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
|
||||
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout);
|
||||
|
||||
/// Release a Semaphore token up to the initial maximum count.
|
||||
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id);
|
||||
|
||||
/// Get current Semaphore token count.
|
||||
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
|
||||
/// \return number of tokens available.
|
||||
uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id);
|
||||
|
||||
/// Delete a Semaphore object.
|
||||
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -26,13 +26,13 @@ static ssize_t stdout_write(void* _cookie, const char* data, size_t size) {
|
||||
furi_assert(furi_stdglue);
|
||||
bool consumed = false;
|
||||
osKernelState_t state = osKernelGetState();
|
||||
osThreadId_t thread_id = osThreadGetId();
|
||||
if(state == osKernelRunning && thread_id &&
|
||||
FuriThreadId task_id = furi_thread_get_current_id();
|
||||
if(state == osKernelRunning && task_id &&
|
||||
osMutexAcquire(furi_stdglue->mutex, osWaitForever) == osOK) {
|
||||
// We are in the thread context
|
||||
// Handle thread callbacks
|
||||
FuriStdglueWriteCallback* callback_ptr =
|
||||
FuriStdglueCallbackDict_get(furi_stdglue->thread_outputs, (uint32_t)thread_id);
|
||||
FuriStdglueCallbackDict_get(furi_stdglue->thread_outputs, (uint32_t)task_id);
|
||||
if(callback_ptr) {
|
||||
(*callback_ptr)(_cookie, data, size);
|
||||
consumed = true;
|
||||
@ -76,14 +76,14 @@ void furi_stdglue_init() {
|
||||
|
||||
bool furi_stdglue_set_thread_stdout_callback(FuriStdglueWriteCallback callback) {
|
||||
furi_assert(furi_stdglue);
|
||||
osThreadId_t thread_id = osThreadGetId();
|
||||
if(thread_id) {
|
||||
FuriThreadId task_id = furi_thread_get_current_id();
|
||||
if(task_id) {
|
||||
furi_check(osMutexAcquire(furi_stdglue->mutex, osWaitForever) == osOK);
|
||||
if(callback) {
|
||||
FuriStdglueCallbackDict_set_at(
|
||||
furi_stdglue->thread_outputs, (uint32_t)thread_id, callback);
|
||||
furi_stdglue->thread_outputs, (uint32_t)task_id, callback);
|
||||
} else {
|
||||
FuriStdglueCallbackDict_erase(furi_stdglue->thread_outputs, (uint32_t)thread_id);
|
||||
FuriStdglueCallbackDict_erase(furi_stdglue->thread_outputs, (uint32_t)task_id);
|
||||
}
|
||||
furi_check(osMutexRelease(furi_stdglue->mutex) == osOK);
|
||||
return true;
|
||||
|
@ -2,7 +2,9 @@
|
||||
#include "memmgr.h"
|
||||
#include "memmgr_heap.h"
|
||||
#include "check.h"
|
||||
#include "common_defines.h"
|
||||
|
||||
#include <task.h>
|
||||
#include <m-string.h>
|
||||
|
||||
struct FuriThread {
|
||||
@ -15,14 +17,22 @@ struct FuriThread {
|
||||
FuriThreadStateCallback state_callback;
|
||||
void* state_context;
|
||||
|
||||
osThreadAttr_t attr;
|
||||
volatile osThreadId_t id;
|
||||
char* name;
|
||||
configSTACK_DEPTH_TYPE stack_size;
|
||||
FuriThreadPriority priority;
|
||||
|
||||
TaskHandle_t task_handle;
|
||||
bool heap_trace_enabled;
|
||||
size_t heap_size;
|
||||
};
|
||||
|
||||
void furi_thread_set_state(FuriThread* thread, FuriThreadState state) {
|
||||
/** Catch threads that are trying to exit wrong way */
|
||||
__attribute__((__noreturn__)) void furi_thread_catch() {
|
||||
asm volatile("nop"); // extra magic
|
||||
furi_crash("You are doing it wrong");
|
||||
}
|
||||
|
||||
static void furi_thread_set_state(FuriThread* thread, FuriThreadState state) {
|
||||
furi_assert(thread);
|
||||
thread->state = state;
|
||||
if(thread->state_callback) {
|
||||
@ -37,23 +47,24 @@ static void furi_thread_body(void* context) {
|
||||
furi_assert(thread->state == FuriThreadStateStarting);
|
||||
furi_thread_set_state(thread, FuriThreadStateRunning);
|
||||
|
||||
osThreadId_t thread_id = osThreadGetId();
|
||||
TaskHandle_t task_handle = xTaskGetCurrentTaskHandle();
|
||||
if(thread->heap_trace_enabled == true) {
|
||||
memmgr_heap_enable_thread_trace(thread_id);
|
||||
memmgr_heap_enable_thread_trace((FuriThreadId)task_handle);
|
||||
}
|
||||
|
||||
thread->ret = thread->callback(thread->context);
|
||||
|
||||
if(thread->heap_trace_enabled == true) {
|
||||
osDelay(33);
|
||||
thread->heap_size = memmgr_heap_get_thread_memory(thread_id);
|
||||
memmgr_heap_disable_thread_trace(thread_id);
|
||||
thread->heap_size = memmgr_heap_get_thread_memory((FuriThreadId)task_handle);
|
||||
memmgr_heap_disable_thread_trace((FuriThreadId)task_handle);
|
||||
}
|
||||
|
||||
furi_assert(thread->state == FuriThreadStateRunning);
|
||||
furi_thread_set_state(thread, FuriThreadStateStopped);
|
||||
|
||||
osThreadExit();
|
||||
vTaskDelete(thread->task_handle);
|
||||
furi_thread_catch();
|
||||
}
|
||||
|
||||
FuriThread* furi_thread_alloc() {
|
||||
@ -66,21 +77,22 @@ void furi_thread_free(FuriThread* thread) {
|
||||
furi_assert(thread);
|
||||
furi_assert(thread->state == FuriThreadStateStopped);
|
||||
|
||||
if(thread->attr.name) free((void*)thread->attr.name);
|
||||
if(thread->name) free((void*)thread->name);
|
||||
free(thread);
|
||||
}
|
||||
|
||||
void furi_thread_set_name(FuriThread* thread, const char* name) {
|
||||
furi_assert(thread);
|
||||
furi_assert(thread->state == FuriThreadStateStopped);
|
||||
if(thread->attr.name) free((void*)thread->attr.name);
|
||||
thread->attr.name = strdup(name);
|
||||
if(thread->name) free((void*)thread->name);
|
||||
thread->name = strdup(name);
|
||||
}
|
||||
|
||||
void furi_thread_set_stack_size(FuriThread* thread, size_t stack_size) {
|
||||
furi_assert(thread);
|
||||
furi_assert(thread->state == FuriThreadStateStopped);
|
||||
thread->attr.stack_size = stack_size;
|
||||
furi_assert(stack_size % 4 == 0);
|
||||
thread->stack_size = stack_size;
|
||||
}
|
||||
|
||||
void furi_thread_set_callback(FuriThread* thread, FuriThreadCallback callback) {
|
||||
@ -95,6 +107,13 @@ void furi_thread_set_context(FuriThread* thread, void* context) {
|
||||
thread->context = context;
|
||||
}
|
||||
|
||||
void furi_thread_set_priority(FuriThread* thread, FuriThreadPriority priority) {
|
||||
furi_assert(thread);
|
||||
furi_assert(thread->state == FuriThreadStateStopped);
|
||||
furi_assert(priority >= FuriThreadPriorityIdle && priority <= FuriThreadPriorityIsr);
|
||||
thread->priority = priority;
|
||||
}
|
||||
|
||||
void furi_thread_set_state_callback(FuriThread* thread, FuriThreadStateCallback callback) {
|
||||
furi_assert(thread);
|
||||
furi_assert(thread->state == FuriThreadStateStopped);
|
||||
@ -112,41 +131,39 @@ FuriThreadState furi_thread_get_state(FuriThread* thread) {
|
||||
return thread->state;
|
||||
}
|
||||
|
||||
bool furi_thread_start(FuriThread* thread) {
|
||||
void furi_thread_start(FuriThread* thread) {
|
||||
furi_assert(thread);
|
||||
furi_assert(thread->callback);
|
||||
furi_assert(thread->state == FuriThreadStateStopped);
|
||||
furi_assert(thread->attr.stack_size > 0);
|
||||
furi_assert(thread->stack_size > 0 && thread->stack_size < 0xFFFF * 4);
|
||||
|
||||
furi_thread_set_state(thread, FuriThreadStateStarting);
|
||||
thread->id = osThreadNew(furi_thread_body, thread, &thread->attr);
|
||||
if(thread->id) {
|
||||
return true;
|
||||
} else {
|
||||
furi_assert(thread->state == FuriThreadStateStarting);
|
||||
furi_thread_set_state(thread, FuriThreadStateStopped);
|
||||
return false;
|
||||
}
|
||||
|
||||
BaseType_t ret = xTaskCreate(
|
||||
furi_thread_body,
|
||||
thread->name,
|
||||
thread->stack_size / 4,
|
||||
thread,
|
||||
thread->priority ? thread->priority : FuriThreadPriorityNormal,
|
||||
&thread->task_handle);
|
||||
|
||||
furi_check(ret == pdPASS);
|
||||
furi_check(thread->task_handle);
|
||||
}
|
||||
|
||||
osStatus_t furi_thread_terminate(FuriThread* thread) {
|
||||
bool furi_thread_join(FuriThread* thread) {
|
||||
furi_assert(thread);
|
||||
osStatus_t ret = osThreadTerminate(thread->id);
|
||||
if(ret == osOK) {
|
||||
furi_thread_set_state(thread, FuriThreadStateStopped);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
osStatus_t furi_thread_join(FuriThread* thread) {
|
||||
furi_assert(thread);
|
||||
while(thread->state != FuriThreadStateStopped) {
|
||||
osDelay(10);
|
||||
}
|
||||
|
||||
return osOK;
|
||||
}
|
||||
|
||||
osThreadId_t furi_thread_get_thread_id(FuriThread* thread) {
|
||||
return thread->id;
|
||||
FuriThreadId furi_thread_get_id(FuriThread* thread) {
|
||||
furi_assert(thread);
|
||||
return thread->task_handle;
|
||||
}
|
||||
|
||||
void furi_thread_enable_heap_trace(FuriThread* thread) {
|
||||
@ -174,3 +191,213 @@ int32_t furi_thread_get_return_code(FuriThread* thread) {
|
||||
furi_assert(thread->state == FuriThreadStateStopped);
|
||||
return thread->ret;
|
||||
}
|
||||
|
||||
FuriThreadId furi_thread_get_current_id() {
|
||||
return xTaskGetCurrentTaskHandle();
|
||||
}
|
||||
|
||||
void furi_thread_yield() {
|
||||
furi_assert(!FURI_IS_IRQ_MODE());
|
||||
taskYIELD();
|
||||
}
|
||||
|
||||
/* Limits */
|
||||
#define MAX_BITS_TASK_NOTIFY 31U
|
||||
#define MAX_BITS_EVENT_GROUPS 24U
|
||||
|
||||
#define THREAD_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_TASK_NOTIFY) - 1U))
|
||||
#define EVENT_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_EVENT_GROUPS) - 1U))
|
||||
|
||||
uint32_t furi_thread_flags_set(FuriThreadId thread_id, uint32_t flags) {
|
||||
TaskHandle_t hTask = (TaskHandle_t)thread_id;
|
||||
uint32_t rflags;
|
||||
BaseType_t yield;
|
||||
|
||||
if((hTask == NULL) || ((flags & THREAD_FLAGS_INVALID_BITS) != 0U)) {
|
||||
rflags = (uint32_t)osErrorParameter;
|
||||
} else {
|
||||
rflags = (uint32_t)osError;
|
||||
|
||||
if(FURI_IS_IRQ_MODE()) {
|
||||
yield = pdFALSE;
|
||||
|
||||
(void)xTaskNotifyFromISR(hTask, flags, eSetBits, &yield);
|
||||
(void)xTaskNotifyAndQueryFromISR(hTask, 0, eNoAction, &rflags, NULL);
|
||||
|
||||
portYIELD_FROM_ISR(yield);
|
||||
} else {
|
||||
(void)xTaskNotify(hTask, flags, eSetBits);
|
||||
(void)xTaskNotifyAndQuery(hTask, 0, eNoAction, &rflags);
|
||||
}
|
||||
}
|
||||
/* Return flags after setting */
|
||||
return (rflags);
|
||||
}
|
||||
|
||||
uint32_t furi_thread_flags_clear(uint32_t flags) {
|
||||
TaskHandle_t hTask;
|
||||
uint32_t rflags, cflags;
|
||||
|
||||
if(FURI_IS_IRQ_MODE()) {
|
||||
rflags = (uint32_t)osErrorISR;
|
||||
} else if((flags & THREAD_FLAGS_INVALID_BITS) != 0U) {
|
||||
rflags = (uint32_t)osErrorParameter;
|
||||
} else {
|
||||
hTask = xTaskGetCurrentTaskHandle();
|
||||
|
||||
if(xTaskNotifyAndQuery(hTask, 0, eNoAction, &cflags) == pdPASS) {
|
||||
rflags = cflags;
|
||||
cflags &= ~flags;
|
||||
|
||||
if(xTaskNotify(hTask, cflags, eSetValueWithOverwrite) != pdPASS) {
|
||||
rflags = (uint32_t)osError;
|
||||
}
|
||||
} else {
|
||||
rflags = (uint32_t)osError;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return flags before clearing */
|
||||
return (rflags);
|
||||
}
|
||||
|
||||
uint32_t furi_thread_flags_get(void) {
|
||||
TaskHandle_t hTask;
|
||||
uint32_t rflags;
|
||||
|
||||
if(FURI_IS_IRQ_MODE()) {
|
||||
rflags = (uint32_t)osErrorISR;
|
||||
} else {
|
||||
hTask = xTaskGetCurrentTaskHandle();
|
||||
|
||||
if(xTaskNotifyAndQuery(hTask, 0, eNoAction, &rflags) != pdPASS) {
|
||||
rflags = (uint32_t)osError;
|
||||
}
|
||||
}
|
||||
|
||||
return (rflags);
|
||||
}
|
||||
|
||||
uint32_t furi_thread_flags_wait(uint32_t flags, uint32_t options, uint32_t timeout) {
|
||||
uint32_t rflags, nval;
|
||||
uint32_t clear;
|
||||
TickType_t t0, td, tout;
|
||||
BaseType_t rval;
|
||||
|
||||
if(FURI_IS_IRQ_MODE()) {
|
||||
rflags = (uint32_t)osErrorISR;
|
||||
} else if((flags & THREAD_FLAGS_INVALID_BITS) != 0U) {
|
||||
rflags = (uint32_t)osErrorParameter;
|
||||
} else {
|
||||
if((options & osFlagsNoClear) == osFlagsNoClear) {
|
||||
clear = 0U;
|
||||
} else {
|
||||
clear = flags;
|
||||
}
|
||||
|
||||
rflags = 0U;
|
||||
tout = timeout;
|
||||
|
||||
t0 = xTaskGetTickCount();
|
||||
do {
|
||||
rval = xTaskNotifyWait(0, clear, &nval, tout);
|
||||
|
||||
if(rval == pdPASS) {
|
||||
rflags &= flags;
|
||||
rflags |= nval;
|
||||
|
||||
if((options & osFlagsWaitAll) == osFlagsWaitAll) {
|
||||
if((flags & rflags) == flags) {
|
||||
break;
|
||||
} else {
|
||||
if(timeout == 0U) {
|
||||
rflags = (uint32_t)osErrorResource;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if((flags & rflags) != 0) {
|
||||
break;
|
||||
} else {
|
||||
if(timeout == 0U) {
|
||||
rflags = (uint32_t)osErrorResource;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update timeout */
|
||||
td = xTaskGetTickCount() - t0;
|
||||
|
||||
if(td > tout) {
|
||||
tout = 0;
|
||||
} else {
|
||||
tout -= td;
|
||||
}
|
||||
} else {
|
||||
if(timeout == 0) {
|
||||
rflags = (uint32_t)osErrorResource;
|
||||
} else {
|
||||
rflags = (uint32_t)osErrorTimeout;
|
||||
}
|
||||
}
|
||||
} while(rval != pdFAIL);
|
||||
}
|
||||
|
||||
/* Return flags before clearing */
|
||||
return (rflags);
|
||||
}
|
||||
|
||||
uint32_t furi_thread_enumerate(FuriThreadId* thread_array, uint32_t array_items) {
|
||||
uint32_t i, count;
|
||||
TaskStatus_t* task;
|
||||
|
||||
if(FURI_IS_IRQ_MODE() || (thread_array == NULL) || (array_items == 0U)) {
|
||||
count = 0U;
|
||||
} else {
|
||||
vTaskSuspendAll();
|
||||
|
||||
count = uxTaskGetNumberOfTasks();
|
||||
task = pvPortMalloc(count * sizeof(TaskStatus_t));
|
||||
|
||||
if(task != NULL) {
|
||||
count = uxTaskGetSystemState(task, count, NULL);
|
||||
|
||||
for(i = 0U; (i < count) && (i < array_items); i++) {
|
||||
thread_array[i] = (FuriThreadId)task[i].xHandle;
|
||||
}
|
||||
count = i;
|
||||
}
|
||||
(void)xTaskResumeAll();
|
||||
|
||||
vPortFree(task);
|
||||
}
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
const char* furi_thread_get_name(FuriThreadId thread_id) {
|
||||
TaskHandle_t hTask = (TaskHandle_t)thread_id;
|
||||
const char* name;
|
||||
|
||||
if(FURI_IS_IRQ_MODE() || (hTask == NULL)) {
|
||||
name = NULL;
|
||||
} else {
|
||||
name = pcTaskGetName(hTask);
|
||||
}
|
||||
|
||||
return (name);
|
||||
}
|
||||
|
||||
uint32_t furi_thread_get_stack_space(FuriThreadId thread_id) {
|
||||
TaskHandle_t hTask = (TaskHandle_t)thread_id;
|
||||
uint32_t sz;
|
||||
|
||||
if(FURI_IS_IRQ_MODE() || (hTask == NULL)) {
|
||||
sz = 0U;
|
||||
} else {
|
||||
sz = (uint32_t)(uxTaskGetStackHighWaterMark(hTask) * sizeof(StackType_t));
|
||||
}
|
||||
|
||||
return (sz);
|
||||
}
|
||||
|
@ -5,9 +5,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <cmsis_os2.h>
|
||||
#include "base.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -20,9 +18,24 @@ typedef enum {
|
||||
FuriThreadStateRunning,
|
||||
} FuriThreadState;
|
||||
|
||||
/** FuriThreadPriority */
|
||||
typedef enum {
|
||||
FuriThreadPriorityNone = 0, /**< Uninitialized, choose system default */
|
||||
FuriThreadPriorityIdle = 1, /**< Idle priority */
|
||||
FuriThreadPriorityLowest = 14, /**< Lowest */
|
||||
FuriThreadPriorityLow = 15, /**< Low */
|
||||
FuriThreadPriorityNormal = 16, /**< Normal */
|
||||
FuriThreadPriorityHigh = 17, /**< High */
|
||||
FuriThreadPriorityHighest = 18, /**< Highest */
|
||||
FuriThreadPriorityIsr = 32, /**< Deffered Isr (highest possible) */
|
||||
} FuriThreadPriority;
|
||||
|
||||
/** FuriThread anonymous structure */
|
||||
typedef struct FuriThread FuriThread;
|
||||
|
||||
/** FuriThreadId proxy type to OS low level functions */
|
||||
typedef void* FuriThreadId;
|
||||
|
||||
/** FuriThreadCallback Your callback to run in new thread
|
||||
* @warning never use osThreadExit in FuriThread
|
||||
*/
|
||||
@ -74,6 +87,13 @@ void furi_thread_set_callback(FuriThread* thread, FuriThreadCallback callback);
|
||||
*/
|
||||
void furi_thread_set_context(FuriThread* thread, void* context);
|
||||
|
||||
/** Set FuriThread priority
|
||||
*
|
||||
* @param thread FuriThread instance
|
||||
* @param priority FuriThreadPriority value
|
||||
*/
|
||||
void furi_thread_set_priority(FuriThread* thread, FuriThreadPriority priority);
|
||||
|
||||
/** Set FuriThread state change callback
|
||||
*
|
||||
* @param thread FuriThread instance
|
||||
@ -99,36 +119,24 @@ FuriThreadState furi_thread_get_state(FuriThread* thread);
|
||||
/** Start FuriThread
|
||||
*
|
||||
* @param thread FuriThread instance
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool furi_thread_start(FuriThread* thread);
|
||||
|
||||
/** Treminate FuriThread
|
||||
*
|
||||
* @param thread FuriThread instance
|
||||
*
|
||||
* @return osStatus_t
|
||||
* @warning terminating statefull thread is dangerous use only if you know
|
||||
* what you doing
|
||||
*/
|
||||
osStatus_t furi_thread_terminate(FuriThread* thread);
|
||||
void furi_thread_start(FuriThread* thread);
|
||||
|
||||
/** Join FuriThread
|
||||
*
|
||||
* @param thread FuriThread instance
|
||||
*
|
||||
* @return osStatus_t
|
||||
* @return bool
|
||||
*/
|
||||
osStatus_t furi_thread_join(FuriThread* thread);
|
||||
bool furi_thread_join(FuriThread* thread);
|
||||
|
||||
/** Get CMSIS Thread ID
|
||||
/** Get FreeRTOS FuriThreadId for FuriThread instance
|
||||
*
|
||||
* @param thread FuriThread instance
|
||||
*
|
||||
* @return osThreadId_t or NULL
|
||||
* @return FuriThreadId or NULL
|
||||
*/
|
||||
osThreadId_t furi_thread_get_thread_id(FuriThread* thread);
|
||||
FuriThreadId furi_thread_get_id(FuriThread* thread);
|
||||
|
||||
/** Enable heap tracing
|
||||
*
|
||||
@ -158,6 +166,33 @@ size_t furi_thread_get_heap_size(FuriThread* thread);
|
||||
*/
|
||||
int32_t furi_thread_get_return_code(FuriThread* thread);
|
||||
|
||||
/** Thread releated methods that doesn't involve FuriThread directly */
|
||||
|
||||
/** Get FreeRTOS FuriThreadId for current thread
|
||||
*
|
||||
* @param thread FuriThread instance
|
||||
*
|
||||
* @return FuriThreadId or NULL
|
||||
*/
|
||||
FuriThreadId furi_thread_get_current_id();
|
||||
|
||||
/** Return control to scheduler */
|
||||
void furi_thread_yield();
|
||||
|
||||
uint32_t furi_thread_flags_set(FuriThreadId thread_id, uint32_t flags);
|
||||
|
||||
uint32_t furi_thread_flags_clear(uint32_t flags);
|
||||
|
||||
uint32_t furi_thread_flags_get(void);
|
||||
|
||||
uint32_t furi_thread_flags_wait(uint32_t flags, uint32_t options, uint32_t timeout);
|
||||
|
||||
uint32_t furi_thread_enumerate(FuriThreadId* thread_array, uint32_t array_items);
|
||||
|
||||
const char* furi_thread_get_name(FuriThreadId thread_id);
|
||||
|
||||
uint32_t furi_thread_get_stack_space(FuriThreadId thread_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <cmsis_os2.h>
|
||||
#include <stdbool.h>
|
||||
#include "mutex.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -20,7 +20,7 @@ extern uint32_t SystemCoreClock;
|
||||
#define configUSE_TICK_HOOK 0
|
||||
#define configCPU_CLOCK_HZ (SystemCoreClock)
|
||||
#define configTICK_RATE_HZ ((TickType_t)1000)
|
||||
#define configMAX_PRIORITIES (56)
|
||||
#define configMAX_PRIORITIES (32)
|
||||
#define configMINIMAL_STACK_SIZE ((uint16_t)128)
|
||||
|
||||
/* Heap size determined automatically by linker */
|
||||
@ -35,7 +35,7 @@ extern uint32_t SystemCoreClock;
|
||||
#define configUSE_RECURSIVE_MUTEXES 1
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
#define configENABLE_BACKWARD_COMPATIBILITY 0
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#define configUSE_TICKLESS_IDLE 2
|
||||
#define configRECORD_STACK_HIGH_ADDRESS 1
|
||||
#define configUSE_NEWLIB_REENTRANT 0
|
||||
@ -89,6 +89,9 @@ to exclude the API function. */
|
||||
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 2
|
||||
#define CMSIS_TASK_NOTIFY_INDEX 1
|
||||
|
||||
extern __attribute__((__noreturn__)) void furi_thread_catch();
|
||||
#define configTASK_RETURN_ADDRESS (furi_thread_catch + 2)
|
||||
|
||||
/*
|
||||
* The CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation used
|
||||
* by the application thus the correct define need to be enabled below
|
||||
|
@ -7,19 +7,16 @@
|
||||
|
||||
#define TAG "Main"
|
||||
|
||||
static const osThreadAttr_t init_thread_attr = {
|
||||
.name = "Init",
|
||||
.stack_size = 4096,
|
||||
};
|
||||
int32_t init_task(void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
void init_task() {
|
||||
// Flipper FURI HAL
|
||||
furi_hal_init();
|
||||
|
||||
// Init flipper
|
||||
flipper_init();
|
||||
|
||||
osThreadExit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
@ -29,8 +26,13 @@ int main() {
|
||||
// Flipper critical FURI HAL
|
||||
furi_hal_init_early();
|
||||
|
||||
FuriThread* main_thread = furi_thread_alloc();
|
||||
furi_thread_set_name(main_thread, "Init");
|
||||
furi_thread_set_stack_size(main_thread, 4096);
|
||||
furi_thread_set_callback(main_thread, init_task);
|
||||
|
||||
#ifdef FURI_RAM_EXEC
|
||||
osThreadNew(init_task, NULL, &init_thread_attr);
|
||||
furi_thread_start(main_thread);
|
||||
#else
|
||||
furi_hal_light_sequence("RGB");
|
||||
|
||||
@ -52,7 +54,7 @@ int main() {
|
||||
furi_hal_power_reset();
|
||||
} else {
|
||||
furi_hal_light_sequence("rgb G");
|
||||
osThreadNew(init_task, NULL, &init_thread_attr);
|
||||
furi_thread_start(main_thread);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "gap.h"
|
||||
|
||||
#include <furi_hal.h>
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "Bt"
|
||||
|
||||
@ -106,9 +107,9 @@ void ble_app_get_key_storage_buff(uint8_t** addr, uint16_t* size) {
|
||||
|
||||
void ble_app_thread_stop() {
|
||||
if(ble_app) {
|
||||
osThreadId_t thread_id = furi_thread_get_thread_id(ble_app->thread);
|
||||
FuriThreadId thread_id = furi_thread_get_id(ble_app->thread);
|
||||
furi_assert(thread_id);
|
||||
osThreadFlagsSet(thread_id, BLE_APP_FLAG_KILL_THREAD);
|
||||
furi_thread_flags_set(thread_id, BLE_APP_FLAG_KILL_THREAD);
|
||||
furi_thread_join(ble_app->thread);
|
||||
furi_thread_free(ble_app->thread);
|
||||
// Free resources
|
||||
@ -125,7 +126,7 @@ static int32_t ble_app_hci_thread(void* arg) {
|
||||
uint32_t flags = 0;
|
||||
|
||||
while(1) {
|
||||
flags = osThreadFlagsWait(BLE_APP_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
||||
flags = furi_thread_flags_wait(BLE_APP_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
||||
if(flags & BLE_APP_FLAG_KILL_THREAD) {
|
||||
break;
|
||||
}
|
||||
@ -141,9 +142,9 @@ static int32_t ble_app_hci_thread(void* arg) {
|
||||
void hci_notify_asynch_evt(void* pdata) {
|
||||
UNUSED(pdata);
|
||||
if(ble_app) {
|
||||
osThreadId_t thread_id = furi_thread_get_thread_id(ble_app->thread);
|
||||
FuriThreadId thread_id = furi_thread_get_id(ble_app->thread);
|
||||
furi_assert(thread_id);
|
||||
osThreadFlagsSet(thread_id, BLE_APP_FLAG_HCI_EVENT);
|
||||
furi_thread_flags_set(thread_id, BLE_APP_FLAG_HCI_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -333,9 +333,9 @@ static void ble_glue_clear_shared_memory() {
|
||||
|
||||
void ble_glue_thread_stop() {
|
||||
if(ble_glue) {
|
||||
osThreadId_t thread_id = furi_thread_get_thread_id(ble_glue->thread);
|
||||
FuriThreadId thread_id = furi_thread_get_id(ble_glue->thread);
|
||||
furi_assert(thread_id);
|
||||
osThreadFlagsSet(thread_id, BLE_GLUE_FLAG_KILL_THREAD);
|
||||
furi_thread_flags_set(thread_id, BLE_GLUE_FLAG_KILL_THREAD);
|
||||
furi_thread_join(ble_glue->thread);
|
||||
furi_thread_free(ble_glue->thread);
|
||||
// Free resources
|
||||
@ -353,7 +353,7 @@ static int32_t ble_glue_shci_thread(void* context) {
|
||||
uint32_t flags = 0;
|
||||
|
||||
while(true) {
|
||||
flags = osThreadFlagsWait(BLE_GLUE_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
||||
flags = furi_thread_flags_wait(BLE_GLUE_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
||||
if(flags & BLE_GLUE_FLAG_SHCI_EVENT) {
|
||||
shci_user_evt_proc();
|
||||
}
|
||||
@ -368,9 +368,9 @@ static int32_t ble_glue_shci_thread(void* context) {
|
||||
void shci_notify_asynch_evt(void* pdata) {
|
||||
UNUSED(pdata);
|
||||
if(ble_glue) {
|
||||
osThreadId_t thread_id = furi_thread_get_thread_id(ble_glue->thread);
|
||||
FuriThreadId thread_id = furi_thread_get_id(ble_glue->thread);
|
||||
furi_assert(thread_id);
|
||||
osThreadFlagsSet(thread_id, BLE_GLUE_FLAG_SHCI_EVENT);
|
||||
furi_thread_flags_set(thread_id, BLE_GLUE_FLAG_SHCI_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,7 +322,7 @@ void furi_hal_bt_set_key_storage_change_callback(
|
||||
|
||||
void furi_hal_bt_nvm_sram_sem_acquire() {
|
||||
while(LL_HSEM_1StepLock(HSEM, CFG_HW_BLE_NVM_SRAM_SEMID)) {
|
||||
osThreadYield();
|
||||
furi_thread_yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ void furi_hal_crc_init(bool synchronize) {
|
||||
void furi_hal_crc_reset() {
|
||||
furi_check(hal_crc_control.state == CRC_State_Ready);
|
||||
if(hal_crc_control.mtx) {
|
||||
furi_check(osMutexGetOwner(hal_crc_control.mtx) == osThreadGetId());
|
||||
furi_check(osMutexGetOwner(hal_crc_control.mtx) == furi_thread_get_current_id());
|
||||
osMutexRelease(hal_crc_control.mtx);
|
||||
}
|
||||
LL_CRC_ResetCRCCalculationUnit(CRC);
|
||||
|
@ -112,7 +112,7 @@ static void furi_hal_flash_lock(void) {
|
||||
static void furi_hal_flash_begin_with_core2(bool erase_flag) {
|
||||
// Take flash controller ownership
|
||||
while(LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID) != 0) {
|
||||
osThreadYield();
|
||||
furi_thread_yield();
|
||||
}
|
||||
|
||||
// Unlock flash operation
|
||||
@ -128,7 +128,7 @@ static void furi_hal_flash_begin_with_core2(bool erase_flag) {
|
||||
while(true) {
|
||||
// Wait till flash controller become usable
|
||||
while(LL_FLASH_IsActiveFlag_OperationSuspended()) {
|
||||
osThreadYield();
|
||||
furi_thread_yield();
|
||||
};
|
||||
|
||||
// Just a little more love
|
||||
@ -137,14 +137,14 @@ static void furi_hal_flash_begin_with_core2(bool erase_flag) {
|
||||
// Actually we already have mutex for it, but specification is specification
|
||||
if(LL_HSEM_IsSemaphoreLocked(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID)) {
|
||||
taskEXIT_CRITICAL();
|
||||
osThreadYield();
|
||||
furi_thread_yield();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Take sempahopre and prevent core2 from anything funky
|
||||
if(LL_HSEM_1StepLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID) != 0) {
|
||||
taskEXIT_CRITICAL();
|
||||
osThreadYield();
|
||||
furi_thread_yield();
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -173,7 +173,7 @@ static void furi_hal_flash_end_with_core2(bool erase_flag) {
|
||||
|
||||
// Doesn't make much sense, does it?
|
||||
while(READ_BIT(FLASH->SR, FLASH_SR_BSY)) {
|
||||
osThreadYield();
|
||||
furi_thread_yield();
|
||||
}
|
||||
|
||||
// Erase activity over, core2 can continue
|
||||
@ -498,7 +498,7 @@ bool furi_hal_flash_ob_set_word(size_t word_idx, const uint32_t value) {
|
||||
/* 3. Check that no Flash memory operation is on going by checking the BSY && PESD */
|
||||
furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT));
|
||||
while(LL_FLASH_IsActiveFlag_OperationSuspended()) {
|
||||
osThreadYield();
|
||||
furi_thread_yield();
|
||||
};
|
||||
|
||||
/* 4. Set the Options start bit OPTSTRT */
|
||||
|
@ -179,7 +179,7 @@ bool furi_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid) {
|
||||
FURI_LOG_T(TAG, "Timeout");
|
||||
return false;
|
||||
}
|
||||
osThreadYield();
|
||||
furi_thread_yield();
|
||||
}
|
||||
rfalNfcGetDevicesFound(&dev_list, &dev_cnt);
|
||||
// Take first device and set cuid
|
||||
@ -397,14 +397,14 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_
|
||||
}
|
||||
|
||||
// Manually wait for interrupt
|
||||
furi_hal_gpio_init(&gpio_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh);
|
||||
st25r3916ClearAndEnableInterrupts(ST25R3916_IRQ_MASK_RXE);
|
||||
|
||||
uint32_t irq = 0;
|
||||
uint8_t rxe = 0;
|
||||
uint32_t start = DWT->CYCCNT;
|
||||
while(true) {
|
||||
if(furi_hal_gpio_read(&gpio_rfid_pull) == true) {
|
||||
if(furi_hal_gpio_read(&gpio_nfc_irq_rfid_pull) == true) {
|
||||
st25r3916ReadRegister(ST25R3916_REG_IRQ_MAIN, &rxe);
|
||||
if(rxe & (1 << 4)) {
|
||||
irq = 1;
|
||||
|
@ -42,7 +42,7 @@ const GpioPin gpio_ext_pa4 = {.port = GPIOA, .pin = LL_GPIO_PIN_4};
|
||||
const GpioPin gpio_ext_pa6 = {.port = GPIOA, .pin = LL_GPIO_PIN_6};
|
||||
const GpioPin gpio_ext_pa7 = {.port = GPIOA, .pin = LL_GPIO_PIN_7};
|
||||
|
||||
const GpioPin gpio_rfid_pull = {.port = RFID_PULL_GPIO_Port, .pin = RFID_PULL_Pin};
|
||||
const GpioPin gpio_nfc_irq_rfid_pull = {.port = RFID_PULL_GPIO_Port, .pin = RFID_PULL_Pin};
|
||||
const GpioPin gpio_rfid_carrier_out = {.port = RFID_OUT_GPIO_Port, .pin = RFID_OUT_Pin};
|
||||
const GpioPin gpio_rfid_data_in = {.port = RFID_RF_IN_GPIO_Port, .pin = RFID_RF_IN_Pin};
|
||||
const GpioPin gpio_rfid_carrier = {.port = RFID_CARRIER_GPIO_Port, .pin = RFID_CARRIER_Pin};
|
||||
@ -138,7 +138,7 @@ void furi_hal_resources_init() {
|
||||
|
||||
furi_hal_gpio_init(&ibutton_gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
furi_hal_gpio_init(&gpio_rfid_pull, GpioModeInterruptRise, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInterruptRise, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
furi_hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
|
@ -77,7 +77,7 @@ extern const GpioPin gpio_ext_pa4;
|
||||
extern const GpioPin gpio_ext_pa6;
|
||||
extern const GpioPin gpio_ext_pa7;
|
||||
|
||||
extern const GpioPin gpio_rfid_pull;
|
||||
extern const GpioPin gpio_nfc_irq_rfid_pull;
|
||||
extern const GpioPin gpio_rfid_carrier_out;
|
||||
extern const GpioPin gpio_rfid_data_in;
|
||||
extern const GpioPin gpio_rfid_carrier;
|
||||
|
@ -69,8 +69,8 @@ void furi_hal_rfid_pins_reset() {
|
||||
furi_hal_gpio_write(&gpio_rfid_carrier_out, false);
|
||||
|
||||
// from both sides
|
||||
furi_hal_gpio_init(&gpio_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_write(&gpio_rfid_pull, true);
|
||||
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, true);
|
||||
|
||||
furi_hal_gpio_init_simple(&gpio_rfid_carrier, GpioModeAnalog);
|
||||
|
||||
@ -84,7 +84,11 @@ void furi_hal_rfid_pins_emulate() {
|
||||
|
||||
// pull pin to timer out
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_rfid_pull, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2);
|
||||
&gpio_nfc_irq_rfid_pull,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedLow,
|
||||
GpioAltFn1TIM2);
|
||||
|
||||
// pull rfid antenna from carrier side
|
||||
furi_hal_gpio_init(&gpio_rfid_carrier_out, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
@ -100,8 +104,8 @@ void furi_hal_rfid_pins_read() {
|
||||
furi_hal_ibutton_pin_low();
|
||||
|
||||
// dont pull rfid antenna
|
||||
furi_hal_gpio_init(&gpio_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_write(&gpio_rfid_pull, false);
|
||||
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, false);
|
||||
|
||||
// carrier pin to timer out
|
||||
furi_hal_gpio_init_ex(
|
||||
@ -116,11 +120,11 @@ void furi_hal_rfid_pins_read() {
|
||||
}
|
||||
|
||||
void furi_hal_rfid_pin_pull_release() {
|
||||
furi_hal_gpio_write(&gpio_rfid_pull, true);
|
||||
furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, true);
|
||||
}
|
||||
|
||||
void furi_hal_rfid_pin_pull_pulldown() {
|
||||
furi_hal_gpio_write(&gpio_rfid_pull, false);
|
||||
furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, false);
|
||||
}
|
||||
|
||||
void furi_hal_rfid_tim_read(float freq, float duty_cycle) {
|
||||
|
@ -101,7 +101,7 @@ bool furi_hal_usb_set_config(FuriHalUsbInterface* new_if, void* ctx) {
|
||||
return true;
|
||||
}
|
||||
furi_assert(usb.thread);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventModeChange);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb.thread), EventModeChange);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -125,17 +125,17 @@ bool furi_hal_usb_is_locked() {
|
||||
|
||||
void furi_hal_usb_disable() {
|
||||
furi_assert(usb.thread);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventDisable);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb.thread), EventDisable);
|
||||
}
|
||||
|
||||
void furi_hal_usb_enable() {
|
||||
furi_assert(usb.thread);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventEnable);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb.thread), EventEnable);
|
||||
}
|
||||
|
||||
void furi_hal_usb_reinit() {
|
||||
furi_assert(usb.thread);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventReinit);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb.thread), EventReinit);
|
||||
}
|
||||
|
||||
/* Get device / configuration descriptors */
|
||||
@ -148,7 +148,7 @@ static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_
|
||||
|
||||
switch(dtype) {
|
||||
case USB_DTYPE_DEVICE:
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventRequest);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb.thread), EventRequest);
|
||||
if(usb.callback != NULL) {
|
||||
usb.callback(FuriHalUsbStateEventDescriptorRequest, usb.cb_ctx);
|
||||
}
|
||||
@ -192,7 +192,7 @@ static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep) {
|
||||
UNUSED(dev);
|
||||
UNUSED(event);
|
||||
UNUSED(ep);
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventReset);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb.thread), EventReset);
|
||||
if(usb.callback != NULL) {
|
||||
usb.callback(FuriHalUsbStateEventReset, usb.cb_ctx);
|
||||
}
|
||||
@ -236,11 +236,11 @@ static int32_t furi_hal_usb_thread(void* context) {
|
||||
FuriHalUsbInterface* if_ctx_new = NULL;
|
||||
|
||||
if(usb.if_next != NULL) {
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventModeChange);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb.thread), EventModeChange);
|
||||
}
|
||||
|
||||
while(true) {
|
||||
uint32_t flags = osThreadFlagsWait(USB_SRV_ALL_EVENTS, osFlagsWaitAny, 500);
|
||||
uint32_t flags = furi_thread_flags_wait(USB_SRV_ALL_EVENTS, osFlagsWaitAny, 500);
|
||||
if((flags & osFlagsError) == 0) {
|
||||
if(flags & EventModeChange) {
|
||||
if(usb.if_next != usb.if_cur) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -61,8 +61,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <furi/base.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
@ -89,77 +88,6 @@ typedef enum {
|
||||
osKernelReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
|
||||
} osKernelState_t;
|
||||
|
||||
/// Thread state.
|
||||
typedef enum {
|
||||
osThreadInactive = 0, ///< Inactive.
|
||||
osThreadReady = 1, ///< Ready.
|
||||
osThreadRunning = 2, ///< Running.
|
||||
osThreadBlocked = 3, ///< Blocked.
|
||||
osThreadTerminated = 4, ///< Terminated.
|
||||
osThreadError = -1, ///< Error.
|
||||
osThreadReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
|
||||
} osThreadState_t;
|
||||
|
||||
/// Priority values.
|
||||
typedef enum {
|
||||
osPriorityNone = 0, ///< No priority (not initialized).
|
||||
osPriorityIdle = 1, ///< Reserved for Idle thread.
|
||||
osPriorityLow = 8, ///< Priority: low
|
||||
osPriorityLow1 = 8+1, ///< Priority: low + 1
|
||||
osPriorityLow2 = 8+2, ///< Priority: low + 2
|
||||
osPriorityLow3 = 8+3, ///< Priority: low + 3
|
||||
osPriorityLow4 = 8+4, ///< Priority: low + 4
|
||||
osPriorityLow5 = 8+5, ///< Priority: low + 5
|
||||
osPriorityLow6 = 8+6, ///< Priority: low + 6
|
||||
osPriorityLow7 = 8+7, ///< Priority: low + 7
|
||||
osPriorityBelowNormal = 16, ///< Priority: below normal
|
||||
osPriorityBelowNormal1 = 16+1, ///< Priority: below normal + 1
|
||||
osPriorityBelowNormal2 = 16+2, ///< Priority: below normal + 2
|
||||
osPriorityBelowNormal3 = 16+3, ///< Priority: below normal + 3
|
||||
osPriorityBelowNormal4 = 16+4, ///< Priority: below normal + 4
|
||||
osPriorityBelowNormal5 = 16+5, ///< Priority: below normal + 5
|
||||
osPriorityBelowNormal6 = 16+6, ///< Priority: below normal + 6
|
||||
osPriorityBelowNormal7 = 16+7, ///< Priority: below normal + 7
|
||||
osPriorityNormal = 24, ///< Priority: normal
|
||||
osPriorityNormal1 = 24+1, ///< Priority: normal + 1
|
||||
osPriorityNormal2 = 24+2, ///< Priority: normal + 2
|
||||
osPriorityNormal3 = 24+3, ///< Priority: normal + 3
|
||||
osPriorityNormal4 = 24+4, ///< Priority: normal + 4
|
||||
osPriorityNormal5 = 24+5, ///< Priority: normal + 5
|
||||
osPriorityNormal6 = 24+6, ///< Priority: normal + 6
|
||||
osPriorityNormal7 = 24+7, ///< Priority: normal + 7
|
||||
osPriorityAboveNormal = 32, ///< Priority: above normal
|
||||
osPriorityAboveNormal1 = 32+1, ///< Priority: above normal + 1
|
||||
osPriorityAboveNormal2 = 32+2, ///< Priority: above normal + 2
|
||||
osPriorityAboveNormal3 = 32+3, ///< Priority: above normal + 3
|
||||
osPriorityAboveNormal4 = 32+4, ///< Priority: above normal + 4
|
||||
osPriorityAboveNormal5 = 32+5, ///< Priority: above normal + 5
|
||||
osPriorityAboveNormal6 = 32+6, ///< Priority: above normal + 6
|
||||
osPriorityAboveNormal7 = 32+7, ///< Priority: above normal + 7
|
||||
osPriorityHigh = 40, ///< Priority: high
|
||||
osPriorityHigh1 = 40+1, ///< Priority: high + 1
|
||||
osPriorityHigh2 = 40+2, ///< Priority: high + 2
|
||||
osPriorityHigh3 = 40+3, ///< Priority: high + 3
|
||||
osPriorityHigh4 = 40+4, ///< Priority: high + 4
|
||||
osPriorityHigh5 = 40+5, ///< Priority: high + 5
|
||||
osPriorityHigh6 = 40+6, ///< Priority: high + 6
|
||||
osPriorityHigh7 = 40+7, ///< Priority: high + 7
|
||||
osPriorityRealtime = 48, ///< Priority: realtime
|
||||
osPriorityRealtime1 = 48+1, ///< Priority: realtime + 1
|
||||
osPriorityRealtime2 = 48+2, ///< Priority: realtime + 2
|
||||
osPriorityRealtime3 = 48+3, ///< Priority: realtime + 3
|
||||
osPriorityRealtime4 = 48+4, ///< Priority: realtime + 4
|
||||
osPriorityRealtime5 = 48+5, ///< Priority: realtime + 5
|
||||
osPriorityRealtime6 = 48+6, ///< Priority: realtime + 6
|
||||
osPriorityRealtime7 = 48+7, ///< Priority: realtime + 7
|
||||
osPriorityISR = 56, ///< Reserved for ISR deferred thread.
|
||||
osPriorityError = -1, ///< System cannot determine priority or illegal priority.
|
||||
osPriorityReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
|
||||
} osPriority_t;
|
||||
|
||||
/// Entry point of a thread.
|
||||
typedef void (*osThreadFunc_t) (void *argument);
|
||||
|
||||
/// Timer callback function.
|
||||
typedef void (*osTimerFunc_t) (void *argument);
|
||||
|
||||
@ -169,62 +97,10 @@ typedef enum {
|
||||
osTimerPeriodic = 1 ///< Repeating timer.
|
||||
} osTimerType_t;
|
||||
|
||||
// Timeout value.
|
||||
#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value.
|
||||
|
||||
// Flags options (\ref osThreadFlagsWait and \ref osEventFlagsWait).
|
||||
#define osFlagsWaitAny 0x00000000U ///< Wait for any flag (default).
|
||||
#define osFlagsWaitAll 0x00000001U ///< Wait for all flags.
|
||||
#define osFlagsNoClear 0x00000002U ///< Do not clear flags which have been specified to wait for.
|
||||
|
||||
// Flags errors (returned by osThreadFlagsXxxx and osEventFlagsXxxx).
|
||||
#define osFlagsError 0x80000000U ///< Error indicator.
|
||||
#define osFlagsErrorUnknown 0xFFFFFFFFU ///< osError (-1).
|
||||
#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2).
|
||||
#define osFlagsErrorResource 0xFFFFFFFDU ///< osErrorResource (-3).
|
||||
#define osFlagsErrorParameter 0xFFFFFFFCU ///< osErrorParameter (-4).
|
||||
#define osFlagsErrorISR 0xFFFFFFFAU ///< osErrorISR (-6).
|
||||
|
||||
// Thread attributes (attr_bits in \ref osThreadAttr_t).
|
||||
#define osThreadDetached 0x00000000U ///< Thread created in detached mode (default)
|
||||
#define osThreadJoinable 0x00000001U ///< Thread created in joinable mode
|
||||
|
||||
// Mutex attributes (attr_bits in \ref osMutexAttr_t).
|
||||
#define osMutexRecursive 0x00000001U ///< Recursive mutex.
|
||||
#define osMutexPrioInherit 0x00000002U ///< Priority inherit protocol.
|
||||
#define osMutexRobust 0x00000008U ///< Robust mutex.
|
||||
|
||||
/// Status code values returned by CMSIS-RTOS functions.
|
||||
typedef enum {
|
||||
osOK = 0, ///< Operation completed successfully.
|
||||
osError = -1, ///< Unspecified RTOS error: run-time error but no other error message fits.
|
||||
osErrorTimeout = -2, ///< Operation not completed within the timeout period.
|
||||
osErrorResource = -3, ///< Resource not available.
|
||||
osErrorParameter = -4, ///< Parameter error.
|
||||
osErrorNoMemory = -5, ///< System is out of memory: it was impossible to allocate or reserve memory for the operation.
|
||||
osErrorISR = -6, ///< Not allowed in ISR context: the function cannot be called from interrupt service routines.
|
||||
osStatusReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
|
||||
} osStatus_t;
|
||||
|
||||
|
||||
/// \details Thread ID identifies the thread.
|
||||
typedef void *osThreadId_t;
|
||||
|
||||
/// \details Timer ID identifies the timer.
|
||||
typedef void *osTimerId_t;
|
||||
|
||||
/// \details Event Flags ID identifies the event flags.
|
||||
typedef void *osEventFlagsId_t;
|
||||
|
||||
/// \details Mutex ID identifies the mutex.
|
||||
typedef void *osMutexId_t;
|
||||
|
||||
/// \details Semaphore ID identifies the semaphore.
|
||||
typedef void *osSemaphoreId_t;
|
||||
|
||||
/// \details Memory Pool ID identifies the memory pool.
|
||||
typedef void *osMemoryPoolId_t;
|
||||
|
||||
/// \details Message Queue ID identifies the message queue.
|
||||
typedef void *osMessageQueueId_t;
|
||||
|
||||
@ -236,19 +112,6 @@ typedef uint32_t TZ_ModuleId_t;
|
||||
#endif
|
||||
|
||||
|
||||
/// Attributes structure for thread.
|
||||
typedef struct {
|
||||
const char *name; ///< name of the thread
|
||||
uint32_t attr_bits; ///< attribute bits
|
||||
void *cb_mem; ///< memory for control block
|
||||
uint32_t cb_size; ///< size of provided memory for control block
|
||||
void *stack_mem; ///< memory for stack
|
||||
uint32_t stack_size; ///< size of stack
|
||||
osPriority_t priority; ///< initial thread priority (default: osPriorityNormal)
|
||||
TZ_ModuleId_t tz_module; ///< TrustZone module identifier
|
||||
uint32_t reserved; ///< reserved (must be 0)
|
||||
} osThreadAttr_t;
|
||||
|
||||
/// Attributes structure for timer.
|
||||
typedef struct {
|
||||
const char *name; ///< name of the timer
|
||||
@ -257,40 +120,6 @@ typedef struct {
|
||||
uint32_t cb_size; ///< size of provided memory for control block
|
||||
} osTimerAttr_t;
|
||||
|
||||
/// Attributes structure for event flags.
|
||||
typedef struct {
|
||||
const char *name; ///< name of the event flags
|
||||
uint32_t attr_bits; ///< attribute bits
|
||||
void *cb_mem; ///< memory for control block
|
||||
uint32_t cb_size; ///< size of provided memory for control block
|
||||
} osEventFlagsAttr_t;
|
||||
|
||||
/// Attributes structure for mutex.
|
||||
typedef struct {
|
||||
const char *name; ///< name of the mutex
|
||||
uint32_t attr_bits; ///< attribute bits
|
||||
void *cb_mem; ///< memory for control block
|
||||
uint32_t cb_size; ///< size of provided memory for control block
|
||||
} osMutexAttr_t;
|
||||
|
||||
/// Attributes structure for semaphore.
|
||||
typedef struct {
|
||||
const char *name; ///< name of the semaphore
|
||||
uint32_t attr_bits; ///< attribute bits
|
||||
void *cb_mem; ///< memory for control block
|
||||
uint32_t cb_size; ///< size of provided memory for control block
|
||||
} osSemaphoreAttr_t;
|
||||
|
||||
/// Attributes structure for memory pool.
|
||||
typedef struct {
|
||||
const char *name; ///< name of the memory pool
|
||||
uint32_t attr_bits; ///< attribute bits
|
||||
void *cb_mem; ///< memory for control block
|
||||
uint32_t cb_size; ///< size of provided memory for control block
|
||||
void *mp_mem; ///< memory for data storage
|
||||
uint32_t mp_size; ///< size of provided memory for data storage
|
||||
} osMemoryPoolAttr_t;
|
||||
|
||||
/// Attributes structure for message queue.
|
||||
typedef struct {
|
||||
const char *name; ///< name of the message queue
|
||||
@ -352,127 +181,10 @@ uint32_t osKernelGetTickCount (void);
|
||||
/// \return frequency of the kernel tick in hertz, i.e. kernel ticks per second.
|
||||
uint32_t osKernelGetTickFreq (void);
|
||||
|
||||
/// Get the RTOS kernel system timer count.
|
||||
/// \return RTOS kernel current system timer count as 32-bit value.
|
||||
uint32_t osKernelGetSysTimerCount (void);
|
||||
|
||||
/// Get the RTOS kernel system timer frequency.
|
||||
/// \return frequency of the system timer in hertz, i.e. timer ticks per second.
|
||||
uint32_t osKernelGetSysTimerFreq (void);
|
||||
|
||||
|
||||
// ==== Thread Management Functions ====
|
||||
|
||||
/// Create a thread and add it to Active Threads.
|
||||
/// \param[in] func thread function.
|
||||
/// \param[in] argument pointer that is passed to the thread function as start argument.
|
||||
/// \param[in] attr thread attributes; NULL: default values.
|
||||
/// \return thread ID for reference by other functions or NULL in case of error.
|
||||
osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr);
|
||||
|
||||
/// Get name of a thread.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
|
||||
/// \return name as null-terminated string.
|
||||
const char *osThreadGetName (osThreadId_t thread_id);
|
||||
|
||||
/// Return the thread ID of the current running thread.
|
||||
/// \return thread ID for reference by other functions or NULL in case of error.
|
||||
osThreadId_t osThreadGetId (void);
|
||||
|
||||
/// Get current thread state of a thread.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
|
||||
/// \return current thread state of the specified thread.
|
||||
osThreadState_t osThreadGetState (osThreadId_t thread_id);
|
||||
|
||||
/// Get stack size of a thread.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
|
||||
/// \return stack size in bytes.
|
||||
uint32_t osThreadGetStackSize (osThreadId_t thread_id);
|
||||
|
||||
/// Get available stack space of a thread based on stack watermark recording during execution.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
|
||||
/// \return remaining stack space in bytes.
|
||||
uint32_t osThreadGetStackSpace (osThreadId_t thread_id);
|
||||
|
||||
/// Change priority of a thread.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
|
||||
/// \param[in] priority new priority value for the thread function.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority);
|
||||
|
||||
/// Get current priority of a thread.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
|
||||
/// \return current priority value of the specified thread.
|
||||
osPriority_t osThreadGetPriority (osThreadId_t thread_id);
|
||||
|
||||
/// Pass control to next thread that is in state \b READY.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osThreadYield (void);
|
||||
|
||||
/// Suspend execution of a thread.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osThreadSuspend (osThreadId_t thread_id);
|
||||
|
||||
/// Resume execution of a thread.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osThreadResume (osThreadId_t thread_id);
|
||||
|
||||
/// Detach a thread (thread storage can be reclaimed when thread terminates).
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osThreadDetach (osThreadId_t thread_id);
|
||||
|
||||
/// Wait for specified thread to terminate.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osThreadJoin (osThreadId_t thread_id);
|
||||
|
||||
/// Terminate execution of current running thread.
|
||||
__NO_RETURN void osThreadExit (void);
|
||||
|
||||
/// Terminate execution of a thread.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osThreadTerminate (osThreadId_t thread_id);
|
||||
|
||||
/// Get number of active threads.
|
||||
/// \return number of active threads.
|
||||
uint32_t osThreadGetCount (void);
|
||||
|
||||
/// Enumerate active threads.
|
||||
/// \param[out] thread_array pointer to array for retrieving thread IDs.
|
||||
/// \param[in] array_items maximum number of items in array for retrieving thread IDs.
|
||||
/// \return number of enumerated threads.
|
||||
uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items);
|
||||
|
||||
|
||||
// ==== Thread Flags Functions ====
|
||||
|
||||
/// Set the specified Thread Flags of a thread.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
|
||||
/// \param[in] flags specifies the flags of the thread that shall be set.
|
||||
/// \return thread flags after setting or error code if highest bit set.
|
||||
uint32_t osThreadFlagsSet (osThreadId_t thread_id, uint32_t flags);
|
||||
|
||||
/// Clear the specified Thread Flags of current running thread.
|
||||
/// \param[in] flags specifies the flags of the thread that shall be cleared.
|
||||
/// \return thread flags before clearing or error code if highest bit set.
|
||||
uint32_t osThreadFlagsClear (uint32_t flags);
|
||||
|
||||
/// Get the current Thread Flags of current running thread.
|
||||
/// \return current thread flags.
|
||||
uint32_t osThreadFlagsGet (void);
|
||||
|
||||
/// Wait for one or more Thread Flags of the current running thread to become signaled.
|
||||
/// \param[in] flags specifies the flags to wait for.
|
||||
/// \param[in] options specifies flags options (osFlagsXxxx).
|
||||
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
|
||||
/// \return thread flags before clearing or error code if highest bit set.
|
||||
uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout);
|
||||
|
||||
|
||||
// ==== Generic Wait Functions ====
|
||||
|
||||
/// Wait for Timeout (Time Delay).
|
||||
@ -522,172 +234,6 @@ uint32_t osTimerIsRunning (osTimerId_t timer_id);
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osTimerDelete (osTimerId_t timer_id);
|
||||
|
||||
|
||||
// ==== Event Flags Management Functions ====
|
||||
|
||||
/// Create and Initialize an Event Flags object.
|
||||
/// \param[in] attr event flags attributes; NULL: default values.
|
||||
/// \return event flags ID for reference by other functions or NULL in case of error.
|
||||
osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr);
|
||||
|
||||
/// Get name of an Event Flags object.
|
||||
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
|
||||
/// \return name as null-terminated string.
|
||||
const char *osEventFlagsGetName (osEventFlagsId_t ef_id);
|
||||
|
||||
/// Set the specified Event Flags.
|
||||
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
|
||||
/// \param[in] flags specifies the flags that shall be set.
|
||||
/// \return event flags after setting or error code if highest bit set.
|
||||
uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags);
|
||||
|
||||
/// Clear the specified Event Flags.
|
||||
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
|
||||
/// \param[in] flags specifies the flags that shall be cleared.
|
||||
/// \return event flags before clearing or error code if highest bit set.
|
||||
uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags);
|
||||
|
||||
/// Get the current Event Flags.
|
||||
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
|
||||
/// \return current event flags.
|
||||
uint32_t osEventFlagsGet (osEventFlagsId_t ef_id);
|
||||
|
||||
/// Wait for one or more Event Flags to become signaled.
|
||||
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
|
||||
/// \param[in] flags specifies the flags to wait for.
|
||||
/// \param[in] options specifies flags options (osFlagsXxxx).
|
||||
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
|
||||
/// \return event flags before clearing or error code if highest bit set.
|
||||
uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout);
|
||||
|
||||
/// Delete an Event Flags object.
|
||||
/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id);
|
||||
|
||||
|
||||
// ==== Mutex Management Functions ====
|
||||
|
||||
/// Create and Initialize a Mutex object.
|
||||
/// \param[in] attr mutex attributes; NULL: default values.
|
||||
/// \return mutex ID for reference by other functions or NULL in case of error.
|
||||
osMutexId_t osMutexNew (const osMutexAttr_t *attr);
|
||||
|
||||
/// Get name of a Mutex object.
|
||||
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
|
||||
/// \return name as null-terminated string.
|
||||
const char *osMutexGetName (osMutexId_t mutex_id);
|
||||
|
||||
/// Acquire a Mutex or timeout if it is locked.
|
||||
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
|
||||
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout);
|
||||
|
||||
/// Release a Mutex that was acquired by \ref osMutexAcquire.
|
||||
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osMutexRelease (osMutexId_t mutex_id);
|
||||
|
||||
/// Get Thread which owns a Mutex object.
|
||||
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
|
||||
/// \return thread ID of owner thread or NULL when mutex was not acquired.
|
||||
osThreadId_t osMutexGetOwner (osMutexId_t mutex_id);
|
||||
|
||||
/// Delete a Mutex object.
|
||||
/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osMutexDelete (osMutexId_t mutex_id);
|
||||
|
||||
|
||||
// ==== Semaphore Management Functions ====
|
||||
|
||||
/// Create and Initialize a Semaphore object.
|
||||
/// \param[in] max_count maximum number of available tokens.
|
||||
/// \param[in] initial_count initial number of available tokens.
|
||||
/// \param[in] attr semaphore attributes; NULL: default values.
|
||||
/// \return semaphore ID for reference by other functions or NULL in case of error.
|
||||
osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr);
|
||||
|
||||
/// Get name of a Semaphore object.
|
||||
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
|
||||
/// \return name as null-terminated string.
|
||||
const char *osSemaphoreGetName (osSemaphoreId_t semaphore_id);
|
||||
|
||||
/// Acquire a Semaphore token or timeout if no tokens are available.
|
||||
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
|
||||
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout);
|
||||
|
||||
/// Release a Semaphore token up to the initial maximum count.
|
||||
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id);
|
||||
|
||||
/// Get current Semaphore token count.
|
||||
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
|
||||
/// \return number of tokens available.
|
||||
uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id);
|
||||
|
||||
/// Delete a Semaphore object.
|
||||
/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id);
|
||||
|
||||
|
||||
// ==== Memory Pool Management Functions ====
|
||||
|
||||
/// Create and Initialize a Memory Pool object.
|
||||
/// \param[in] block_count maximum number of memory blocks in memory pool.
|
||||
/// \param[in] block_size memory block size in bytes.
|
||||
/// \param[in] attr memory pool attributes; NULL: default values.
|
||||
/// \return memory pool ID for reference by other functions or NULL in case of error.
|
||||
osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr);
|
||||
|
||||
/// Get name of a Memory Pool object.
|
||||
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
|
||||
/// \return name as null-terminated string.
|
||||
const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id);
|
||||
|
||||
/// Allocate a memory block from a Memory Pool.
|
||||
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
|
||||
/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
|
||||
/// \return address of the allocated memory block or NULL in case of no memory is available.
|
||||
void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout);
|
||||
|
||||
/// Return an allocated memory block back to a Memory Pool.
|
||||
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
|
||||
/// \param[in] block address of the allocated memory block to be returned to the memory pool.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block);
|
||||
|
||||
/// Get maximum number of memory blocks in a Memory Pool.
|
||||
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
|
||||
/// \return maximum number of memory blocks.
|
||||
uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id);
|
||||
|
||||
/// Get memory block size in a Memory Pool.
|
||||
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
|
||||
/// \return memory block size in bytes.
|
||||
uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id);
|
||||
|
||||
/// Get number of memory blocks used in a Memory Pool.
|
||||
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
|
||||
/// \return number of memory blocks used.
|
||||
uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id);
|
||||
|
||||
/// Get number of memory blocks available in a Memory Pool.
|
||||
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
|
||||
/// \return number of memory blocks available.
|
||||
uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id);
|
||||
|
||||
/// Delete a Memory Pool object.
|
||||
/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id);
|
||||
|
||||
|
||||
// ==== Message Queue Management Functions ====
|
||||
|
||||
/// Create and Initialize a Message Queue object.
|
||||
|
@ -1,63 +0,0 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
* Copyright (c) 2013-2020 Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Name: freertos_mpool.h
|
||||
* Purpose: CMSIS RTOS2 wrapper for FreeRTOS
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef FREERTOS_MPOOL_H_
|
||||
#define FREERTOS_MPOOL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* Memory Pool implementation definitions */
|
||||
#define MPOOL_STATUS 0x5EED0000U
|
||||
|
||||
/* Memory Block header */
|
||||
typedef struct {
|
||||
void *next; /* Pointer to next block */
|
||||
} MemPoolBlock_t;
|
||||
|
||||
/* Memory Pool control block */
|
||||
typedef struct MemPoolDef_t {
|
||||
MemPoolBlock_t *head; /* Pointer to head block */
|
||||
SemaphoreHandle_t sem; /* Pool semaphore handle */
|
||||
uint8_t *mem_arr; /* Pool memory array */
|
||||
uint32_t mem_sz; /* Pool memory array size */
|
||||
const char *name; /* Pointer to name string */
|
||||
uint32_t bl_sz; /* Size of a single block */
|
||||
uint32_t bl_cnt; /* Number of blocks */
|
||||
uint32_t n; /* Block allocation index */
|
||||
volatile uint32_t status; /* Object status flags */
|
||||
#if (configSUPPORT_STATIC_ALLOCATION == 1)
|
||||
StaticSemaphore_t mem_sem; /* Semaphore object memory */
|
||||
#endif
|
||||
} MemPool_t;
|
||||
|
||||
/* No need to hide static object type, just align to coding style */
|
||||
#define StaticMemPool_t MemPool_t
|
||||
|
||||
/* Define memory pool control block size */
|
||||
#define MEMPOOL_CB_SIZE (sizeof(StaticMemPool_t))
|
||||
|
||||
/* Define size of the byte array required to create count of blocks of given size */
|
||||
#define MEMPOOL_ARR_SIZE(bl_count, bl_size) (((((bl_size) + (4 - 1)) / 4) * 4)*(bl_count))
|
||||
|
||||
#endif /* FREERTOS_MPOOL_H_ */
|
@ -75,7 +75,7 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
Option to exclude CMSIS-RTOS2 function osThreadEnumerate from the application image.
|
||||
Option to exclude CMSIS-RTOS2 function furi_thread_enumerate from the application image.
|
||||
*/
|
||||
#ifndef configUSE_OS2_THREAD_ENUMERATE
|
||||
#define configUSE_OS2_THREAD_ENUMERATE 1
|
||||
@ -153,7 +153,7 @@
|
||||
#if (INCLUDE_xTaskGetCurrentTaskHandle == 0)
|
||||
/*
|
||||
CMSIS-RTOS2 API uses FreeRTOS function xTaskGetCurrentTaskHandle to implement
|
||||
functions osThreadGetId, osThreadFlagsClear and osThreadFlagsGet. In case if these
|
||||
functions osThreadGetId, furi_thread_flags_clear and furi_thread_flags_get. In case if these
|
||||
functions are not used in the application image, compiler will optimize them away.
|
||||
Set #define INCLUDE_xTaskGetCurrentTaskHandle 1 to fix this error.
|
||||
*/
|
||||
@ -170,8 +170,8 @@
|
||||
#endif
|
||||
#if (INCLUDE_uxTaskGetStackHighWaterMark == 0)
|
||||
/*
|
||||
CMSIS-RTOS2 function osThreadGetStackSpace uses FreeRTOS function uxTaskGetStackHighWaterMark.
|
||||
In case if osThreadGetStackSpace is not used in the application image, compiler will
|
||||
CMSIS-RTOS2 function furi_thread_get_stack_space uses FreeRTOS function uxTaskGetStackHighWaterMark.
|
||||
In case if furi_thread_get_stack_space is not used in the application image, compiler will
|
||||
optimize it away.
|
||||
Set #define INCLUDE_uxTaskGetStackHighWaterMark 1 to fix this error.
|
||||
*/
|
||||
@ -294,16 +294,16 @@
|
||||
|
||||
#if (configUSE_TRACE_FACILITY == 0)
|
||||
/*
|
||||
CMSIS-RTOS2 function osThreadEnumerate requires FreeRTOS function uxTaskGetSystemState
|
||||
CMSIS-RTOS2 function furi_thread_enumerate requires FreeRTOS function uxTaskGetSystemState
|
||||
which is only enabled if configUSE_TRACE_FACILITY == 1.
|
||||
Set #define configUSE_TRACE_FACILITY 1 to fix this error.
|
||||
|
||||
Alternatively, if the application does not use osThreadEnumerate it can be
|
||||
Alternatively, if the application does not use furi_thread_enumerate it can be
|
||||
excluded from the image code by setting:
|
||||
#define configUSE_OS2_THREAD_ENUMERATE 0 (in FreeRTOSConfig.h)
|
||||
*/
|
||||
#if (configUSE_OS2_THREAD_ENUMERATE == 1)
|
||||
#error "Definition configUSE_TRACE_FACILITY must equal 1 to implement osThreadEnumerate."
|
||||
#error "Definition configUSE_TRACE_FACILITY must equal 1 to implement furi_thread_enumerate."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -316,21 +316,4 @@
|
||||
#error "Definition configUSE_16_BIT_TICKS must be zero to implement CMSIS-RTOS2 API."
|
||||
#endif
|
||||
|
||||
#if (configMAX_PRIORITIES != 56)
|
||||
/*
|
||||
CMSIS-RTOS2 defines 56 different priorities (see osPriority_t) and portable CMSIS-RTOS2
|
||||
implementation should implement the same number of priorities.
|
||||
Set #define configMAX_PRIORITIES 56 to fix this error.
|
||||
*/
|
||||
#error "Definition configMAX_PRIORITIES must equal 56 to implement Thread Management API."
|
||||
#endif
|
||||
#if (configUSE_PORT_OPTIMISED_TASK_SELECTION != 0)
|
||||
/*
|
||||
CMSIS-RTOS2 requires handling of 56 different priorities (see osPriority_t) while FreeRTOS port
|
||||
optimised selection for Cortex core only handles 32 different priorities.
|
||||
Set #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 to fix this error.
|
||||
*/
|
||||
#error "Definition configUSE_PORT_OPTIMISED_TASK_SELECTION must be zero to implement Thread Management API."
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_OS2_H_ */
|
||||
|
@ -1,80 +0,0 @@
|
||||
/**************************************************************************//**
|
||||
* @file os_tick.h
|
||||
* @brief CMSIS OS Tick header file
|
||||
* @version V1.0.2
|
||||
* @date 19. March 2021
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Copyright (c) 2017-2021 ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef OS_TICK_H
|
||||
#define OS_TICK_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/// IRQ Handler.
|
||||
#ifndef IRQHANDLER_T
|
||||
#define IRQHANDLER_T
|
||||
typedef void (*IRQHandler_t) (void);
|
||||
#endif
|
||||
|
||||
/// Setup OS Tick timer to generate periodic RTOS Kernel Ticks
|
||||
/// \param[in] freq tick frequency in Hz
|
||||
/// \param[in] handler tick IRQ handler
|
||||
/// \return 0 on success, -1 on error.
|
||||
int32_t OS_Tick_Setup (uint32_t freq, IRQHandler_t handler);
|
||||
|
||||
/// Enable OS Tick timer interrupt
|
||||
void OS_Tick_Enable (void);
|
||||
|
||||
/// Disable OS Tick timer interrupt
|
||||
void OS_Tick_Disable (void);
|
||||
|
||||
/// Acknowledge execution of OS Tick timer interrupt
|
||||
void OS_Tick_AcknowledgeIRQ (void);
|
||||
|
||||
/// Get OS Tick timer IRQ number
|
||||
/// \return OS Tick IRQ number
|
||||
int32_t OS_Tick_GetIRQn (void);
|
||||
|
||||
/// Get OS Tick timer clock frequency
|
||||
/// \return OS Tick timer clock frequency in Hz
|
||||
uint32_t OS_Tick_GetClock (void);
|
||||
|
||||
/// Get OS Tick timer interval reload value
|
||||
/// \return OS Tick timer interval reload value
|
||||
uint32_t OS_Tick_GetInterval (void);
|
||||
|
||||
/// Get OS Tick timer counter value
|
||||
/// \return OS Tick timer counter value
|
||||
uint32_t OS_Tick_GetCount (void);
|
||||
|
||||
/// Get OS Tick timer overflow status
|
||||
/// \return OS Tick overflow status (1 - overflow, 0 - no overflow).
|
||||
uint32_t OS_Tick_GetOverflow (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OS_TICK_H */
|
@ -3,49 +3,58 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal_spi.h>
|
||||
|
||||
static const osThreadAttr_t platform_irq_thread_attr = {
|
||||
.name = "RfalIrqDriver",
|
||||
.stack_size = 1024,
|
||||
.priority = osPriorityRealtime,
|
||||
};
|
||||
typedef struct {
|
||||
FuriThread* thread;
|
||||
volatile PlatformIrqCallback callback;
|
||||
} RfalPlatform;
|
||||
|
||||
static volatile osThreadId_t platform_irq_thread_id = NULL;
|
||||
static volatile PlatformIrqCallback platform_irq_callback = NULL;
|
||||
static const GpioPin pin = {ST25R_INT_PORT, ST25R_INT_PIN};
|
||||
static volatile RfalPlatform rfal_platform = {
|
||||
.thread = NULL,
|
||||
.callback = NULL,
|
||||
};
|
||||
|
||||
void nfc_isr(void* _ctx) {
|
||||
UNUSED(_ctx);
|
||||
if(platform_irq_callback && platformGpioIsHigh(ST25R_INT_PORT, ST25R_INT_PIN)) {
|
||||
osThreadFlagsSet(platform_irq_thread_id, 0x1);
|
||||
if(rfal_platform.callback && platformGpioIsHigh(ST25R_INT_PORT, ST25R_INT_PIN)) {
|
||||
furi_thread_flags_set(furi_thread_get_id(rfal_platform.thread), 0x1);
|
||||
}
|
||||
}
|
||||
|
||||
void platformIrqThread() {
|
||||
int32_t rfal_platform_irq_thread(void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
while(1) {
|
||||
uint32_t flags = osThreadFlagsWait(0x1, osFlagsWaitAny, osWaitForever);
|
||||
uint32_t flags = furi_thread_flags_wait(0x1, osFlagsWaitAny, osWaitForever);
|
||||
if(flags & 0x1) {
|
||||
platform_irq_callback();
|
||||
rfal_platform.callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void platformEnableIrqCallback() {
|
||||
furi_hal_gpio_init(&pin, GpioModeInterruptRise, GpioPullDown, GpioSpeedLow);
|
||||
furi_hal_gpio_enable_int_callback(&pin);
|
||||
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInterruptRise, GpioPullDown, GpioSpeedLow);
|
||||
furi_hal_gpio_enable_int_callback(&gpio_nfc_irq_rfid_pull);
|
||||
}
|
||||
|
||||
void platformDisableIrqCallback() {
|
||||
furi_hal_gpio_init(&pin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_disable_int_callback(&pin);
|
||||
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_disable_int_callback(&gpio_nfc_irq_rfid_pull);
|
||||
}
|
||||
|
||||
void platformSetIrqCallback(PlatformIrqCallback callback) {
|
||||
platform_irq_callback = callback;
|
||||
platform_irq_thread_id = osThreadNew(platformIrqThread, NULL, &platform_irq_thread_attr);
|
||||
furi_hal_gpio_add_int_callback(&pin, nfc_isr, NULL);
|
||||
rfal_platform.callback = callback;
|
||||
rfal_platform.thread = furi_thread_alloc();
|
||||
|
||||
furi_thread_set_name(rfal_platform.thread, "RfalIrqDriver");
|
||||
furi_thread_set_callback(rfal_platform.thread, rfal_platform_irq_thread);
|
||||
furi_thread_set_stack_size(rfal_platform.thread, 1024);
|
||||
furi_thread_set_priority(rfal_platform.thread, FuriThreadPriorityIsr);
|
||||
furi_thread_start(rfal_platform.thread);
|
||||
|
||||
furi_hal_gpio_add_int_callback(&gpio_nfc_irq_rfid_pull, nfc_isr, NULL);
|
||||
// Disable interrupt callback as the pin is shared between 2 apps
|
||||
// It is enabled in rfalLowPowerModeStop()
|
||||
furi_hal_gpio_disable_int_callback(&pin);
|
||||
furi_hal_gpio_disable_int_callback(&gpio_nfc_irq_rfid_pull);
|
||||
}
|
||||
|
||||
bool platformSpiTxRx(const uint8_t* txBuf, uint8_t* rxBuf, uint16_t len) {
|
||||
|
@ -92,8 +92,8 @@ static void infrared_worker_furi_hal_message_sent_isr_callback(void* context);
|
||||
|
||||
static void infrared_worker_rx_timeout_callback(void* context) {
|
||||
InfraredWorker* instance = context;
|
||||
uint32_t flags_set = osThreadFlagsSet(
|
||||
furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_RX_TIMEOUT_RECEIVED);
|
||||
uint32_t flags_set = furi_thread_flags_set(
|
||||
furi_thread_get_id(instance->thread), INFRARED_WORKER_RX_TIMEOUT_RECEIVED);
|
||||
furi_check(flags_set & INFRARED_WORKER_RX_TIMEOUT_RECEIVED);
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ static void infrared_worker_rx_callback(void* context, bool level, uint32_t dura
|
||||
INFRARED_WORKER_OVERRUN;
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
|
||||
uint32_t flags_set = osThreadFlagsSet(furi_thread_get_thread_id(instance->thread), events);
|
||||
uint32_t flags_set = furi_thread_flags_set(furi_thread_get_id(instance->thread), events);
|
||||
furi_check(flags_set & events);
|
||||
}
|
||||
|
||||
@ -152,8 +152,8 @@ static void
|
||||
instance->signal.timings[instance->signal.timings_cnt] = duration;
|
||||
++instance->signal.timings_cnt;
|
||||
} else {
|
||||
uint32_t flags_set = osThreadFlagsSet(
|
||||
furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_OVERRUN);
|
||||
uint32_t flags_set = furi_thread_flags_set(
|
||||
furi_thread_get_id(instance->thread), INFRARED_WORKER_OVERRUN);
|
||||
furi_check(flags_set & INFRARED_WORKER_OVERRUN);
|
||||
instance->rx.overrun = true;
|
||||
}
|
||||
@ -167,7 +167,7 @@ static int32_t infrared_worker_rx_thread(void* thread_context) {
|
||||
TickType_t last_blink_time = 0;
|
||||
|
||||
while(1) {
|
||||
events = osThreadFlagsWait(INFRARED_WORKER_ALL_RX_EVENTS, 0, osWaitForever);
|
||||
events = furi_thread_flags_wait(INFRARED_WORKER_ALL_RX_EVENTS, 0, osWaitForever);
|
||||
furi_check(events & INFRARED_WORKER_ALL_RX_EVENTS); /* at least one caught */
|
||||
|
||||
if(events & INFRARED_WORKER_RX_RECEIVED) {
|
||||
@ -282,7 +282,7 @@ void infrared_worker_rx_stop(InfraredWorker* instance) {
|
||||
furi_hal_infrared_async_rx_set_capture_isr_callback(NULL, NULL);
|
||||
furi_hal_infrared_async_rx_stop();
|
||||
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_EXIT);
|
||||
furi_thread_flags_set(furi_thread_get_id(instance->thread), INFRARED_WORKER_EXIT);
|
||||
furi_thread_join(instance->thread);
|
||||
|
||||
BaseType_t xReturn = xStreamBufferReset(instance->stream);
|
||||
@ -342,8 +342,8 @@ void infrared_worker_tx_start(InfraredWorker* instance) {
|
||||
|
||||
static void infrared_worker_furi_hal_message_sent_isr_callback(void* context) {
|
||||
InfraredWorker* instance = context;
|
||||
uint32_t flags_set = osThreadFlagsSet(
|
||||
furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_TX_MESSAGE_SENT);
|
||||
uint32_t flags_set = furi_thread_flags_set(
|
||||
furi_thread_get_id(instance->thread), INFRARED_WORKER_TX_MESSAGE_SENT);
|
||||
furi_check(flags_set & INFRARED_WORKER_TX_MESSAGE_SENT);
|
||||
}
|
||||
|
||||
@ -369,8 +369,8 @@ static FuriHalInfraredTxGetDataState
|
||||
state = FuriHalInfraredTxGetDataStateDone;
|
||||
}
|
||||
|
||||
uint32_t flags_set = osThreadFlagsSet(
|
||||
furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_TX_FILL_BUFFER);
|
||||
uint32_t flags_set = furi_thread_flags_set(
|
||||
furi_thread_get_id(instance->thread), INFRARED_WORKER_TX_FILL_BUFFER);
|
||||
furi_check(flags_set & INFRARED_WORKER_TX_FILL_BUFFER);
|
||||
|
||||
return state;
|
||||
@ -498,7 +498,7 @@ static int32_t infrared_worker_tx_thread(void* thread_context) {
|
||||
furi_hal_infrared_async_tx_wait_termination();
|
||||
instance->state = InfraredWorkerStateStartTx;
|
||||
|
||||
events = osThreadFlagsGet();
|
||||
events = furi_thread_flags_get();
|
||||
if(events & INFRARED_WORKER_EXIT) {
|
||||
exit = true;
|
||||
break;
|
||||
@ -506,7 +506,7 @@ static int32_t infrared_worker_tx_thread(void* thread_context) {
|
||||
|
||||
break;
|
||||
case InfraredWorkerStateRunTx:
|
||||
events = osThreadFlagsWait(INFRARED_WORKER_ALL_TX_EVENTS, 0, osWaitForever);
|
||||
events = furi_thread_flags_wait(INFRARED_WORKER_ALL_TX_EVENTS, 0, osWaitForever);
|
||||
furi_check(events & INFRARED_WORKER_ALL_TX_EVENTS); /* at least one caught */
|
||||
|
||||
if(events & INFRARED_WORKER_EXIT) {
|
||||
@ -558,7 +558,7 @@ void infrared_worker_tx_stop(InfraredWorker* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->state != InfraredWorkerStateRunRx);
|
||||
|
||||
osThreadFlagsSet(furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_EXIT);
|
||||
furi_thread_flags_set(furi_thread_get_id(instance->thread), INFRARED_WORKER_EXIT);
|
||||
furi_thread_join(instance->thread);
|
||||
furi_hal_infrared_async_tx_set_data_isr_callback(NULL, NULL);
|
||||
furi_hal_infrared_async_tx_set_signal_sent_isr_callback(NULL, NULL);
|
||||
|
@ -216,8 +216,9 @@ bool subghz_file_encoder_worker_start(SubGhzFileEncoderWorker* instance, const c
|
||||
xStreamBufferReset(instance->stream);
|
||||
string_set(instance->file_path, file_path);
|
||||
instance->worker_running = true;
|
||||
bool res = furi_thread_start(instance->thread);
|
||||
return res;
|
||||
furi_thread_start(instance->thread);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_file_encoder_worker_stop(SubGhzFileEncoderWorker* instance) {
|
||||
|
Loading…
Reference in New Issue
Block a user