Furi: make furi_is_irq_context public (#2276)

* Furi: make `furi_is_irq_context` public
* Furi: proper name and documentation for furi_kernel_is_irq_or_masked.
* Target: bump symbol table version
* Furi: proper doxygen context for warnings

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
Petr Portnov | PROgrm_JARvis 2023-01-29 13:12:24 +03:00 committed by GitHub
parent d93ed003fe
commit f5fe0ff694
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 74 additions and 47 deletions

View File

@ -1389,6 +1389,7 @@ Function,+,furi_hal_version_uid_size,size_t,
Function,-,furi_hal_vibro_init,void,
Function,+,furi_hal_vibro_on,void,_Bool
Function,-,furi_init,void,
Function,+,furi_kernel_is_irq_or_masked,_Bool,
Function,+,furi_kernel_get_tick_frequency,uint32_t,
Function,+,furi_kernel_lock,int32_t,
Function,+,furi_kernel_restore_lock,int32_t,int32_t

1 entry status name type params
1389 Function - furi_hal_vibro_init void
1390 Function + furi_hal_vibro_on void _Bool
1391 Function - furi_init void
1392 Function + furi_kernel_is_irq_or_masked _Bool
1393 Function + furi_kernel_get_tick_frequency uint32_t
1394 Function + furi_kernel_lock int32_t
1395 Function + furi_kernel_restore_lock int32_t int32_t

View File

@ -52,30 +52,6 @@ extern "C" {
}
#endif
static inline bool furi_is_irq_context() {
bool irq = false;
BaseType_t state;
if(FURI_IS_IRQ_MODE()) {
/* Called from interrupt context */
irq = true;
} else {
/* Get FreeRTOS scheduler state */
state = xTaskGetSchedulerState();
if(state != taskSCHEDULER_NOT_STARTED) {
/* Scheduler was started */
if(FURI_IS_IRQ_MASKED()) {
/* Interrupts are masked */
irq = true;
}
}
}
/* Return context, 0: thread context, 1: IRQ context */
return (irq);
}
#ifdef __cplusplus
}
#endif

View File

