VA Fixes: USB IRQ Handling and EP configuration, Thread handler shenanigans. (#3705)

* FuriHal: properly handle high priority USB IRQ, change CDC decriptor to use separate TX/RX endpoints
* Furi: drop task handle, cleanup casts and memory corrupt in threads
* FuriHal: update max power in USB descriptors
* Furi: properly handle thread free if thread was not started
* Furi crash: meaningful interrupt name instead of id

---------

Co-authored-by: SG <who.just.the.doctor@gmail.com>
This commit is contained in:
あく 2024-06-12 16:07:29 +01:00 committed by GitHub
parent 798e0c3e78
commit 70d2453bbc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 207 additions and 31 deletions

View File

@ -6,6 +6,7 @@
#include <furi_hal_rtc.h>
#include <furi_hal_debug.h>
#include <furi_hal_bt.h>
#include <furi_hal_interrupt.h>
#include <stdio.h>
#include <FreeRTOS.h>
@ -110,8 +111,14 @@ static void __furi_print_heap_info(void) {
static void __furi_print_name(bool isr) {
if(isr) {
uint8_t exception_number = __get_IPSR();
const char* name = furi_hal_interrupt_get_name(exception_number);
furi_log_puts("[ISR ");
__furi_put_uint32_as_text(__get_IPSR());
if(name) {
furi_log_puts(name);
} else {
__furi_put_uint32_as_text(__get_IPSR());
}
furi_log_puts("] ");
} else {
const char* name = pcTaskGetName(NULL);

View File

@ -28,7 +28,6 @@ struct FuriThreadStdout {
struct FuriThread {
StaticTask_t container;
TaskHandle_t task_handle;
StackType_t* stack_buffer;
FuriThreadState state;
@ -54,6 +53,7 @@ struct FuriThread {
// this ensures that the size of this structure is minimal
bool is_service;
bool heap_trace_enabled;
volatile bool is_active;
};
// IMPORTANT: container MUST be the FIRST struct member
@ -90,9 +90,8 @@ static void furi_thread_body(void* context) {
furi_check(thread->state == FuriThreadStateStarting);
furi_thread_set_state(thread, FuriThreadStateRunning);
TaskHandle_t task_handle = xTaskGetCurrentTaskHandle();
if(thread->heap_trace_enabled == true) {
memmgr_heap_enable_thread_trace((FuriThreadId)task_handle);
memmgr_heap_enable_thread_trace(thread);
}
thread->ret = thread->callback(thread->context);
@ -101,14 +100,14 @@ static void furi_thread_body(void* context) {
if(thread->heap_trace_enabled == true) {
furi_delay_ms(33);
thread->heap_size = memmgr_heap_get_thread_memory((FuriThreadId)task_handle);
thread->heap_size = memmgr_heap_get_thread_memory(thread);
furi_log_print_format(
thread->heap_size ? FuriLogLevelError : FuriLogLevelInfo,
TAG,
"%s allocation balance: %zu",
thread->name ? thread->name : "Thread",
thread->heap_size);
memmgr_heap_disable_thread_trace((FuriThreadId)task_handle);
memmgr_heap_disable_thread_trace(thread);
}
furi_check(thread->state == FuriThreadStateRunning);
@ -197,7 +196,7 @@ void furi_thread_free(FuriThread* thread) {
furi_check(thread->is_service == false);
// Cannot free a non-joined thread
furi_check(thread->state == FuriThreadStateStopped);
furi_check(thread->task_handle == NULL);
furi_check(!thread->is_active);
furi_thread_set_name(thread, NULL);
furi_thread_set_appid(thread, NULL);
@ -313,16 +312,17 @@ void furi_thread_start(FuriThread* thread) {
uint32_t stack_depth = thread->stack_size / sizeof(StackType_t);
UBaseType_t priority = thread->priority ? thread->priority : FuriThreadPriorityNormal;
thread->task_handle = xTaskCreateStatic(
furi_thread_body,
thread->name,
stack_depth,
thread,
priority,
thread->stack_buffer,
&thread->container);
thread->is_active = true;
furi_check(thread->task_handle == (TaskHandle_t)&thread->container);
furi_check(
xTaskCreateStatic(
furi_thread_body,
thread->name,
stack_depth,
thread,
priority,
thread->stack_buffer,
&thread->container) == (TaskHandle_t)thread);
}
void furi_thread_cleanup_tcb_event(TaskHandle_t task) {
@ -330,8 +330,8 @@ void furi_thread_cleanup_tcb_event(TaskHandle_t task) {
if(thread) {
// clear thread local storage
vTaskSetThreadLocalStoragePointer(task, 0, NULL);
furi_check(thread->task_handle == task);
thread->task_handle = NULL;
furi_check(thread == (FuriThread*)task);
thread->is_active = false;
}
}
@ -346,7 +346,7 @@ bool furi_thread_join(FuriThread* thread) {
//
// If your thread exited, but your app stuck here: some other thread uses
// all cpu time, which delays kernel from releasing task handle
while(thread->task_handle) {
while(thread->is_active) {
furi_delay_ms(10);
}
@ -355,7 +355,7 @@ bool furi_thread_join(FuriThread* thread) {
FuriThreadId furi_thread_get_id(FuriThread* thread) {
furi_check(thread);
return thread->task_handle;
return thread;
}
void furi_thread_enable_heap_trace(FuriThread* thread) {

View File

@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,64.2,,
Version,+,64.3,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
Header,+,applications/services/cli/cli.h,,
@ -1271,6 +1271,7 @@ Function,+,furi_hal_info_get,void,"PropertyValueCallback, char, void*"
Function,+,furi_hal_info_get_api_version,void,"uint16_t*, uint16_t*"
Function,-,furi_hal_init,void,
Function,-,furi_hal_init_early,void,
Function,+,furi_hal_interrupt_get_name,const char*,uint8_t
Function,-,furi_hal_interrupt_init,void,
Function,+,furi_hal_interrupt_set_isr,void,"FuriHalInterruptId, FuriHalInterruptISR, void*"
Function,+,furi_hal_interrupt_set_isr_ex,void,"FuriHalInterruptId, FuriHalInterruptPriority, FuriHalInterruptISR, void*"

1 entry status name type params
2 Version + 64.2 64.3
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/bt/bt_service/bt_keys_storage.h
5 Header + applications/services/cli/cli.h
1271 Function + furi_hal_info_get_api_version void uint16_t*, uint16_t*
1272 Function - furi_hal_init void
1273 Function - furi_hal_init_early void
1274 Function + furi_hal_interrupt_get_name const char* uint8_t
1275 Function - furi_hal_interrupt_init void
1276 Function + furi_hal_interrupt_set_isr void FuriHalInterruptId, FuriHalInterruptISR, void*
1277 Function + furi_hal_interrupt_set_isr_ex void FuriHalInterruptId, FuriHalInterruptPriority, FuriHalInterruptISR, void*

View File

@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,64.2,,
Version,+,64.3,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
@ -1396,6 +1396,7 @@ Function,+,furi_hal_infrared_is_busy,_Bool,
Function,+,furi_hal_infrared_set_tx_output,void,FuriHalInfraredTxPin
Function,-,furi_hal_init,void,
Function,-,furi_hal_init_early,void,
Function,+,furi_hal_interrupt_get_name,const char*,uint8_t
Function,-,furi_hal_interrupt_init,void,
Function,+,furi_hal_interrupt_set_isr,void,"FuriHalInterruptId, FuriHalInterruptISR, void*"
Function,+,furi_hal_interrupt_set_isr_ex,void,"FuriHalInterruptId, FuriHalInterruptPriority, FuriHalInterruptISR, void*"

1 entry status name type params
2 Version + 64.2 64.3
3 Header + applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h
4 Header + applications/services/bt/bt_service/bt.h
5 Header + applications/services/bt/bt_service/bt_keys_storage.h
1396 Function + furi_hal_infrared_set_tx_output void FuriHalInfraredTxPin
1397 Function - furi_hal_init void
1398 Function - furi_hal_init_early void
1399 Function + furi_hal_interrupt_get_name const char* uint8_t
1400 Function - furi_hal_interrupt_init void
1401 Function + furi_hal_interrupt_set_isr void FuriHalInterruptId, FuriHalInterruptISR, void*
1402 Function + furi_hal_interrupt_set_isr_ex void FuriHalInterruptId, FuriHalInterruptPriority, FuriHalInterruptISR, void*

View File

@ -313,6 +313,12 @@ void USB_LP_IRQHandler(void) {
#endif
}
void USB_HP_IRQHandler(void) { //-V524
#ifndef FURI_RAM_EXEC
usbd_poll(&udev);
#endif
}
void IPCC_C1_TX_IRQHandler(void) {
HW_IPCC_Tx_Handler();
}
@ -340,3 +346,156 @@ void USART1_IRQHandler(void) {
void LPUART1_IRQHandler(void) {
furi_hal_interrupt_call(FuriHalInterruptIdLpUart1);
}
const char* furi_hal_interrupt_get_name(uint8_t exception_number) {
int32_t id = (int32_t)exception_number - 16;
switch(id) {
case -14:
return "NMI";
case -13:
return "HardFault";
case -12:
return "MemMgmt";
case -11:
return "BusFault";
case -10:
return "UsageFault";
case -5:
return "SVC";
case -4:
return "DebugMon";
case -2:
return "PendSV";
case -1:
return "SysTick";
case 0:
return "WWDG";
case 1:
return "PVD_PVM";
case 2:
return "TAMP";
case 3:
return "RTC_WKUP";
case 4:
return "FLASH";
case 5:
return "RCC";
case 6:
return "EXTI0";
case 7:
return "EXTI1";
case 8:
return "EXTI2";
case 9:
return "EXTI3";
case 10:
return "EXTI4";
case 11:
return "DMA1_Ch1";
case 12:
return "DMA1_Ch2";
case 13:
return "DMA1_Ch3";
case 14:
return "DMA1_Ch4";
case 15:
return "DMA1_Ch5";
case 16:
return "DMA1_Ch6";
case 17:
return "DMA1_Ch7";
case 18:
return "ADC1";
case 19:
return "USB_HP";
case 20:
return "USB_LP";
case 21:
return "C2SEV_PWR_C2H";
case 22:
return "COMP";
case 23:
return "EXTI9_5";
case 24:
return "TIM1_BRK";
case 25:
return "TIM1_UP_TIM16";
case 26:
return "TIM1_TRG_COM_TIM17";
case 27:
return "TIM1_CC";
case 28:
return "TIM2";
case 29:
return "PKA";
case 30:
return "I2C1_EV";
case 31:
return "I2C1_ER";
case 32:
return "I2C3_EV";
case 33:
return "I2C3_ER";
case 34:
return "SPI1";
case 35:
return "SPI2";
case 36:
return "USART1";
case 37:
return "LPUART1";
case 38:
return "SAI1";
case 39:
return "TSC";
case 40:
return "EXTI15_10";
case 41:
return "RTC_Alarm";
case 42:
return "CRS";
case 43:
return "PWR_SOTF_BLE";
case 44:
return "IPCC_C1_RX";
case 45:
return "IPCC_C1_TX";
case 46:
return "HSEM";
case 47:
return "LPTIM1";
case 48:
return "LPTIM2";
case 49:
return "LCD";
case 50:
return "QUADSPI";
case 51:
return "AES1";
case 52:
return "AES2";
case 53:
return "RNG";
case 54:
return "FPU";
case 55:
return "DMA2_Ch1";
case 56:
return "DMA2_Ch2";
case 57:
return "DMA2_Ch3";
case 58:
return "DMA2_Ch4";
case 59:
return "DMA2_Ch5";
case 60:
return "DMA2_Ch6";
case 61:
return "DMA2_Ch7";
case 62:
return "DMAMUX1_OVR";
default:
return NULL;
}
}

View File

@ -110,6 +110,14 @@ void furi_hal_interrupt_set_isr_ex(
FuriHalInterruptISR isr,
void* context);
/** Get interrupt name by exception number.
* Exception number can be obtained from IPSR register.
*
* @param exception_number
* @return const char* or NULL if interrupt name is not found
*/
const char* furi_hal_interrupt_get_name(uint8_t exception_number);
#ifdef __cplusplus
}
#endif

View File

@ -94,7 +94,7 @@ static const struct CcidConfigDescriptor ccid_cfg_desc = {
.bConfigurationValue = 1,
.iConfiguration = NO_DESCRIPTOR,
.bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
.bMaxPower = USB_CFG_POWER_MA(100),
.bMaxPower = USB_CFG_POWER_MA(500),
},
.intf_0 =
{

View File

@ -7,13 +7,13 @@
#include "usb.h"
#include "usb_cdc.h"
#define CDC0_RXD_EP 0x02
#define CDC0_RXD_EP 0x01
#define CDC0_TXD_EP 0x82
#define CDC0_NTF_EP 0x81
#define CDC0_NTF_EP 0x83
#define CDC1_RXD_EP 0x04
#define CDC1_TXD_EP 0x84
#define CDC1_NTF_EP 0x83
#define CDC1_TXD_EP 0x85
#define CDC1_NTF_EP 0x86
#define CDC_NTF_SZ 0x08
@ -75,7 +75,7 @@ static const struct CdcConfigDescriptorSingle cdc_cfg_desc_single = {
.bConfigurationValue = 1,
.iConfiguration = NO_DESCRIPTOR,
.bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
.bMaxPower = USB_CFG_POWER_MA(100),
.bMaxPower = USB_CFG_POWER_MA(500),
},
.iad_0 =
{
@ -188,7 +188,7 @@ static const struct CdcConfigDescriptorDual
.bConfigurationValue = 1,
.iConfiguration = NO_DESCRIPTOR,
.bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
.bMaxPower = USB_CFG_POWER_MA(100),
.bMaxPower = USB_CFG_POWER_MA(500),
},
.iad_0 =
{

View File

@ -155,7 +155,7 @@ static const struct HidConfigDescriptor hid_cfg_desc = {
.bConfigurationValue = 1,
.iConfiguration = NO_DESCRIPTOR,
.bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
.bMaxPower = USB_CFG_POWER_MA(100),
.bMaxPower = USB_CFG_POWER_MA(500),
},
.intf_0 =
{

View File

@ -79,7 +79,7 @@ static const struct HidConfigDescriptor hid_u2f_cfg_desc = {
.bConfigurationValue = 1,
.iConfiguration = NO_DESCRIPTOR,
.bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
.bMaxPower = USB_CFG_POWER_MA(100),
.bMaxPower = USB_CFG_POWER_MA(500),
},
.iad_0 =
{