[FL-2219, FL-2251] System, FuriCore, FuriHal: various bug fixes and improvements (#986)

* Replace irq shenanigans with critical section
* Power: halt system on power off instead of crash.
* Gui: properly handle input event on NULL current_view
* FuriHal: correct gpio configuration sequence
* FuriHal: cleanup uart initialization. Makefile: allow to disable thread support.
* Loader: improve locking, fix simultaneous app start crash, full command line args support for gui apps, more consistent insomnia
* Loader: correct spelling
* FuriHal: increase gpio configuration readability
* FuriHal: correct gpio configuration error when mode is GpioModeEventRiseFall
Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com>
This commit is contained in:
あく
2022-02-10 14:20:50 +03:00
committed by GitHub
parent 6b78a8ccfe
commit df2d1ad13f
35 changed files with 1145 additions and 1962 deletions

View File

@@ -68,25 +68,37 @@ void hal_gpio_init_ex(
uint32_t exti_line = GET_EXTI_LINE(gpio->pin);
// Configure gpio with interrupts disabled
__disable_irq();
FURI_CRITICAL_ENTER();
// Set gpio speed
if(speed == GpioSpeedLow) {
switch(speed) {
case GpioSpeedLow:
LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_LOW);
} else if(speed == GpioSpeedMedium) {
break;
case GpioSpeedMedium:
LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_MEDIUM);
} else if(speed == GpioSpeedHigh) {
break;
case GpioSpeedHigh:
LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_HIGH);
} else {
break;
case GpioSpeedVeryHigh:
LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_VERY_HIGH);
break;
}
// Set gpio pull mode
if(pull == GpioPullNo) {
switch(pull) {
case GpioPullNo:
LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_NO);
} else if(pull == GpioPullUp) {
break;
case GpioPullUp:
LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_UP);
} else {
break;
case GpioPullDown:
LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_DOWN);
break;
}
// Set gpio mode
if(mode >= GpioModeInterruptRise) {
// Set pin in interrupt mode
@@ -100,93 +112,106 @@ void hal_gpio_init_ex(
LL_EXTI_EnableIT_0_31(exti_line);
LL_EXTI_EnableFallingTrig_0_31(exti_line);
}
if(mode == GpioModeEventRise || mode == GpioModeInterruptRiseFall) {
if(mode == GpioModeEventRise || mode == GpioModeEventRiseFall) {
LL_EXTI_EnableEvent_0_31(exti_line);
LL_EXTI_EnableRisingTrig_0_31(exti_line);
}
if(mode == GpioModeEventFall || mode == GpioModeInterruptRiseFall) {
if(mode == GpioModeEventFall || mode == GpioModeEventRiseFall) {
LL_EXTI_EnableEvent_0_31(exti_line);
LL_EXTI_EnableFallingTrig_0_31(exti_line);
}
} else {
// Disable interrupt if it was set
// Disable interrupts if set
if(LL_SYSCFG_GetEXTISource(sys_exti_line) == sys_exti_port &&
LL_EXTI_IsEnabledIT_0_31(exti_line)) {
LL_EXTI_DisableIT_0_31(exti_line);
LL_EXTI_DisableRisingTrig_0_31(exti_line);
LL_EXTI_DisableFallingTrig_0_31(exti_line);
}
// Prepare alternative part if any
if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) {
// set alternate function
if(hal_gpio_get_pin_num(gpio) < 8) {
LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn);
} else {
LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn);
}
}
// Set not interrupt pin modes
if(mode == GpioModeInput) {
switch(mode) {
case GpioModeInput:
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT);
} else if(mode == GpioModeOutputPushPull || mode == GpioModeAltFunctionPushPull) {
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT);
break;
case GpioModeOutputPushPull:
LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL);
} else if(mode == GpioModeOutputOpenDrain || mode == GpioModeAltFunctionOpenDrain) {
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT);
break;
case GpioModeAltFunctionPushPull:
LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE);
break;
case GpioModeOutputOpenDrain:
LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN);
} else if(mode == GpioModeAnalog) {
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT);
break;
case GpioModeAltFunctionOpenDrain:
LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN);
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE);
break;
case GpioModeAnalog:
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ANALOG);
break;
default:
break;
}
}
if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) {
// enable alternate mode
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE);
// set alternate function
if(hal_gpio_get_pin_num(gpio) < 8) {
LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn);
} else {
LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn);
}
}
__enable_irq();
FURI_CRITICAL_EXIT();
}
void hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, void* ctx) {
furi_assert(gpio);
furi_assert(cb);
__disable_irq();
FURI_CRITICAL_ENTER();
uint8_t pin_num = hal_gpio_get_pin_num(gpio);
furi_assert(gpio_interrupt[pin_num].callback == NULL);
gpio_interrupt[pin_num].callback = cb;
gpio_interrupt[pin_num].context = ctx;
gpio_interrupt[pin_num].ready = true;
__enable_irq();
FURI_CRITICAL_EXIT();
}
void hal_gpio_enable_int_callback(const GpioPin* gpio) {
furi_assert(gpio);
__disable_irq();
FURI_CRITICAL_ENTER();
uint8_t pin_num = hal_gpio_get_pin_num(gpio);
if(gpio_interrupt[pin_num].callback) {
gpio_interrupt[pin_num].ready = true;
}
__enable_irq();
FURI_CRITICAL_EXIT();
}
void hal_gpio_disable_int_callback(const GpioPin* gpio) {
furi_assert(gpio);
__disable_irq();
FURI_CRITICAL_ENTER();
uint8_t pin_num = hal_gpio_get_pin_num(gpio);
gpio_interrupt[pin_num].ready = false;
__enable_irq();
FURI_CRITICAL_EXIT();
}
void hal_gpio_remove_int_callback(const GpioPin* gpio) {
furi_assert(gpio);
__disable_irq();
FURI_CRITICAL_ENTER();
uint8_t pin_num = hal_gpio_get_pin_num(gpio);
gpio_interrupt[pin_num].callback = NULL;
gpio_interrupt[pin_num].context = NULL;
gpio_interrupt[pin_num].ready = false;
__enable_irq();
FURI_CRITICAL_EXIT();
}
static void hal_gpio_int_call(uint16_t pin_num) {

View File

@@ -516,7 +516,7 @@ static void furi_hal_irda_tx_dma_set_polarity(uint8_t buf_num, uint8_t polarity_
IrdaTxBuf* buffer = &irda_tim_tx.buffer[buf_num];
furi_assert(buffer->polarity != NULL);
__disable_irq();
FURI_CRITICAL_ENTER();
bool channel_enabled = LL_DMA_IsEnabledChannel(DMA1, LL_DMA_CHANNEL_1);
if(channel_enabled) {
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
@@ -526,7 +526,7 @@ static void furi_hal_irda_tx_dma_set_polarity(uint8_t buf_num, uint8_t polarity_
if(channel_enabled) {
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
}
__enable_irq();
FURI_CRITICAL_EXIT();
}
static void furi_hal_irda_tx_dma_set_buffer(uint8_t buf_num) {
@@ -536,7 +536,7 @@ static void furi_hal_irda_tx_dma_set_buffer(uint8_t buf_num) {
furi_assert(buffer->data != NULL);
/* non-circular mode requires disabled channel before setup */
__disable_irq();
FURI_CRITICAL_ENTER();
bool channel_enabled = LL_DMA_IsEnabledChannel(DMA1, LL_DMA_CHANNEL_2);
if(channel_enabled) {
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2);
@@ -546,7 +546,7 @@ static void furi_hal_irda_tx_dma_set_buffer(uint8_t buf_num) {
if(channel_enabled) {
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
}
__enable_irq();
FURI_CRITICAL_EXIT();
}
static void furi_hal_irda_async_tx_free_resources(void) {
@@ -621,10 +621,10 @@ void furi_hal_irda_async_tx_start(uint32_t freq, float duty_cycle) {
hal_gpio_init_ex(
&gpio_irda_tx, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedHigh, GpioAltFn1TIM1);
__disable_irq();
FURI_CRITICAL_ENTER();
LL_TIM_GenerateEvent_UPDATE(TIM1); /* TIMx_RCR -> Repetition counter */
LL_TIM_EnableCounter(TIM1);
__enable_irq();
FURI_CRITICAL_EXIT();
}
void furi_hal_irda_async_tx_wait_termination(void) {
@@ -642,9 +642,9 @@ void furi_hal_irda_async_tx_stop(void) {
furi_assert(furi_hal_irda_state >= IrdaStateAsyncTx);
furi_assert(furi_hal_irda_state < IrdaStateMAX);
__disable_irq();
FURI_CRITICAL_ENTER();
if(furi_hal_irda_state == IrdaStateAsyncTx) furi_hal_irda_state = IrdaStateAsyncTxStopReq;
__enable_irq();
FURI_CRITICAL_EXIT();
furi_hal_irda_async_tx_wait_termination();
}

View File

@@ -115,11 +115,11 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) {
}
// Stop IRQ handling, no one should disturb us till we finish
__disable_irq();
FURI_CRITICAL_ENTER();
// Confirm OS that sleep is still possible
if(eTaskConfirmSleepModeStatus() == eAbortSleep) {
__enable_irq();
FURI_CRITICAL_EXIT();
return;
}
@@ -136,7 +136,7 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) {
}
// Reenable IRQ
__enable_irq();
FURI_CRITICAL_EXIT();
}
void vApplicationStackOverflowHook(TaskHandle_t xTask, char* pcTaskName) {

View File

@@ -5,6 +5,7 @@
#include <furi_hal_resources.h>
#include <furi.h>
#include <furi_hal_delay.h>
static void (*irq_cb[2])(uint8_t ev, uint8_t data, void* context);
static void* irq_ctx[2];
@@ -33,13 +34,12 @@ static void furi_hal_usart_init(uint32_t baud) {
USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
LL_USART_Init(USART1, &USART_InitStruct);
LL_USART_SetTXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_2);
LL_USART_EnableFIFO(USART1);
LL_USART_ConfigAsyncMode(USART1);
LL_USART_Enable(USART1);
while(!LL_USART_IsActiveFlag_TEACK(USART1))
while(!LL_USART_IsActiveFlag_TEACK(USART1) || !LL_USART_IsActiveFlag_REACK(USART1))
;
LL_USART_EnableIT_RXNE_RXFNE(USART1);
@@ -70,13 +70,11 @@ static void furi_hal_lpuart_init(uint32_t baud) {
LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;
LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
LL_LPUART_Init(LPUART1, &LPUART_InitStruct);
LL_LPUART_SetTXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8);
LL_LPUART_SetRXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8);
LL_LPUART_EnableFIFO(LPUART1);
LL_LPUART_Enable(LPUART1);
while((!(LL_LPUART_IsActiveFlag_TEACK(LPUART1))) || (!(LL_LPUART_IsActiveFlag_REACK(LPUART1))))
while(!LL_LPUART_IsActiveFlag_TEACK(LPUART1) || !LL_LPUART_IsActiveFlag_REACK(LPUART1))
;
furi_hal_uart_set_br(FuriHalUartIdLPUART1, baud);