[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;
|
BadUsbScript* bad_usb = context;
|
||||||
|
|
||||||
if(state == true)
|
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
|
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) {
|
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;
|
bad_usb->st.state = worker_state;
|
||||||
|
|
||||||
} else if(worker_state == BadUsbStateNotConnected) { // State: USB not connected
|
} else if(worker_state == BadUsbStateNotConnected) { // State: USB not connected
|
||||||
uint32_t flags =
|
uint32_t flags = furi_thread_flags_wait(
|
||||||
osThreadFlagsWait(WorkerEvtEnd | WorkerEvtConnect, osFlagsWaitAny, osWaitForever);
|
WorkerEvtEnd | WorkerEvtConnect, osFlagsWaitAny, osWaitForever);
|
||||||
furi_check((flags & osFlagsError) == 0);
|
furi_check((flags & osFlagsError) == 0);
|
||||||
if(flags & WorkerEvtEnd) {
|
if(flags & WorkerEvtEnd) {
|
||||||
break;
|
break;
|
||||||
@ -494,7 +494,7 @@ static int32_t bad_usb_worker(void* context) {
|
|||||||
bad_usb->st.state = worker_state;
|
bad_usb->st.state = worker_state;
|
||||||
|
|
||||||
} else if(worker_state == BadUsbStateIdle) { // State: ready to start
|
} else if(worker_state == BadUsbStateIdle) { // State: ready to start
|
||||||
uint32_t flags = osThreadFlagsWait(
|
uint32_t flags = furi_thread_flags_wait(
|
||||||
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect,
|
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect,
|
||||||
osFlagsWaitAny,
|
osFlagsWaitAny,
|
||||||
osWaitForever);
|
osWaitForever);
|
||||||
@ -518,7 +518,7 @@ static int32_t bad_usb_worker(void* context) {
|
|||||||
|
|
||||||
} else if(worker_state == BadUsbStateRunning) { // State: running
|
} else if(worker_state == BadUsbStateRunning) { // State: running
|
||||||
uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val);
|
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);
|
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, osFlagsWaitAny, delay_cur);
|
||||||
delay_val -= delay_cur;
|
delay_val -= delay_cur;
|
||||||
if(!(flags & osFlagsError)) {
|
if(!(flags & osFlagsError)) {
|
||||||
@ -561,7 +561,7 @@ static int32_t bad_usb_worker(void* context) {
|
|||||||
} else if(
|
} else if(
|
||||||
(worker_state == BadUsbStateFileError) ||
|
(worker_state == BadUsbStateFileError) ||
|
||||||
(worker_state == BadUsbStateScriptError)) { // State: error
|
(worker_state == BadUsbStateScriptError)) { // State: error
|
||||||
uint32_t flags = osThreadFlagsWait(
|
uint32_t flags = furi_thread_flags_wait(
|
||||||
WorkerEvtEnd, osFlagsWaitAny, osWaitForever); // Waiting for exit command
|
WorkerEvtEnd, osFlagsWaitAny, osWaitForever); // Waiting for exit command
|
||||||
furi_check((flags & osFlagsError) == 0);
|
furi_check((flags & osFlagsError) == 0);
|
||||||
if(flags & WorkerEvtEnd) {
|
if(flags & WorkerEvtEnd) {
|
||||||
@ -605,7 +605,7 @@ BadUsbScript* bad_usb_script_open(string_t file_path) {
|
|||||||
|
|
||||||
void bad_usb_script_close(BadUsbScript* bad_usb) {
|
void bad_usb_script_close(BadUsbScript* bad_usb) {
|
||||||
furi_assert(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_join(bad_usb->thread);
|
||||||
furi_thread_free(bad_usb->thread);
|
furi_thread_free(bad_usb->thread);
|
||||||
string_clear(bad_usb->file_path);
|
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) {
|
void bad_usb_script_toggle(BadUsbScript* bad_usb) {
|
||||||
furi_assert(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) {
|
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);
|
UNUSED(context);
|
||||||
|
|
||||||
const uint8_t threads_num_max = 32;
|
const uint8_t threads_num_max = 32;
|
||||||
osThreadId_t threads_id[threads_num_max];
|
FuriThreadId threads_ids[threads_num_max];
|
||||||
uint8_t thread_num = osThreadEnumerate(threads_id, threads_num_max);
|
uint8_t thread_num = furi_thread_enumerate(threads_ids, threads_num_max);
|
||||||
printf(
|
printf(
|
||||||
"%-20s %-14s %-8s %-8s %s\r\n", "Name", "Stack start", "Heap", "Stack", "Stack min free");
|
"%-20s %-14s %-8s %-8s %s\r\n", "Name", "Stack start", "Heap", "Stack", "Stack min free");
|
||||||
for(uint8_t i = 0; i < thread_num; i++) {
|
for(uint8_t i = 0; i < thread_num; i++) {
|
||||||
TaskControlBlock* tcb = (TaskControlBlock*)threads_id[i];
|
TaskControlBlock* tcb = (TaskControlBlock*)threads_ids[i];
|
||||||
printf(
|
printf(
|
||||||
"%-20s 0x%-12lx %-8d %-8ld %-8ld\r\n",
|
"%-20s 0x%-12lx %-8d %-8ld %-8ld\r\n",
|
||||||
osThreadGetName(threads_id[i]),
|
furi_thread_get_name(threads_ids[i]),
|
||||||
(uint32_t)tcb->pxStack,
|
(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),
|
(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);
|
printf("\r\nTotal: %d", thread_num);
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ static void cli_vcp_init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void cli_vcp_deinit() {
|
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_join(vcp->thread);
|
||||||
furi_thread_free(vcp->thread);
|
furi_thread_free(vcp->thread);
|
||||||
vcp->thread = NULL;
|
vcp->thread = NULL;
|
||||||
@ -102,7 +102,8 @@ static int32_t vcp_worker(void* context) {
|
|||||||
vcp->running = true;
|
vcp->running = true;
|
||||||
|
|
||||||
while(1) {
|
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);
|
furi_assert((flags & osFlagsError) == 0);
|
||||||
|
|
||||||
// VCP session opened
|
// 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);
|
FURI_LOG_D(TAG, "rx %u ", batch_size);
|
||||||
#endif
|
#endif
|
||||||
if(len == 0) break;
|
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;
|
size -= len;
|
||||||
buffer += len;
|
buffer += len;
|
||||||
rx_cnt += 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;
|
if(batch_size > USB_CDC_PKT_LEN) batch_size = USB_CDC_PKT_LEN;
|
||||||
|
|
||||||
xStreamBufferSend(vcp->tx_stream, buffer, batch_size, osWaitForever);
|
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
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "tx %u", batch_size);
|
FURI_LOG_D(TAG, "tx %u", batch_size);
|
||||||
#endif
|
#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) {
|
static void vcp_state_callback(void* context, uint8_t state) {
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
if(state == 0) {
|
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);
|
bool dtr = state & (1 << 0);
|
||||||
|
|
||||||
if(dtr == true) {
|
if(dtr == true) {
|
||||||
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtConnect);
|
furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtConnect);
|
||||||
} else {
|
} 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) {
|
static void vcp_on_cdc_rx(void* context) {
|
||||||
UNUSED(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);
|
furi_check((ret & osFlagsError) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vcp_on_cdc_tx_complete(void* context) {
|
static void vcp_on_cdc_tx_complete(void* context) {
|
||||||
UNUSED(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) {
|
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) {
|
if(ev == UartIrqEventRXNE) {
|
||||||
xStreamBufferSendFromISR(app->rx_stream, &data, 1, &xHigherPriorityTaskWoken);
|
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);
|
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,7 +149,8 @@ static int32_t uart_echo_worker(void* context) {
|
|||||||
UartEchoApp* app = context;
|
UartEchoApp* app = context;
|
||||||
|
|
||||||
while(1) {
|
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);
|
furi_check((events & osFlagsError) == 0);
|
||||||
|
|
||||||
if(events & WorkerEventStop) break;
|
if(events & WorkerEventStop) break;
|
||||||
@ -234,7 +235,7 @@ static UartEchoApp* uart_echo_app_alloc() {
|
|||||||
static void uart_echo_app_free(UartEchoApp* app) {
|
static void uart_echo_app_free(UartEchoApp* app) {
|
||||||
furi_assert(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_join(app->worker_thread);
|
||||||
furi_thread_free(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) {
|
if(ev == UartIrqEventRXNE) {
|
||||||
xStreamBufferSendFromISR(usb_uart->rx_stream, &data, 1, &xHigherPriorityTaskWoken);
|
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);
|
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,12 +181,13 @@ static int32_t usb_uart_worker(void* context) {
|
|||||||
usb_uart_update_ctrl_lines(usb_uart);
|
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);
|
furi_thread_start(usb_uart->tx_thread);
|
||||||
|
|
||||||
while(1) {
|
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);
|
furi_check((events & osFlagsError) == 0);
|
||||||
if(events & WorkerEvtStop) break;
|
if(events & WorkerEvtStop) break;
|
||||||
if(events & WorkerEvtRxDone) {
|
if(events & WorkerEvtRxDone) {
|
||||||
@ -205,7 +206,7 @@ static int32_t usb_uart_worker(void* context) {
|
|||||||
}
|
}
|
||||||
if(events & WorkerEvtCfgChange) {
|
if(events & WorkerEvtCfgChange) {
|
||||||
if(usb_uart->cfg.vcp_ch != usb_uart->cfg_new.vcp_ch) {
|
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);
|
furi_thread_join(usb_uart->tx_thread);
|
||||||
|
|
||||||
usb_uart_vcp_deinit(usb_uart, usb_uart->cfg.vcp_ch);
|
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;
|
events |= WorkerEvtLineCfgSet;
|
||||||
}
|
}
|
||||||
if(usb_uart->cfg.uart_ch != usb_uart->cfg_new.uart_ch) {
|
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);
|
furi_thread_join(usb_uart->tx_thread);
|
||||||
|
|
||||||
usb_uart_serial_deinit(usb_uart, usb_uart->cfg.uart_ch);
|
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);
|
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_join(usb_uart->tx_thread);
|
||||||
furi_thread_free(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];
|
uint8_t data[USB_CDC_PKT_LEN];
|
||||||
while(1) {
|
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);
|
furi_check((events & osFlagsError) == 0);
|
||||||
if(events & WorkerEvtTxStop) break;
|
if(events & WorkerEvtTxStop) break;
|
||||||
if(events & WorkerEvtCdcRx) {
|
if(events & WorkerEvtCdcRx) {
|
||||||
@ -314,7 +316,7 @@ static void vcp_on_cdc_tx_complete(void* context) {
|
|||||||
|
|
||||||
static void vcp_on_cdc_rx(void* context) {
|
static void vcp_on_cdc_rx(void* context) {
|
||||||
UsbUartBridge* usb_uart = (UsbUartBridge*)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) {
|
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) {
|
static void vcp_on_cdc_control_line(void* context, uint8_t state) {
|
||||||
UNUSED(state);
|
UNUSED(state);
|
||||||
UsbUartBridge* usb_uart = (UsbUartBridge*)context;
|
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) {
|
static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) {
|
||||||
UNUSED(config);
|
UNUSED(config);
|
||||||
UsbUartBridge* usb_uart = (UsbUartBridge*)context;
|
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) {
|
UsbUartBridge* usb_uart_enable(UsbUartConfig* cfg) {
|
||||||
@ -351,7 +353,7 @@ UsbUartBridge* usb_uart_enable(UsbUartConfig* cfg) {
|
|||||||
|
|
||||||
void usb_uart_disable(UsbUartBridge* usb_uart) {
|
void usb_uart_disable(UsbUartBridge* usb_uart) {
|
||||||
furi_assert(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_join(usb_uart->thread);
|
||||||
furi_thread_free(usb_uart->thread);
|
furi_thread_free(usb_uart->thread);
|
||||||
free(usb_uart);
|
free(usb_uart);
|
||||||
@ -361,7 +363,7 @@ void usb_uart_set_config(UsbUartBridge* usb_uart, UsbUartConfig* cfg) {
|
|||||||
furi_assert(usb_uart);
|
furi_assert(usb_uart);
|
||||||
furi_assert(cfg);
|
furi_assert(cfg);
|
||||||
memcpy(&(usb_uart->cfg_new), cfg, sizeof(UsbUartConfig));
|
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) {
|
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) {
|
void gui_update(Gui* gui) {
|
||||||
furi_assert(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) {
|
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;
|
Gui* gui = ctx;
|
||||||
|
|
||||||
osMessageQueuePut(gui->input_queue, value, 0, osWaitForever);
|
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
|
// Only Fullscreen supports vertical display for now
|
||||||
@ -471,7 +471,7 @@ void gui_set_lockdown(Gui* gui, bool lockdown) {
|
|||||||
Gui* gui_alloc() {
|
Gui* gui_alloc() {
|
||||||
Gui* gui = malloc(sizeof(Gui));
|
Gui* gui = malloc(sizeof(Gui));
|
||||||
// Thread ID
|
// Thread ID
|
||||||
gui->thread = osThreadGetId();
|
gui->thread_id = furi_thread_get_current_id();
|
||||||
// Allocate mutex
|
// Allocate mutex
|
||||||
gui->mutex = osMutexNew(NULL);
|
gui->mutex = osMutexNew(NULL);
|
||||||
furi_check(gui->mutex);
|
furi_check(gui->mutex);
|
||||||
@ -500,7 +500,8 @@ int32_t gui_srv(void* p) {
|
|||||||
furi_record_create("gui", gui);
|
furi_record_create("gui", gui);
|
||||||
|
|
||||||
while(1) {
|
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
|
// Process and dispatch input
|
||||||
if(flags & GUI_THREAD_FLAG_INPUT) {
|
if(flags & GUI_THREAD_FLAG_INPUT) {
|
||||||
// Process till queue become empty
|
// Process till queue become empty
|
||||||
@ -512,7 +513,7 @@ int32_t gui_srv(void* p) {
|
|||||||
// Process and dispatch draw call
|
// Process and dispatch draw call
|
||||||
if(flags & GUI_THREAD_FLAG_DRAW) {
|
if(flags & GUI_THREAD_FLAG_DRAW) {
|
||||||
// Clear flags that arrived on input step
|
// Clear flags that arrived on input step
|
||||||
osThreadFlagsClear(GUI_THREAD_FLAG_DRAW);
|
furi_thread_flags_clear(GUI_THREAD_FLAG_DRAW);
|
||||||
gui_redraw(gui);
|
gui_redraw(gui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ ALGO_DEF(CanvasCallbackPairArray, CanvasCallbackPairArray_t);
|
|||||||
/** Gui structure */
|
/** Gui structure */
|
||||||
struct Gui {
|
struct Gui {
|
||||||
// Thread and lock
|
// Thread and lock
|
||||||
osThreadId_t thread;
|
FuriThreadId thread_id;
|
||||||
osMutexId_t mutex;
|
osMutexId_t mutex;
|
||||||
|
|
||||||
// Layers and Canvas
|
// Layers and Canvas
|
||||||
|
@ -259,10 +259,10 @@ static int32_t browser_worker(void* context) {
|
|||||||
string_t filename;
|
string_t filename;
|
||||||
string_init(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) {
|
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);
|
furi_assert((flags & osFlagsError) == 0);
|
||||||
|
|
||||||
if(flags & WorkerEvtConfigChange) {
|
if(flags & WorkerEvtConfigChange) {
|
||||||
@ -272,7 +272,7 @@ static int32_t browser_worker(void* context) {
|
|||||||
}
|
}
|
||||||
idx_last_array_reset(browser->idx_last);
|
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) {
|
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) {
|
void file_browser_worker_free(BrowserWorker* browser) {
|
||||||
furi_assert(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_join(browser->thread);
|
||||||
furi_thread_free(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(browser->path_next, path);
|
||||||
string_set_str(browser->filter_extension, filter_ext);
|
string_set_str(browser->filter_extension, filter_ext);
|
||||||
browser->skip_assets = skip_assets;
|
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) {
|
void file_browser_worker_folder_enter(BrowserWorker* browser, string_t path, int32_t item_idx) {
|
||||||
furi_assert(browser);
|
furi_assert(browser);
|
||||||
string_set(browser->path_next, path);
|
string_set(browser->path_next, path);
|
||||||
browser->item_sel_idx = item_idx;
|
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) {
|
void file_browser_worker_folder_exit(BrowserWorker* browser) {
|
||||||
furi_assert(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) {
|
void file_browser_worker_folder_refresh(BrowserWorker* browser, int32_t item_idx) {
|
||||||
furi_assert(browser);
|
furi_assert(browser);
|
||||||
browser->item_sel_idx = item_idx;
|
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) {
|
void file_browser_worker_load(BrowserWorker* browser, uint32_t offset, uint32_t count) {
|
||||||
furi_assert(browser);
|
furi_assert(browser);
|
||||||
browser->load_offset = offset;
|
browser->load_offset = offset;
|
||||||
browser->load_count = count;
|
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) {
|
void input_isr(void* _ctx) {
|
||||||
UNUSED(_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) {
|
const char* input_get_key_name(InputKey key) {
|
||||||
@ -66,7 +66,7 @@ const char* input_get_type_name(InputType type) {
|
|||||||
|
|
||||||
int32_t input_srv() {
|
int32_t input_srv() {
|
||||||
input = malloc(sizeof(Input));
|
input = malloc(sizeof(Input));
|
||||||
input->thread = osThreadGetId();
|
input->thread_id = furi_thread_get_current_id();
|
||||||
input->event_pubsub = furi_pubsub_alloc();
|
input->event_pubsub = furi_pubsub_alloc();
|
||||||
furi_record_create("input_events", input->event_pubsub);
|
furi_record_create("input_events", input->event_pubsub);
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ int32_t input_srv() {
|
|||||||
if(is_changing) {
|
if(is_changing) {
|
||||||
osDelay(1);
|
osDelay(1);
|
||||||
} else {
|
} 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 */
|
/** Input state */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
osThreadId_t thread;
|
FuriThreadId thread_id;
|
||||||
FuriPubSub* event_pubsub;
|
FuriPubSub* event_pubsub;
|
||||||
InputPinState* pin_states;
|
InputPinState* pin_states;
|
||||||
Cli* cli;
|
Cli* cli;
|
||||||
|
@ -29,13 +29,9 @@ static bool
|
|||||||
furi_thread_set_callback(
|
furi_thread_set_callback(
|
||||||
loader_instance->application_thread, loader_instance->application->app);
|
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) {
|
return true;
|
||||||
loader_instance->application = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loader_menu_callback(void* _ctx, uint32_t index) {
|
static void loader_menu_callback(void* _ctx, uint32_t index) {
|
||||||
@ -300,7 +296,7 @@ static Loader* loader_alloc() {
|
|||||||
UNUSED(loader_cli);
|
UNUSED(loader_cli);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
instance->loader_thread = osThreadGetId();
|
instance->loader_thread = furi_thread_get_current_id();
|
||||||
|
|
||||||
// Gui
|
// Gui
|
||||||
instance->gui = furi_record_open("gui");
|
instance->gui = furi_record_open("gui");
|
||||||
@ -444,7 +440,7 @@ static void loader_build_submenu() {
|
|||||||
|
|
||||||
void loader_show_menu() {
|
void loader_show_menu() {
|
||||||
furi_assert(loader_instance);
|
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() {
|
void loader_update_menu() {
|
||||||
@ -474,7 +470,8 @@ int32_t loader_srv(void* p) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
while(1) {
|
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) {
|
if(flags & LOADER_THREAD_FLAG_SHOW_MENU) {
|
||||||
menu_set_selected_item(loader_instance->primary_menu, 0);
|
menu_set_selected_item(loader_instance->primary_menu, 0);
|
||||||
view_dispatcher_switch_to_view(
|
view_dispatcher_switch_to_view(
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#include <assets_icons.h>
|
#include <assets_icons.h>
|
||||||
|
|
||||||
struct Loader {
|
struct Loader {
|
||||||
osThreadId_t loader_thread;
|
FuriThreadId loader_thread;
|
||||||
|
|
||||||
const FlipperApplication* application;
|
const FlipperApplication* application;
|
||||||
FuriThread* application_thread;
|
FuriThread* application_thread;
|
||||||
|
@ -408,7 +408,7 @@ size_t
|
|||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
size_t bytes_sent = xStreamBufferSend(session->stream, encoded_bytes, size, timeout);
|
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;
|
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) {
|
if(count == bytes_received) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
flags = osThreadFlagsWait(RPC_ALL_EVENTS, osFlagsWaitAny, osWaitForever);
|
flags = furi_thread_flags_wait(RPC_ALL_EVENTS, osFlagsWaitAny, osWaitForever);
|
||||||
if(flags & RpcEvtDisconnect) {
|
if(flags & RpcEvtDisconnect) {
|
||||||
if(xStreamBufferIsEmpty(session->stream)) {
|
if(xStreamBufferIsEmpty(session->stream)) {
|
||||||
session->terminate = true;
|
session->terminate = true;
|
||||||
@ -450,7 +450,7 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
|
|||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
/* Save disconnect flag and continue reading buffer */
|
/* 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) {
|
} else if(flags & RpcEvtNewData) {
|
||||||
// Just wake thread up
|
// 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_send_bytes_callback(session, NULL);
|
||||||
rpc_session_set_close_callback(session, NULL);
|
rpc_session_set_close_callback(session, NULL);
|
||||||
rpc_session_set_buffer_is_empty_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) {
|
int32_t rpc_srv(void* p) {
|
||||||
|
@ -40,8 +40,7 @@ static void
|
|||||||
|
|
||||||
memcpy(buffer, data, size);
|
memcpy(buffer, data, size);
|
||||||
|
|
||||||
osThreadFlagsSet(
|
furi_thread_flags_set(furi_thread_get_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagTransmit);
|
||||||
furi_thread_get_thread_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagTransmit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t rpc_system_gui_screen_stream_frame_transmit_thread(void* context) {
|
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;
|
RpcGuiSystem* rpc_gui = (RpcGuiSystem*)context;
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
uint32_t flags = osThreadFlagsWait(RpcGuiWorkerFlagAny, osFlagsWaitAny, osWaitForever);
|
uint32_t flags =
|
||||||
|
furi_thread_flags_wait(RpcGuiWorkerFlagAny, osFlagsWaitAny, osWaitForever);
|
||||||
if(flags & RpcGuiWorkerFlagTransmit) {
|
if(flags & RpcGuiWorkerFlagTransmit) {
|
||||||
rpc_send(rpc_gui->session, rpc_gui->transmit_frame);
|
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(
|
gui_remove_framebuffer_callback(
|
||||||
rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context);
|
rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context);
|
||||||
// Stop and release worker thread
|
// Stop and release worker thread
|
||||||
osThreadFlagsSet(
|
furi_thread_flags_set(furi_thread_get_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagExit);
|
||||||
furi_thread_get_thread_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagExit);
|
|
||||||
furi_thread_join(rpc_gui->transmit_thread);
|
furi_thread_join(rpc_gui->transmit_thread);
|
||||||
furi_thread_free(rpc_gui->transmit_thread);
|
furi_thread_free(rpc_gui->transmit_thread);
|
||||||
// Release frame
|
// Release frame
|
||||||
@ -367,8 +366,7 @@ void rpc_system_gui_free(void* context) {
|
|||||||
gui_remove_framebuffer_callback(
|
gui_remove_framebuffer_callback(
|
||||||
rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context);
|
rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context);
|
||||||
// Stop and release worker thread
|
// Stop and release worker thread
|
||||||
osThreadFlagsSet(
|
furi_thread_flags_set(furi_thread_get_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagExit);
|
||||||
furi_thread_get_thread_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagExit);
|
|
||||||
furi_thread_join(rpc_gui->transmit_thread);
|
furi_thread_join(rpc_gui->transmit_thread);
|
||||||
furi_thread_free(rpc_gui->transmit_thread);
|
furi_thread_free(rpc_gui->transmit_thread);
|
||||||
// Release frame
|
// Release frame
|
||||||
|
@ -92,7 +92,9 @@ bool subghz_chat_worker_start(SubGhzChatWorker* instance, uint32_t frequency) {
|
|||||||
instance->worker_running = true;
|
instance->worker_running = true;
|
||||||
instance->last_time_rx_data = 0;
|
instance->last_time_rx_data = 0;
|
||||||
|
|
||||||
res = furi_thread_start(instance->thread);
|
furi_thread_start(instance->thread);
|
||||||
|
|
||||||
|
res = true;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -72,18 +72,18 @@ static void u2f_hid_event_callback(HidU2fEvent ev, void* context) {
|
|||||||
U2fHid* u2f_hid = context;
|
U2fHid* u2f_hid = context;
|
||||||
|
|
||||||
if(ev == HidU2fDisconnected)
|
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)
|
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)
|
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) {
|
static void u2f_hid_lock_timeout_callback(void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
U2fHid* u2f_hid = 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) {
|
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);
|
furi_hal_hid_u2f_set_callback(u2f_hid_event_callback, u2f_hid);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
uint32_t flags = osThreadFlagsWait(
|
uint32_t flags = furi_thread_flags_wait(
|
||||||
WorkerEvtStop | WorkerEvtConnect | WorkerEvtDisconnect | WorkerEvtRequest,
|
WorkerEvtStop | WorkerEvtConnect | WorkerEvtDisconnect | WorkerEvtRequest,
|
||||||
osFlagsWaitAny,
|
osFlagsWaitAny,
|
||||||
osWaitForever);
|
osWaitForever);
|
||||||
@ -292,7 +292,7 @@ U2fHid* u2f_hid_start(U2fData* u2f_inst) {
|
|||||||
|
|
||||||
void u2f_hid_stop(U2fHid* u2f_hid) {
|
void u2f_hid_stop(U2fHid* u2f_hid) {
|
||||||
furi_assert(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_join(u2f_hid->thread);
|
||||||
furi_thread_free(u2f_hid->thread);
|
furi_thread_free(u2f_hid->thread);
|
||||||
free(u2f_hid);
|
free(u2f_hid);
|
||||||
|
@ -40,91 +40,3 @@ void test_furi_valuemutex() {
|
|||||||
|
|
||||||
mu_check(delete_mutex(&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();
|
test_furi_valuemutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(mu_test_furi_concurrent_access) {
|
|
||||||
test_furi_concurrent_access();
|
|
||||||
}
|
|
||||||
|
|
||||||
MU_TEST(mu_test_furi_pubsub) {
|
MU_TEST(mu_test_furi_pubsub) {
|
||||||
test_furi_pubsub();
|
test_furi_pubsub();
|
||||||
}
|
}
|
||||||
@ -55,7 +51,6 @@ MU_TEST_SUITE(test_suite) {
|
|||||||
// v2 tests
|
// v2 tests
|
||||||
MU_RUN_TEST(mu_test_furi_create_open);
|
MU_RUN_TEST(mu_test_furi_create_open);
|
||||||
MU_RUN_TEST(mu_test_furi_valuemutex);
|
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_pubsub);
|
||||||
MU_RUN_TEST(mu_test_furi_memmgr);
|
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_stack_size(locker_thread, 2048);
|
||||||
furi_thread_set_context(locker_thread, semaphore);
|
furi_thread_set_context(locker_thread, semaphore);
|
||||||
furi_thread_set_callback(locker_thread, storage_file_locker);
|
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
|
// wait for file lock
|
||||||
osSemaphoreAcquire(semaphore, osWaitForever);
|
osSemaphoreAcquire(semaphore, osWaitForever);
|
||||||
@ -139,7 +139,7 @@ MU_TEST(storage_dir_open_lock) {
|
|||||||
furi_thread_set_stack_size(locker_thread, 2048);
|
furi_thread_set_stack_size(locker_thread, 2048);
|
||||||
furi_thread_set_context(locker_thread, semaphore);
|
furi_thread_set_context(locker_thread, semaphore);
|
||||||
furi_thread_set_callback(locker_thread, storage_dir_locker);
|
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
|
// wait for dir lock
|
||||||
osSemaphoreAcquire(semaphore, osWaitForever);
|
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);
|
bool level = level_duration_get_level(level_duration);
|
||||||
uint32_t duration = level_duration_get_duration(level_duration);
|
uint32_t duration = level_duration_get_duration(level_duration);
|
||||||
// Yield, to load data inside the worker
|
// Yield, to load data inside the worker
|
||||||
osThreadYield();
|
furi_thread_yield();
|
||||||
decoder->protocol->decoder->feed(decoder, level, duration);
|
decoder->protocol->decoder->feed(decoder, level, duration);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@ -115,7 +115,7 @@ static bool subghz_decode_random_test(const char* path) {
|
|||||||
bool level = level_duration_get_level(level_duration);
|
bool level = level_duration_get_level(level_duration);
|
||||||
uint32_t duration = level_duration_get_duration(level_duration);
|
uint32_t duration = level_duration_get_duration(level_duration);
|
||||||
// Yield, to load data inside the worker
|
// Yield, to load data inside the worker
|
||||||
osThreadYield();
|
furi_thread_yield();
|
||||||
subghz_receiver_decode(receiver_handler, level, duration);
|
subghz_receiver_decode(receiver_handler, level, duration);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -324,9 +324,9 @@ void update_task_set_progress_cb(UpdateTask* update_task, updateProgressCb cb, v
|
|||||||
update_task->status_change_cb_state = state;
|
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);
|
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) {
|
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);
|
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);
|
bool update_task_is_running(UpdateTask* update_task);
|
||||||
|
|
||||||
|
@ -6,16 +6,19 @@
|
|||||||
|
|
||||||
#include <cmsis_os2.h>
|
#include <cmsis_os2.h>
|
||||||
|
|
||||||
#include <furi/common_defines.h>
|
|
||||||
#include <furi/check.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.h>
|
||||||
#include <furi/memmgr_heap.h>
|
#include <furi/memmgr_heap.h>
|
||||||
|
#include <furi/mutex.h>
|
||||||
#include <furi/pubsub.h>
|
#include <furi/pubsub.h>
|
||||||
#include <furi/record.h>
|
#include <furi/record.h>
|
||||||
|
#include <furi/semaphore.h>
|
||||||
#include <furi/stdglue.h>
|
#include <furi/stdglue.h>
|
||||||
#include <furi/thread.h>
|
#include <furi/thread.h>
|
||||||
#include <furi/valuemutex.h>
|
#include <furi/valuemutex.h>
|
||||||
#include <furi/log.h>
|
|
||||||
|
|
||||||
#include <furi_hal_gpio.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 <furi_hal_rtc.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <task.h>
|
||||||
|
|
||||||
void __furi_print_name() {
|
void __furi_print_name() {
|
||||||
if(FURI_IS_ISR()) {
|
if(FURI_IS_ISR()) {
|
||||||
furi_hal_console_puts("[ISR] ");
|
furi_hal_console_puts("[ISR] ");
|
||||||
} else {
|
} else {
|
||||||
const char* name = osThreadGetName(osThreadGetId());
|
const char* name = pcTaskGetName(xTaskGetCurrentTaskHandle());
|
||||||
if(name == NULL) {
|
if(name == NULL) {
|
||||||
furi_hal_console_puts("[main] ");
|
furi_hal_console_puts("[main] ");
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#define FURI_NORETURN [[noreturn]]
|
#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 "log.h"
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
#include "mutex.h"
|
||||||
#include <cmsis_os2.h>
|
#include <cmsis_os2.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ void memmgr_heap_init() {
|
|||||||
MemmgrHeapThreadDict_init(memmgr_heap_thread_dict);
|
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();
|
vTaskSuspendAll();
|
||||||
{
|
{
|
||||||
memmgr_heap_thread_trace_depth++;
|
memmgr_heap_thread_trace_depth++;
|
||||||
@ -147,7 +147,7 @@ void memmgr_heap_enable_thread_trace(osThreadId_t thread_id) {
|
|||||||
(void)xTaskResumeAll();
|
(void)xTaskResumeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void memmgr_heap_disable_thread_trace(osThreadId_t thread_id) {
|
void memmgr_heap_disable_thread_trace(FuriThreadId thread_id) {
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
{
|
{
|
||||||
memmgr_heap_thread_trace_depth++;
|
memmgr_heap_thread_trace_depth++;
|
||||||
@ -158,7 +158,7 @@ void memmgr_heap_disable_thread_trace(osThreadId_t thread_id) {
|
|||||||
(void)xTaskResumeAll();
|
(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;
|
size_t leftovers = MEMMGR_HEAP_UNKNOWN;
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
{
|
{
|
||||||
@ -192,7 +192,7 @@ size_t memmgr_heap_get_thread_memory(osThreadId_t thread_id) {
|
|||||||
|
|
||||||
#undef traceMALLOC
|
#undef traceMALLOC
|
||||||
static inline void traceMALLOC(void* pointer, size_t size) {
|
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) {
|
if(thread_id && memmgr_heap_thread_trace_depth == 0) {
|
||||||
memmgr_heap_thread_trace_depth++;
|
memmgr_heap_thread_trace_depth++;
|
||||||
MemmgrHeapAllocDict_t* alloc_dict =
|
MemmgrHeapAllocDict_t* alloc_dict =
|
||||||
@ -207,7 +207,7 @@ static inline void traceMALLOC(void* pointer, size_t size) {
|
|||||||
#undef traceFREE
|
#undef traceFREE
|
||||||
static inline void traceFREE(void* pointer, size_t size) {
|
static inline void traceFREE(void* pointer, size_t size) {
|
||||||
UNUSED(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) {
|
if(thread_id && memmgr_heap_thread_trace_depth == 0) {
|
||||||
memmgr_heap_thread_trace_depth++;
|
memmgr_heap_thread_trace_depth++;
|
||||||
MemmgrHeapAllocDict_t* alloc_dict =
|
MemmgrHeapAllocDict_t* alloc_dict =
|
||||||
@ -297,7 +297,7 @@ static void print_heap_init() {
|
|||||||
|
|
||||||
static void print_heap_malloc(void* ptr, size_t size) {
|
static void print_heap_malloc(void* ptr, size_t size) {
|
||||||
char tmp_str[33];
|
char tmp_str[33];
|
||||||
const char* name = osThreadGetName(osThreadGetId());
|
const char* name = furi_thread_get_name(furi_thread_get_current_id());
|
||||||
if(!name) {
|
if(!name) {
|
||||||
name = "";
|
name = "";
|
||||||
}
|
}
|
||||||
@ -318,7 +318,7 @@ static void print_heap_malloc(void* ptr, size_t size) {
|
|||||||
|
|
||||||
static void print_heap_free(void* ptr) {
|
static void print_heap_free(void* ptr) {
|
||||||
char tmp_str[33];
|
char tmp_str[33];
|
||||||
const char* name = osThreadGetName(osThreadGetId());
|
const char* name = furi_thread_get_name(furi_thread_get_current_id());
|
||||||
if(!name) {
|
if(!name) {
|
||||||
name = "";
|
name = "";
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <cmsis_os2.h>
|
#include "furi/thread.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -18,13 +18,13 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
* @param thread_id - thread id to track
|
* @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
|
/** Memmgr heap disable thread allocation tracking
|
||||||
*
|
*
|
||||||
* @param thread_id - thread id to track
|
* @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
|
/** 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
|
* @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
|
/** 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 "pubsub.h"
|
||||||
#include "memmgr.h"
|
#include "memmgr.h"
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
#include "mutex.h"
|
||||||
|
|
||||||
#include <m-list.h>
|
#include <m-list.h>
|
||||||
#include <cmsis_os2.h>
|
|
||||||
|
|
||||||
struct FuriPubSubSubscription {
|
struct FuriPubSubSubscription {
|
||||||
FuriPubSubCallback callback;
|
FuriPubSubCallback callback;
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#include "record.h"
|
#include "record.h"
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "memmgr.h"
|
#include "memmgr.h"
|
||||||
|
#include "mutex.h"
|
||||||
|
#include "event_flags.h"
|
||||||
|
|
||||||
#include <cmsis_os2.h>
|
|
||||||
#include <m-string.h>
|
#include <m-string.h>
|
||||||
#include <m-dict.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);
|
furi_assert(furi_stdglue);
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
osKernelState_t state = osKernelGetState();
|
osKernelState_t state = osKernelGetState();
|
||||||
osThreadId_t thread_id = osThreadGetId();
|
FuriThreadId task_id = furi_thread_get_current_id();
|
||||||
if(state == osKernelRunning && thread_id &&
|
if(state == osKernelRunning && task_id &&
|
||||||
osMutexAcquire(furi_stdglue->mutex, osWaitForever) == osOK) {
|
osMutexAcquire(furi_stdglue->mutex, osWaitForever) == osOK) {
|
||||||
// We are in the thread context
|
// We are in the thread context
|
||||||
// Handle thread callbacks
|
// Handle thread callbacks
|
||||||
FuriStdglueWriteCallback* callback_ptr =
|
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) {
|
if(callback_ptr) {
|
||||||
(*callback_ptr)(_cookie, data, size);
|
(*callback_ptr)(_cookie, data, size);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
@ -76,14 +76,14 @@ void furi_stdglue_init() {
|
|||||||
|
|
||||||
bool furi_stdglue_set_thread_stdout_callback(FuriStdglueWriteCallback callback) {
|
bool furi_stdglue_set_thread_stdout_callback(FuriStdglueWriteCallback callback) {
|
||||||
furi_assert(furi_stdglue);
|
furi_assert(furi_stdglue);
|
||||||
osThreadId_t thread_id = osThreadGetId();
|
FuriThreadId task_id = furi_thread_get_current_id();
|
||||||
if(thread_id) {
|
if(task_id) {
|
||||||
furi_check(osMutexAcquire(furi_stdglue->mutex, osWaitForever) == osOK);
|
furi_check(osMutexAcquire(furi_stdglue->mutex, osWaitForever) == osOK);
|
||||||
if(callback) {
|
if(callback) {
|
||||||
FuriStdglueCallbackDict_set_at(
|
FuriStdglueCallbackDict_set_at(
|
||||||
furi_stdglue->thread_outputs, (uint32_t)thread_id, callback);
|
furi_stdglue->thread_outputs, (uint32_t)task_id, callback);
|
||||||
} else {
|
} 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);
|
furi_check(osMutexRelease(furi_stdglue->mutex) == osOK);
|
||||||
return true;
|
return true;
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
#include "memmgr.h"
|
#include "memmgr.h"
|
||||||
#include "memmgr_heap.h"
|
#include "memmgr_heap.h"
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
#include "common_defines.h"
|
||||||
|
|
||||||
|
#include <task.h>
|
||||||
#include <m-string.h>
|
#include <m-string.h>
|
||||||
|
|
||||||
struct FuriThread {
|
struct FuriThread {
|
||||||
@ -15,14 +17,22 @@ struct FuriThread {
|
|||||||
FuriThreadStateCallback state_callback;
|
FuriThreadStateCallback state_callback;
|
||||||
void* state_context;
|
void* state_context;
|
||||||
|
|
||||||
osThreadAttr_t attr;
|
char* name;
|
||||||
volatile osThreadId_t id;
|
configSTACK_DEPTH_TYPE stack_size;
|
||||||
|
FuriThreadPriority priority;
|
||||||
|
|
||||||
|
TaskHandle_t task_handle;
|
||||||
bool heap_trace_enabled;
|
bool heap_trace_enabled;
|
||||||
size_t heap_size;
|
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);
|
furi_assert(thread);
|
||||||
thread->state = state;
|
thread->state = state;
|
||||||
if(thread->state_callback) {
|
if(thread->state_callback) {
|
||||||
@ -37,23 +47,24 @@ static void furi_thread_body(void* context) {
|
|||||||
furi_assert(thread->state == FuriThreadStateStarting);
|
furi_assert(thread->state == FuriThreadStateStarting);
|
||||||
furi_thread_set_state(thread, FuriThreadStateRunning);
|
furi_thread_set_state(thread, FuriThreadStateRunning);
|
||||||
|
|
||||||
osThreadId_t thread_id = osThreadGetId();
|
TaskHandle_t task_handle = xTaskGetCurrentTaskHandle();
|
||||||
if(thread->heap_trace_enabled == true) {
|
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);
|
thread->ret = thread->callback(thread->context);
|
||||||
|
|
||||||
if(thread->heap_trace_enabled == true) {
|
if(thread->heap_trace_enabled == true) {
|
||||||
osDelay(33);
|
osDelay(33);
|
||||||
thread->heap_size = memmgr_heap_get_thread_memory(thread_id);
|
thread->heap_size = memmgr_heap_get_thread_memory((FuriThreadId)task_handle);
|
||||||
memmgr_heap_disable_thread_trace(thread_id);
|
memmgr_heap_disable_thread_trace((FuriThreadId)task_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_assert(thread->state == FuriThreadStateRunning);
|
furi_assert(thread->state == FuriThreadStateRunning);
|
||||||
furi_thread_set_state(thread, FuriThreadStateStopped);
|
furi_thread_set_state(thread, FuriThreadStateStopped);
|
||||||
|
|
||||||
osThreadExit();
|
vTaskDelete(thread->task_handle);
|
||||||
|
furi_thread_catch();
|
||||||
}
|
}
|
||||||
|
|
||||||
FuriThread* furi_thread_alloc() {
|
FuriThread* furi_thread_alloc() {
|
||||||
@ -66,21 +77,22 @@ void furi_thread_free(FuriThread* thread) {
|
|||||||
furi_assert(thread);
|
furi_assert(thread);
|
||||||
furi_assert(thread->state == FuriThreadStateStopped);
|
furi_assert(thread->state == FuriThreadStateStopped);
|
||||||
|
|
||||||
if(thread->attr.name) free((void*)thread->attr.name);
|
if(thread->name) free((void*)thread->name);
|
||||||
free(thread);
|
free(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_thread_set_name(FuriThread* thread, const char* name) {
|
void furi_thread_set_name(FuriThread* thread, const char* name) {
|
||||||
furi_assert(thread);
|
furi_assert(thread);
|
||||||
furi_assert(thread->state == FuriThreadStateStopped);
|
furi_assert(thread->state == FuriThreadStateStopped);
|
||||||
if(thread->attr.name) free((void*)thread->attr.name);
|
if(thread->name) free((void*)thread->name);
|
||||||
thread->attr.name = strdup(name);
|
thread->name = strdup(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_thread_set_stack_size(FuriThread* thread, size_t stack_size) {
|
void furi_thread_set_stack_size(FuriThread* thread, size_t stack_size) {
|
||||||
furi_assert(thread);
|
furi_assert(thread);
|
||||||
furi_assert(thread->state == FuriThreadStateStopped);
|
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) {
|
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;
|
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) {
|
void furi_thread_set_state_callback(FuriThread* thread, FuriThreadStateCallback callback) {
|
||||||
furi_assert(thread);
|
furi_assert(thread);
|
||||||
furi_assert(thread->state == FuriThreadStateStopped);
|
furi_assert(thread->state == FuriThreadStateStopped);
|
||||||
@ -112,41 +131,39 @@ FuriThreadState furi_thread_get_state(FuriThread* thread) {
|
|||||||
return thread->state;
|
return thread->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool furi_thread_start(FuriThread* thread) {
|
void furi_thread_start(FuriThread* thread) {
|
||||||
furi_assert(thread);
|
furi_assert(thread);
|
||||||
furi_assert(thread->callback);
|
furi_assert(thread->callback);
|
||||||
furi_assert(thread->state == FuriThreadStateStopped);
|
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);
|
furi_thread_set_state(thread, FuriThreadStateStarting);
|
||||||
thread->id = osThreadNew(furi_thread_body, thread, &thread->attr);
|
|
||||||
if(thread->id) {
|
BaseType_t ret = xTaskCreate(
|
||||||
return true;
|
furi_thread_body,
|
||||||
} else {
|
thread->name,
|
||||||
furi_assert(thread->state == FuriThreadStateStarting);
|
thread->stack_size / 4,
|
||||||
furi_thread_set_state(thread, FuriThreadStateStopped);
|
thread,
|
||||||
return false;
|
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);
|
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) {
|
while(thread->state != FuriThreadStateStopped) {
|
||||||
osDelay(10);
|
osDelay(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
return osOK;
|
return osOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
osThreadId_t furi_thread_get_thread_id(FuriThread* thread) {
|
FuriThreadId furi_thread_get_id(FuriThread* thread) {
|
||||||
return thread->id;
|
furi_assert(thread);
|
||||||
|
return thread->task_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_thread_enable_heap_trace(FuriThread* thread) {
|
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);
|
furi_assert(thread->state == FuriThreadStateStopped);
|
||||||
return thread->ret;
|
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
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "base.h"
|
||||||
#include <stdbool.h>
|
|
||||||
#include <cmsis_os2.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -20,9 +18,24 @@ typedef enum {
|
|||||||
FuriThreadStateRunning,
|
FuriThreadStateRunning,
|
||||||
} FuriThreadState;
|
} 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 */
|
/** FuriThread anonymous structure */
|
||||||
typedef struct FuriThread FuriThread;
|
typedef struct FuriThread FuriThread;
|
||||||
|
|
||||||
|
/** FuriThreadId proxy type to OS low level functions */
|
||||||
|
typedef void* FuriThreadId;
|
||||||
|
|
||||||
/** FuriThreadCallback Your callback to run in new thread
|
/** FuriThreadCallback Your callback to run in new thread
|
||||||
* @warning never use osThreadExit in FuriThread
|
* @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);
|
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
|
/** Set FuriThread state change callback
|
||||||
*
|
*
|
||||||
* @param thread FuriThread instance
|
* @param thread FuriThread instance
|
||||||
@ -99,36 +119,24 @@ FuriThreadState furi_thread_get_state(FuriThread* thread);
|
|||||||
/** Start FuriThread
|
/** Start FuriThread
|
||||||
*
|
*
|
||||||
* @param thread FuriThread instance
|
* @param thread FuriThread instance
|
||||||
*
|
|
||||||
* @return true on success
|
|
||||||
*/
|
*/
|
||||||
bool furi_thread_start(FuriThread* thread);
|
void 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);
|
|
||||||
|
|
||||||
/** Join FuriThread
|
/** Join FuriThread
|
||||||
*
|
*
|
||||||
* @param thread FuriThread instance
|
* @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
|
* @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
|
/** 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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <cmsis_os2.h>
|
#include <cmsis_os2.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "mutex.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -20,7 +20,7 @@ extern uint32_t SystemCoreClock;
|
|||||||
#define configUSE_TICK_HOOK 0
|
#define configUSE_TICK_HOOK 0
|
||||||
#define configCPU_CLOCK_HZ (SystemCoreClock)
|
#define configCPU_CLOCK_HZ (SystemCoreClock)
|
||||||
#define configTICK_RATE_HZ ((TickType_t)1000)
|
#define configTICK_RATE_HZ ((TickType_t)1000)
|
||||||
#define configMAX_PRIORITIES (56)
|
#define configMAX_PRIORITIES (32)
|
||||||
#define configMINIMAL_STACK_SIZE ((uint16_t)128)
|
#define configMINIMAL_STACK_SIZE ((uint16_t)128)
|
||||||
|
|
||||||
/* Heap size determined automatically by linker */
|
/* Heap size determined automatically by linker */
|
||||||
@ -35,7 +35,7 @@ extern uint32_t SystemCoreClock;
|
|||||||
#define configUSE_RECURSIVE_MUTEXES 1
|
#define configUSE_RECURSIVE_MUTEXES 1
|
||||||
#define configUSE_COUNTING_SEMAPHORES 1
|
#define configUSE_COUNTING_SEMAPHORES 1
|
||||||
#define configENABLE_BACKWARD_COMPATIBILITY 0
|
#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 configUSE_TICKLESS_IDLE 2
|
||||||
#define configRECORD_STACK_HIGH_ADDRESS 1
|
#define configRECORD_STACK_HIGH_ADDRESS 1
|
||||||
#define configUSE_NEWLIB_REENTRANT 0
|
#define configUSE_NEWLIB_REENTRANT 0
|
||||||
@ -89,6 +89,9 @@ to exclude the API function. */
|
|||||||
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 2
|
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 2
|
||||||
#define CMSIS_TASK_NOTIFY_INDEX 1
|
#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
|
* 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
|
* by the application thus the correct define need to be enabled below
|
||||||
|
@ -7,19 +7,16 @@
|
|||||||
|
|
||||||
#define TAG "Main"
|
#define TAG "Main"
|
||||||
|
|
||||||
static const osThreadAttr_t init_thread_attr = {
|
int32_t init_task(void* context) {
|
||||||
.name = "Init",
|
UNUSED(context);
|
||||||
.stack_size = 4096,
|
|
||||||
};
|
|
||||||
|
|
||||||
void init_task() {
|
|
||||||
// Flipper FURI HAL
|
// Flipper FURI HAL
|
||||||
furi_hal_init();
|
furi_hal_init();
|
||||||
|
|
||||||
// Init flipper
|
// Init flipper
|
||||||
flipper_init();
|
flipper_init();
|
||||||
|
|
||||||
osThreadExit();
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
@ -29,8 +26,13 @@ int main() {
|
|||||||
// Flipper critical FURI HAL
|
// Flipper critical FURI HAL
|
||||||
furi_hal_init_early();
|
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
|
#ifdef FURI_RAM_EXEC
|
||||||
osThreadNew(init_task, NULL, &init_thread_attr);
|
furi_thread_start(main_thread);
|
||||||
#else
|
#else
|
||||||
furi_hal_light_sequence("RGB");
|
furi_hal_light_sequence("RGB");
|
||||||
|
|
||||||
@ -52,7 +54,7 @@ int main() {
|
|||||||
furi_hal_power_reset();
|
furi_hal_power_reset();
|
||||||
} else {
|
} else {
|
||||||
furi_hal_light_sequence("rgb G");
|
furi_hal_light_sequence("rgb G");
|
||||||
osThreadNew(init_task, NULL, &init_thread_attr);
|
furi_thread_start(main_thread);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "gap.h"
|
#include "gap.h"
|
||||||
|
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
#define TAG "Bt"
|
#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() {
|
void ble_app_thread_stop() {
|
||||||
if(ble_app) {
|
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);
|
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_join(ble_app->thread);
|
||||||
furi_thread_free(ble_app->thread);
|
furi_thread_free(ble_app->thread);
|
||||||
// Free resources
|
// Free resources
|
||||||
@ -125,7 +126,7 @@ static int32_t ble_app_hci_thread(void* arg) {
|
|||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
|
|
||||||
while(1) {
|
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) {
|
if(flags & BLE_APP_FLAG_KILL_THREAD) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -141,9 +142,9 @@ static int32_t ble_app_hci_thread(void* arg) {
|
|||||||
void hci_notify_asynch_evt(void* pdata) {
|
void hci_notify_asynch_evt(void* pdata) {
|
||||||
UNUSED(pdata);
|
UNUSED(pdata);
|
||||||
if(ble_app) {
|
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);
|
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() {
|
void ble_glue_thread_stop() {
|
||||||
if(ble_glue) {
|
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);
|
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_join(ble_glue->thread);
|
||||||
furi_thread_free(ble_glue->thread);
|
furi_thread_free(ble_glue->thread);
|
||||||
// Free resources
|
// Free resources
|
||||||
@ -353,7 +353,7 @@ static int32_t ble_glue_shci_thread(void* context) {
|
|||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
|
|
||||||
while(true) {
|
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) {
|
if(flags & BLE_GLUE_FLAG_SHCI_EVENT) {
|
||||||
shci_user_evt_proc();
|
shci_user_evt_proc();
|
||||||
}
|
}
|
||||||
@ -368,9 +368,9 @@ static int32_t ble_glue_shci_thread(void* context) {
|
|||||||
void shci_notify_asynch_evt(void* pdata) {
|
void shci_notify_asynch_evt(void* pdata) {
|
||||||
UNUSED(pdata);
|
UNUSED(pdata);
|
||||||
if(ble_glue) {
|
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);
|
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() {
|
void furi_hal_bt_nvm_sram_sem_acquire() {
|
||||||
while(LL_HSEM_1StepLock(HSEM, CFG_HW_BLE_NVM_SRAM_SEMID)) {
|
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() {
|
void furi_hal_crc_reset() {
|
||||||
furi_check(hal_crc_control.state == CRC_State_Ready);
|
furi_check(hal_crc_control.state == CRC_State_Ready);
|
||||||
if(hal_crc_control.mtx) {
|
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);
|
osMutexRelease(hal_crc_control.mtx);
|
||||||
}
|
}
|
||||||
LL_CRC_ResetCRCCalculationUnit(CRC);
|
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) {
|
static void furi_hal_flash_begin_with_core2(bool erase_flag) {
|
||||||
// Take flash controller ownership
|
// Take flash controller ownership
|
||||||
while(LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID) != 0) {
|
while(LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID) != 0) {
|
||||||
osThreadYield();
|
furi_thread_yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock flash operation
|
// Unlock flash operation
|
||||||
@ -128,7 +128,7 @@ static void furi_hal_flash_begin_with_core2(bool erase_flag) {
|
|||||||
while(true) {
|
while(true) {
|
||||||
// Wait till flash controller become usable
|
// Wait till flash controller become usable
|
||||||
while(LL_FLASH_IsActiveFlag_OperationSuspended()) {
|
while(LL_FLASH_IsActiveFlag_OperationSuspended()) {
|
||||||
osThreadYield();
|
furi_thread_yield();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Just a little more love
|
// 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
|
// Actually we already have mutex for it, but specification is specification
|
||||||
if(LL_HSEM_IsSemaphoreLocked(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID)) {
|
if(LL_HSEM_IsSemaphoreLocked(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID)) {
|
||||||
taskEXIT_CRITICAL();
|
taskEXIT_CRITICAL();
|
||||||
osThreadYield();
|
furi_thread_yield();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take sempahopre and prevent core2 from anything funky
|
// Take sempahopre and prevent core2 from anything funky
|
||||||
if(LL_HSEM_1StepLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID) != 0) {
|
if(LL_HSEM_1StepLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID) != 0) {
|
||||||
taskEXIT_CRITICAL();
|
taskEXIT_CRITICAL();
|
||||||
osThreadYield();
|
furi_thread_yield();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ static void furi_hal_flash_end_with_core2(bool erase_flag) {
|
|||||||
|
|
||||||
// Doesn't make much sense, does it?
|
// Doesn't make much sense, does it?
|
||||||
while(READ_BIT(FLASH->SR, FLASH_SR_BSY)) {
|
while(READ_BIT(FLASH->SR, FLASH_SR_BSY)) {
|
||||||
osThreadYield();
|
furi_thread_yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Erase activity over, core2 can continue
|
// 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 */
|
/* 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));
|
furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT));
|
||||||
while(LL_FLASH_IsActiveFlag_OperationSuspended()) {
|
while(LL_FLASH_IsActiveFlag_OperationSuspended()) {
|
||||||
osThreadYield();
|
furi_thread_yield();
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 4. Set the Options start bit OPTSTRT */
|
/* 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");
|
FURI_LOG_T(TAG, "Timeout");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
osThreadYield();
|
furi_thread_yield();
|
||||||
}
|
}
|
||||||
rfalNfcGetDevicesFound(&dev_list, &dev_cnt);
|
rfalNfcGetDevicesFound(&dev_list, &dev_cnt);
|
||||||
// Take first device and set cuid
|
// 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
|
// 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);
|
st25r3916ClearAndEnableInterrupts(ST25R3916_IRQ_MASK_RXE);
|
||||||
|
|
||||||
uint32_t irq = 0;
|
uint32_t irq = 0;
|
||||||
uint8_t rxe = 0;
|
uint8_t rxe = 0;
|
||||||
uint32_t start = DWT->CYCCNT;
|
uint32_t start = DWT->CYCCNT;
|
||||||
while(true) {
|
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);
|
st25r3916ReadRegister(ST25R3916_REG_IRQ_MAIN, &rxe);
|
||||||
if(rxe & (1 << 4)) {
|
if(rxe & (1 << 4)) {
|
||||||
irq = 1;
|
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_pa6 = {.port = GPIOA, .pin = LL_GPIO_PIN_6};
|
||||||
const GpioPin gpio_ext_pa7 = {.port = GPIOA, .pin = LL_GPIO_PIN_7};
|
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_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_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};
|
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(&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);
|
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_pa6;
|
||||||
extern const GpioPin gpio_ext_pa7;
|
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_carrier_out;
|
||||||
extern const GpioPin gpio_rfid_data_in;
|
extern const GpioPin gpio_rfid_data_in;
|
||||||
extern const GpioPin gpio_rfid_carrier;
|
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);
|
furi_hal_gpio_write(&gpio_rfid_carrier_out, false);
|
||||||
|
|
||||||
// from both sides
|
// from both sides
|
||||||
furi_hal_gpio_init(&gpio_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||||
furi_hal_gpio_write(&gpio_rfid_pull, true);
|
furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, true);
|
||||||
|
|
||||||
furi_hal_gpio_init_simple(&gpio_rfid_carrier, GpioModeAnalog);
|
furi_hal_gpio_init_simple(&gpio_rfid_carrier, GpioModeAnalog);
|
||||||
|
|
||||||
@ -84,7 +84,11 @@ void furi_hal_rfid_pins_emulate() {
|
|||||||
|
|
||||||
// pull pin to timer out
|
// pull pin to timer out
|
||||||
furi_hal_gpio_init_ex(
|
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
|
// pull rfid antenna from carrier side
|
||||||
furi_hal_gpio_init(&gpio_rfid_carrier_out, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
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();
|
furi_hal_ibutton_pin_low();
|
||||||
|
|
||||||
// dont pull rfid antenna
|
// dont pull rfid antenna
|
||||||
furi_hal_gpio_init(&gpio_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||||
furi_hal_gpio_write(&gpio_rfid_pull, false);
|
furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, false);
|
||||||
|
|
||||||
// carrier pin to timer out
|
// carrier pin to timer out
|
||||||
furi_hal_gpio_init_ex(
|
furi_hal_gpio_init_ex(
|
||||||
@ -116,11 +120,11 @@ void furi_hal_rfid_pins_read() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_rfid_pin_pull_release() {
|
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() {
|
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) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
furi_assert(usb.thread);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,17 +125,17 @@ bool furi_hal_usb_is_locked() {
|
|||||||
|
|
||||||
void furi_hal_usb_disable() {
|
void furi_hal_usb_disable() {
|
||||||
furi_assert(usb.thread);
|
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() {
|
void furi_hal_usb_enable() {
|
||||||
furi_assert(usb.thread);
|
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() {
|
void furi_hal_usb_reinit() {
|
||||||
furi_assert(usb.thread);
|
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 */
|
/* Get device / configuration descriptors */
|
||||||
@ -148,7 +148,7 @@ static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_
|
|||||||
|
|
||||||
switch(dtype) {
|
switch(dtype) {
|
||||||
case USB_DTYPE_DEVICE:
|
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) {
|
if(usb.callback != NULL) {
|
||||||
usb.callback(FuriHalUsbStateEventDescriptorRequest, usb.cb_ctx);
|
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(dev);
|
||||||
UNUSED(event);
|
UNUSED(event);
|
||||||
UNUSED(ep);
|
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) {
|
if(usb.callback != NULL) {
|
||||||
usb.callback(FuriHalUsbStateEventReset, usb.cb_ctx);
|
usb.callback(FuriHalUsbStateEventReset, usb.cb_ctx);
|
||||||
}
|
}
|
||||||
@ -236,11 +236,11 @@ static int32_t furi_hal_usb_thread(void* context) {
|
|||||||
FuriHalUsbInterface* if_ctx_new = NULL;
|
FuriHalUsbInterface* if_ctx_new = NULL;
|
||||||
|
|
||||||
if(usb.if_next != 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) {
|
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 & osFlagsError) == 0) {
|
||||||
if(flags & EventModeChange) {
|
if(flags & EventModeChange) {
|
||||||
if(usb.if_next != usb.if_cur) {
|
if(usb.if_next != usb.if_cur) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -61,8 +61,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <furi/base.h>
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
@ -89,77 +88,6 @@ typedef enum {
|
|||||||
osKernelReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
|
osKernelReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
|
||||||
} osKernelState_t;
|
} 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.
|
/// Timer callback function.
|
||||||
typedef void (*osTimerFunc_t) (void *argument);
|
typedef void (*osTimerFunc_t) (void *argument);
|
||||||
|
|
||||||
@ -169,62 +97,10 @@ typedef enum {
|
|||||||
osTimerPeriodic = 1 ///< Repeating timer.
|
osTimerPeriodic = 1 ///< Repeating timer.
|
||||||
} osTimerType_t;
|
} 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.
|
/// \details Timer ID identifies the timer.
|
||||||
typedef void *osTimerId_t;
|
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.
|
/// \details Message Queue ID identifies the message queue.
|
||||||
typedef void *osMessageQueueId_t;
|
typedef void *osMessageQueueId_t;
|
||||||
|
|
||||||
@ -236,19 +112,6 @@ typedef uint32_t TZ_ModuleId_t;
|
|||||||
#endif
|
#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.
|
/// Attributes structure for timer.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *name; ///< name of the timer
|
const char *name; ///< name of the timer
|
||||||
@ -257,40 +120,6 @@ typedef struct {
|
|||||||
uint32_t cb_size; ///< size of provided memory for control block
|
uint32_t cb_size; ///< size of provided memory for control block
|
||||||
} osTimerAttr_t;
|
} 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.
|
/// Attributes structure for message queue.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *name; ///< name of the message queue
|
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.
|
/// \return frequency of the kernel tick in hertz, i.e. kernel ticks per second.
|
||||||
uint32_t osKernelGetTickFreq (void);
|
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.
|
/// Get the RTOS kernel system timer frequency.
|
||||||
/// \return frequency of the system timer in hertz, i.e. timer ticks per second.
|
/// \return frequency of the system timer in hertz, i.e. timer ticks per second.
|
||||||
uint32_t osKernelGetSysTimerFreq (void);
|
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 ====
|
// ==== Generic Wait Functions ====
|
||||||
|
|
||||||
/// Wait for Timeout (Time Delay).
|
/// 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.
|
/// \return status code that indicates the execution status of the function.
|
||||||
osStatus_t osTimerDelete (osTimerId_t timer_id);
|
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 ====
|
// ==== Message Queue Management Functions ====
|
||||||
|
|
||||||
/// Create and Initialize a Message Queue object.
|
/// 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
|
#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
|
#ifndef configUSE_OS2_THREAD_ENUMERATE
|
||||||
#define configUSE_OS2_THREAD_ENUMERATE 1
|
#define configUSE_OS2_THREAD_ENUMERATE 1
|
||||||
@ -153,7 +153,7 @@
|
|||||||
#if (INCLUDE_xTaskGetCurrentTaskHandle == 0)
|
#if (INCLUDE_xTaskGetCurrentTaskHandle == 0)
|
||||||
/*
|
/*
|
||||||
CMSIS-RTOS2 API uses FreeRTOS function xTaskGetCurrentTaskHandle to implement
|
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.
|
functions are not used in the application image, compiler will optimize them away.
|
||||||
Set #define INCLUDE_xTaskGetCurrentTaskHandle 1 to fix this error.
|
Set #define INCLUDE_xTaskGetCurrentTaskHandle 1 to fix this error.
|
||||||
*/
|
*/
|
||||||
@ -170,8 +170,8 @@
|
|||||||
#endif
|
#endif
|
||||||
#if (INCLUDE_uxTaskGetStackHighWaterMark == 0)
|
#if (INCLUDE_uxTaskGetStackHighWaterMark == 0)
|
||||||
/*
|
/*
|
||||||
CMSIS-RTOS2 function osThreadGetStackSpace uses FreeRTOS function uxTaskGetStackHighWaterMark.
|
CMSIS-RTOS2 function furi_thread_get_stack_space uses FreeRTOS function uxTaskGetStackHighWaterMark.
|
||||||
In case if osThreadGetStackSpace is not used in the application image, compiler will
|
In case if furi_thread_get_stack_space is not used in the application image, compiler will
|
||||||
optimize it away.
|
optimize it away.
|
||||||
Set #define INCLUDE_uxTaskGetStackHighWaterMark 1 to fix this error.
|
Set #define INCLUDE_uxTaskGetStackHighWaterMark 1 to fix this error.
|
||||||
*/
|
*/
|
||||||
@ -294,16 +294,16 @@
|
|||||||
|
|
||||||
#if (configUSE_TRACE_FACILITY == 0)
|
#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.
|
which is only enabled if configUSE_TRACE_FACILITY == 1.
|
||||||
Set #define configUSE_TRACE_FACILITY 1 to fix this error.
|
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:
|
excluded from the image code by setting:
|
||||||
#define configUSE_OS2_THREAD_ENUMERATE 0 (in FreeRTOSConfig.h)
|
#define configUSE_OS2_THREAD_ENUMERATE 0 (in FreeRTOSConfig.h)
|
||||||
*/
|
*/
|
||||||
#if (configUSE_OS2_THREAD_ENUMERATE == 1)
|
#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
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -316,21 +316,4 @@
|
|||||||
#error "Definition configUSE_16_BIT_TICKS must be zero to implement CMSIS-RTOS2 API."
|
#error "Definition configUSE_16_BIT_TICKS must be zero to implement CMSIS-RTOS2 API."
|
||||||
#endif
|
#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_ */
|
#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.h>
|
||||||
#include <furi_hal_spi.h>
|
#include <furi_hal_spi.h>
|
||||||
|
|
||||||
static const osThreadAttr_t platform_irq_thread_attr = {
|
typedef struct {
|
||||||
.name = "RfalIrqDriver",
|
FuriThread* thread;
|
||||||
.stack_size = 1024,
|
volatile PlatformIrqCallback callback;
|
||||||
.priority = osPriorityRealtime,
|
} RfalPlatform;
|
||||||
};
|
|
||||||
|
|
||||||
static volatile osThreadId_t platform_irq_thread_id = NULL;
|
static volatile RfalPlatform rfal_platform = {
|
||||||
static volatile PlatformIrqCallback platform_irq_callback = NULL;
|
.thread = NULL,
|
||||||
static const GpioPin pin = {ST25R_INT_PORT, ST25R_INT_PIN};
|
.callback = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
void nfc_isr(void* _ctx) {
|
void nfc_isr(void* _ctx) {
|
||||||
UNUSED(_ctx);
|
UNUSED(_ctx);
|
||||||
if(platform_irq_callback && platformGpioIsHigh(ST25R_INT_PORT, ST25R_INT_PIN)) {
|
if(rfal_platform.callback && platformGpioIsHigh(ST25R_INT_PORT, ST25R_INT_PIN)) {
|
||||||
osThreadFlagsSet(platform_irq_thread_id, 0x1);
|
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) {
|
while(1) {
|
||||||
uint32_t flags = osThreadFlagsWait(0x1, osFlagsWaitAny, osWaitForever);
|
uint32_t flags = furi_thread_flags_wait(0x1, osFlagsWaitAny, osWaitForever);
|
||||||
if(flags & 0x1) {
|
if(flags & 0x1) {
|
||||||
platform_irq_callback();
|
rfal_platform.callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void platformEnableIrqCallback() {
|
void platformEnableIrqCallback() {
|
||||||
furi_hal_gpio_init(&pin, GpioModeInterruptRise, GpioPullDown, GpioSpeedLow);
|
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInterruptRise, GpioPullDown, GpioSpeedLow);
|
||||||
furi_hal_gpio_enable_int_callback(&pin);
|
furi_hal_gpio_enable_int_callback(&gpio_nfc_irq_rfid_pull);
|
||||||
}
|
}
|
||||||
|
|
||||||
void platformDisableIrqCallback() {
|
void platformDisableIrqCallback() {
|
||||||
furi_hal_gpio_init(&pin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
|
||||||
furi_hal_gpio_disable_int_callback(&pin);
|
furi_hal_gpio_disable_int_callback(&gpio_nfc_irq_rfid_pull);
|
||||||
}
|
}
|
||||||
|
|
||||||
void platformSetIrqCallback(PlatformIrqCallback callback) {
|
void platformSetIrqCallback(PlatformIrqCallback callback) {
|
||||||
platform_irq_callback = callback;
|
rfal_platform.callback = callback;
|
||||||
platform_irq_thread_id = osThreadNew(platformIrqThread, NULL, &platform_irq_thread_attr);
|
rfal_platform.thread = furi_thread_alloc();
|
||||||
furi_hal_gpio_add_int_callback(&pin, nfc_isr, NULL);
|
|
||||||
|
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
|
// Disable interrupt callback as the pin is shared between 2 apps
|
||||||
// It is enabled in rfalLowPowerModeStop()
|
// 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) {
|
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) {
|
static void infrared_worker_rx_timeout_callback(void* context) {
|
||||||
InfraredWorker* instance = context;
|
InfraredWorker* instance = context;
|
||||||
uint32_t flags_set = osThreadFlagsSet(
|
uint32_t flags_set = furi_thread_flags_set(
|
||||||
furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_RX_TIMEOUT_RECEIVED);
|
furi_thread_get_id(instance->thread), INFRARED_WORKER_RX_TIMEOUT_RECEIVED);
|
||||||
furi_check(flags_set & 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;
|
INFRARED_WORKER_OVERRUN;
|
||||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
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);
|
furi_check(flags_set & events);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,8 +152,8 @@ static void
|
|||||||
instance->signal.timings[instance->signal.timings_cnt] = duration;
|
instance->signal.timings[instance->signal.timings_cnt] = duration;
|
||||||
++instance->signal.timings_cnt;
|
++instance->signal.timings_cnt;
|
||||||
} else {
|
} else {
|
||||||
uint32_t flags_set = osThreadFlagsSet(
|
uint32_t flags_set = furi_thread_flags_set(
|
||||||
furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_OVERRUN);
|
furi_thread_get_id(instance->thread), INFRARED_WORKER_OVERRUN);
|
||||||
furi_check(flags_set & INFRARED_WORKER_OVERRUN);
|
furi_check(flags_set & INFRARED_WORKER_OVERRUN);
|
||||||
instance->rx.overrun = true;
|
instance->rx.overrun = true;
|
||||||
}
|
}
|
||||||
@ -167,7 +167,7 @@ static int32_t infrared_worker_rx_thread(void* thread_context) {
|
|||||||
TickType_t last_blink_time = 0;
|
TickType_t last_blink_time = 0;
|
||||||
|
|
||||||
while(1) {
|
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 */
|
furi_check(events & INFRARED_WORKER_ALL_RX_EVENTS); /* at least one caught */
|
||||||
|
|
||||||
if(events & INFRARED_WORKER_RX_RECEIVED) {
|
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_set_capture_isr_callback(NULL, NULL);
|
||||||
furi_hal_infrared_async_rx_stop();
|
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);
|
furi_thread_join(instance->thread);
|
||||||
|
|
||||||
BaseType_t xReturn = xStreamBufferReset(instance->stream);
|
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) {
|
static void infrared_worker_furi_hal_message_sent_isr_callback(void* context) {
|
||||||
InfraredWorker* instance = context;
|
InfraredWorker* instance = context;
|
||||||
uint32_t flags_set = osThreadFlagsSet(
|
uint32_t flags_set = furi_thread_flags_set(
|
||||||
furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_TX_MESSAGE_SENT);
|
furi_thread_get_id(instance->thread), INFRARED_WORKER_TX_MESSAGE_SENT);
|
||||||
furi_check(flags_set & INFRARED_WORKER_TX_MESSAGE_SENT);
|
furi_check(flags_set & INFRARED_WORKER_TX_MESSAGE_SENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,8 +369,8 @@ static FuriHalInfraredTxGetDataState
|
|||||||
state = FuriHalInfraredTxGetDataStateDone;
|
state = FuriHalInfraredTxGetDataStateDone;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t flags_set = osThreadFlagsSet(
|
uint32_t flags_set = furi_thread_flags_set(
|
||||||
furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_TX_FILL_BUFFER);
|
furi_thread_get_id(instance->thread), INFRARED_WORKER_TX_FILL_BUFFER);
|
||||||
furi_check(flags_set & INFRARED_WORKER_TX_FILL_BUFFER);
|
furi_check(flags_set & INFRARED_WORKER_TX_FILL_BUFFER);
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
@ -498,7 +498,7 @@ static int32_t infrared_worker_tx_thread(void* thread_context) {
|
|||||||
furi_hal_infrared_async_tx_wait_termination();
|
furi_hal_infrared_async_tx_wait_termination();
|
||||||
instance->state = InfraredWorkerStateStartTx;
|
instance->state = InfraredWorkerStateStartTx;
|
||||||
|
|
||||||
events = osThreadFlagsGet();
|
events = furi_thread_flags_get();
|
||||||
if(events & INFRARED_WORKER_EXIT) {
|
if(events & INFRARED_WORKER_EXIT) {
|
||||||
exit = true;
|
exit = true;
|
||||||
break;
|
break;
|
||||||
@ -506,7 +506,7 @@ static int32_t infrared_worker_tx_thread(void* thread_context) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case InfraredWorkerStateRunTx:
|
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 */
|
furi_check(events & INFRARED_WORKER_ALL_TX_EVENTS); /* at least one caught */
|
||||||
|
|
||||||
if(events & INFRARED_WORKER_EXIT) {
|
if(events & INFRARED_WORKER_EXIT) {
|
||||||
@ -558,7 +558,7 @@ void infrared_worker_tx_stop(InfraredWorker* instance) {
|
|||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
furi_assert(instance->state != InfraredWorkerStateRunRx);
|
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_thread_join(instance->thread);
|
||||||
furi_hal_infrared_async_tx_set_data_isr_callback(NULL, NULL);
|
furi_hal_infrared_async_tx_set_data_isr_callback(NULL, NULL);
|
||||||
furi_hal_infrared_async_tx_set_signal_sent_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);
|
xStreamBufferReset(instance->stream);
|
||||||
string_set(instance->file_path, file_path);
|
string_set(instance->file_path, file_path);
|
||||||
instance->worker_running = true;
|
instance->worker_running = true;
|
||||||
bool res = furi_thread_start(instance->thread);
|
furi_thread_start(instance->thread);
|
||||||
return res;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_file_encoder_worker_stop(SubGhzFileEncoderWorker* instance) {
|
void subghz_file_encoder_worker_stop(SubGhzFileEncoderWorker* instance) {
|
||||||
|
Loading…
Reference in New Issue
Block a user