@ -7,8 +7,32 @@
#include CMSIS_device_header
bool furi_kernel_is_irq_or_masked() {
bool irq = false;
BaseType_t state;
if(FURI_IS_IRQ_MODE()) {
/* Called from interrupt context */
irq = true;
} else {
/* Get FreeRTOS scheduler state */
state = xTaskGetSchedulerState();
if(state != taskSCHEDULER_NOT_STARTED) {
/* Scheduler was started */
if(FURI_IS_IRQ_MASKED()) {
/* Interrupts are masked */
irq = true;
}
}
}
/* Return context, 0: thread context, 1: IRQ context */
return (irq);
}
int32_t furi_kernel_lock() {
furi_assert(!furi_is_irq_context());
furi_assert(!furi_kernel_is_irq_or_masked());
int32_t lock;
@ -33,7 +57,7 @@ int32_t furi_kernel_lock() {
}
int32_t furi_kernel_unlock() {
furi_assert(!furi_is_irq_context());
furi_assert(!furi_kernel_is_irq_or_masked());
int32_t lock;
@ -63,7 +87,7 @@ int32_t furi_kernel_unlock() {
}
int32_t furi_kernel_restore_lock(int32_t lock) {
furi_assert(!furi_is_irq_context());
furi_assert(!furi_kernel_is_irq_or_masked());
switch(xTaskGetSchedulerState()) {
case taskSCHEDULER_SUSPENDED:
@ -99,7 +123,7 @@ uint32_t furi_kernel_get_tick_frequency() {
}
void furi_delay_tick(uint32_t ticks) {
furi_assert(!furi_is_irq_context());
furi_assert(!furi_kernel_is_irq_or_masked());
if(ticks == 0U) {
taskYIELD();
} else {
@ -108,7 +132,7 @@ void furi_delay_tick(uint32_t ticks) {
}
FuriStatus furi_delay_until_tick(uint32_t tick) {
furi_assert(!furi_is_irq_context());
furi_assert(!furi_kernel_is_irq_or_masked());
TickType_t tcnt, delay;
FuriStatus stat;
@ -137,7 +161,7 @@ FuriStatus furi_delay_until_tick(uint32_t tick) {
uint32_t furi_get_tick() {
TickType_t ticks;
if(furi_is_irq_context() != 0U) {
if(furi_kernel_is_irq_or_masked() != 0U) {
ticks = xTaskGetTickCountFromISR();
} else {
ticks = xTaskGetTickCount();

View File

@ -10,19 +10,42 @@
extern "C" {
#endif
/** Check if CPU is in IRQ or kernel running and IRQ is masked
*
* Originally this primitive was born as a workaround for FreeRTOS kernel primitives shenanigans with PRIMASK.
*
* Meaningful use cases are:
*
* - When kernel is started and you want to ensure that you are not in IRQ or IRQ is not masked(like in critical section)
* - When kernel is not started and you want to make sure that you are not in IRQ mode, ignoring PRIMASK.
*
* As you can see there will be edge case when kernel is not started and PRIMASK is not 0 that may cause some funky behavior.
* Most likely it will happen after kernel primitives being used, but control not yet passed to kernel.
* It's up to you to figure out if it is safe for your code or not.
*
* @return true if CPU is in IRQ or kernel running and IRQ is masked
*/
bool furi_kernel_is_irq_or_masked();
/** Lock kernel, pause process scheduling
*
* @warning This should never be called in interrupt request context.
*
* @return previous lock state(0 - unlocked, 1 - locked)
*/
int32_t furi_kernel_lock();
/** Unlock kernel, resume process scheduling
*
* @warning This should never be called in interrupt request context.
*
* @return previous lock state(0 - unlocked, 1 - locked)
*/
int32_t furi_kernel_unlock();
/** Restore kernel lock state
*
* @warning This should never be called in interrupt request context.
*
* @param[in] lock The lock state
*
@ -37,7 +60,9 @@ int32_t furi_kernel_restore_lock(int32_t lock);
uint32_t furi_kernel_get_tick_frequency();
/** Delay execution
*
*
* @warning This should never be called in interrupt request context.
*
* Also keep in mind delay is aliased to scheduler timer intervals.
*
* @param[in] ticks The ticks count to pause
@ -45,6 +70,8 @@ uint32_t furi_kernel_get_tick_frequency();
void furi_delay_tick(uint32_t ticks);
/** Delay until tick
*
* @warning This should never be called in interrupt request context.
*
* @param[in] ticks The tick until which kerel should delay task execution
*

View File

@ -1,11 +1,11 @@
#include "kernel.h"
#include "message_queue.h"
#include "core/common_defines.h"
#include <FreeRTOS.h>
#include <queue.h>
#include "check.h"
FuriMessageQueue* furi_message_queue_alloc(uint32_t msg_count, uint32_t msg_size) {
furi_assert((furi_is_irq_context() == 0U) && (msg_count > 0U) && (msg_size > 0U));
furi_assert((furi_kernel_is_irq_or_masked() == 0U) && (msg_count > 0U) && (msg_size > 0U));
QueueHandle_t handle = xQueueCreate(msg_count, msg_size);
furi_check(handle);
@ -14,7 +14,7 @@ FuriMessageQueue* furi_message_queue_alloc(uint32_t msg_count, uint32_t msg_size
}
void furi_message_queue_free(FuriMessageQueue* instance) {
furi_assert(furi_is_irq_context() == 0U);
furi_assert(furi_kernel_is_irq_or_masked() == 0U);
furi_assert(instance);
vQueueDelete((QueueHandle_t)instance);
@ -28,7 +28,7 @@ FuriStatus
stat = FuriStatusOk;
if(furi_is_irq_context() != 0U) {
if(furi_kernel_is_irq_or_masked() != 0U) {
if((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) {
stat = FuriStatusErrorParameter;
} else {
@ -65,7 +65,7 @@ FuriStatus furi_message_queue_get(FuriMessageQueue* instance, void* msg_ptr, uin
stat = FuriStatusOk;
if(furi_is_irq_context() != 0U) {
if(furi_kernel_is_irq_or_masked() != 0U) {
if((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) {
stat = FuriStatusErrorParameter;
} else {
@ -131,7 +131,7 @@ uint32_t furi_message_queue_get_count(FuriMessageQueue* instance) {
if(hQueue == NULL) {
count = 0U;
} else if(furi_is_irq_context() != 0U) {
} else if(furi_kernel_is_irq_or_masked() != 0U) {
count = uxQueueMessagesWaitingFromISR(hQueue);
} else {
count = uxQueueMessagesWaiting(hQueue);
@ -148,7 +148,7 @@ uint32_t furi_message_queue_get_space(FuriMessageQueue* instance) {
if(mq == NULL) {
space = 0U;
} else if(furi_is_irq_context() != 0U) {
} else if(furi_kernel_is_irq_or_masked() != 0U) {
isrm = taskENTER_CRITICAL_FROM_ISR();
/* space = pxQueue->uxLength - pxQueue->uxMessagesWaiting; */
@ -167,7 +167,7 @@ FuriStatus furi_message_queue_reset(FuriMessageQueue* instance) {
QueueHandle_t hQueue = (QueueHandle_t)instance;
FuriStatus stat;
if(furi_is_irq_context() != 0U) {
if(furi_kernel_is_irq_or_masked() != 0U) {
stat = FuriStatusErrorISR;
} else if(hQueue == NULL) {
stat = FuriStatusErrorParameter;

View File

@ -3,7 +3,6 @@
#include "memmgr.h"
#include "kernel.h"
#include "core/common_defines.h"
#include <FreeRTOS.h>
#include <timers.h>
@ -27,7 +26,7 @@ static void TimerCallback(TimerHandle_t hTimer) {
}
FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* context) {
furi_assert((furi_is_irq_context() == 0U) && (func != NULL));
furi_assert((furi_kernel_is_irq_or_masked() == 0U) && (func != NULL));
TimerHandle_t hTimer;
TimerCallback_t* callb;
@ -60,7 +59,7 @@ FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* co
}
void furi_timer_free(FuriTimer* instance) {
furi_assert(!furi_is_irq_context());
furi_assert(!furi_kernel_is_irq_or_masked());
furi_assert(instance);
TimerHandle_t hTimer = (TimerHandle_t)instance;
@ -82,7 +81,7 @@ void furi_timer_free(FuriTimer* instance) {
}
FuriStatus furi_timer_start(FuriTimer* instance, uint32_t ticks) {
furi_assert(!furi_is_irq_context());
furi_assert(!furi_kernel_is_irq_or_masked());
furi_assert(instance);
TimerHandle_t hTimer = (TimerHandle_t)instance;
@ -99,7 +98,7 @@ FuriStatus furi_timer_start(FuriTimer* instance, uint32_t ticks) {
}
FuriStatus furi_timer_stop(FuriTimer* instance) {
furi_assert(!furi_is_irq_context());
furi_assert(!furi_kernel_is_irq_or_masked());
furi_assert(instance);
TimerHandle_t hTimer = (TimerHandle_t)instance;
@ -117,7 +116,7 @@ FuriStatus furi_timer_stop(FuriTimer* instance) {
}
uint32_t furi_timer_is_running(FuriTimer* instance) {
furi_assert(!furi_is_irq_context());
furi_assert(!furi_kernel_is_irq_or_masked());
furi_assert(instance);
TimerHandle_t hTimer = (TimerHandle_t)instance;

View File

@ -3,7 +3,7 @@
#include "queue.h"
void furi_init() {
furi_assert(!furi_is_irq_context());
furi_assert(!furi_kernel_is_irq_or_masked());
furi_assert(xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED);
furi_log_init();
@ -11,7 +11,7 @@ void furi_init() {
}
void furi_run() {
furi_assert(!furi_is_irq_context());
furi_assert(!furi_kernel_is_irq_or_masked());
furi_assert(xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED);
#if(__ARM_ARCH_7A__ == 0U)