diff --git a/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_wdt.h b/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_wdt.h index 9708e0f..a89626a 100644 --- a/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_wdt.h +++ b/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_wdt.h @@ -105,7 +105,7 @@ typedef struct __WDT_ClockTypeDef } WDT_ClockTypeDef; -void HAL_RTC_MspInit(WDT_HandleTypeDef* hwdt); +void HAL_WDT_MspInit(WDT_HandleTypeDef* hwdt); HAL_StatusTypeDef HAL_WDT_Init(WDT_HandleTypeDef *hwdt, uint32_t timeout); HAL_StatusTypeDef HAL_WDT_Refresh(WDT_HandleTypeDef *hwdt, uint32_t timeout); HAL_StatusTypeDef HAL_WDT_Start(WDT_HandleTypeDef *hwdt, uint32_t timeout); diff --git a/cores/arduino/mik32/hal/peripherals/Source/mik32_hal_wdt.c b/cores/arduino/mik32/hal/peripherals/Source/mik32_hal_wdt.c index 7c39985..9b12a7a 100644 --- a/cores/arduino/mik32/hal/peripherals/Source/mik32_hal_wdt.c +++ b/cores/arduino/mik32/hal/peripherals/Source/mik32_hal_wdt.c @@ -3,14 +3,56 @@ uint16_t TimeOut = 20; uint16_t WDT_prescale[] = {1, 2, 4, 16, 64, 256, 1024, 4096}; +/** + * @brief Запись слова в регистр CON (конфигурация WDT) + * @param hwdt указатель на структуру WDT_HandleTypeDef, которая содержит + * информацию о конфигурации для модуля WDT. + * @param conValue 32-х битное слово + */ +static void __attribute__( ( noinline, section(".ram_text") ) ) HAL_WDT_Write_Word_To_CON(WDT_HandleTypeDef* hwdt, uint32_t conValue) +{ + //Если позволить компилятору inlining, станет невозможно выделить функцию в отдельную секцию. + intptr_t ptr = (intptr_t)(hwdt->Instance); + /** + * Попытки избежать использования отдельной переменной-указателя, такие как: + * "sb a0,0x9C(%a0)\n\t" + * : "m" (*(hwdt->Instance)) + * не работают из-за бага GCC (internal compiler error <...> riscv_print_operand_address) + * */ + asm volatile( + "li a0,0x1E\n\t" //Store unlock byte somewhere + "sb a0,0x9C(%0)\n\t" //Write UNLOCK byte into WDT KEY register + "sw %1,0x84(%0)\n\t" //Write payload + : + : "r" (ptr), "r" (conValue) + : "a0" + ); +} +/** + * @brief Запись байта в регистр KEY (пуск/остановка WDT) + * @param hwdt указатель на структуру WDT_HandleTypeDef, которая содержит + * информацию о конфигурации для модуля WDT. + * @param key байт для записи ( @ref WDT_KEY_START или @ref WDT_KEY_STOP ) + */ +static void __attribute__( ( noinline, section(".ram_text") ) ) HAL_WDT_Write_Byte_To_KEY(WDT_HandleTypeDef* hwdt, uint8_t key) +{ + intptr_t ptr = (intptr_t)(hwdt->Instance); + asm volatile( + "li a0,0x1E\n\t" //Store unlock byte somewhere + "sb a0,0x9C(%0)\n\t" //Write UNLOCK byte into WDT KEY register + "sb %1,0x9C(%0)\n\t" //Write payload + : + : "r" (ptr), "r" (key) + : "a0" + ); +} + /** * @brief Инициализация WDT MSP. * @param hwdt указатель на структуру WDT_HandleTypeDef, которая содержит * информацию о конфигурации для модуля WDT. - * - * информацию о конфигурации для модуля WDT. */ -__attribute__((weak)) void HAL_RTC_MspInit(WDT_HandleTypeDef *hwdt) +__attribute__((weak)) void HAL_WDT_MspInit(WDT_HandleTypeDef *hwdt) { __HAL_PCC_WDT_CLK_ENABLE(); } @@ -82,7 +124,7 @@ HAL_StatusTypeDef HAL_WDT_Init(WDT_HandleTypeDef *hwdt, uint32_t timeout) return HAL_ERROR; } - HAL_RTC_MspInit(hwdt); + HAL_WDT_MspInit(hwdt); if (HAL_WDT_Stop(hwdt, timeout) != HAL_OK) @@ -100,8 +142,7 @@ HAL_StatusTypeDef HAL_WDT_Init(WDT_HandleTypeDef *hwdt, uint32_t timeout) } uint32_t conValue = (wdtClock.divIndex << WDT_CON_PRESCALE_S) | WDT_CON_PRELOAD(wdtClock.tick); - hwdt->Instance->KEY = WDT_KEY_UNLOCK; - hwdt->Instance->CON = conValue; + HAL_WDT_Write_Word_To_CON(hwdt, conValue); return HAL_OK; } @@ -115,8 +156,7 @@ HAL_StatusTypeDef HAL_WDT_Init(WDT_HandleTypeDef *hwdt, uint32_t timeout) */ HAL_StatusTypeDef HAL_WDT_Refresh(WDT_HandleTypeDef *hwdt, uint32_t timeout) { - hwdt->Instance->KEY = WDT_KEY_UNLOCK; - hwdt->Instance->KEY = WDT_KEY_START; + HAL_WDT_Write_Byte_To_KEY(hwdt, WDT_KEY_START); while (timeout--) { @@ -139,8 +179,7 @@ HAL_StatusTypeDef HAL_WDT_Refresh(WDT_HandleTypeDef *hwdt, uint32_t timeout) */ HAL_StatusTypeDef HAL_WDT_Start(WDT_HandleTypeDef *hwdt, uint32_t timeout) { - hwdt->Instance->KEY = WDT_KEY_UNLOCK; - hwdt->Instance->KEY = WDT_KEY_START; + HAL_WDT_Write_Byte_To_KEY(hwdt, WDT_KEY_START); while (timeout--) { @@ -162,8 +201,7 @@ HAL_StatusTypeDef HAL_WDT_Start(WDT_HandleTypeDef *hwdt, uint32_t timeout) */ HAL_StatusTypeDef HAL_WDT_Stop(WDT_HandleTypeDef *hwdt, uint32_t timeout) { - hwdt->Instance->KEY = WDT_KEY_UNLOCK; - hwdt->Instance->KEY = WDT_KEY_STOP; + HAL_WDT_Write_Byte_To_KEY(hwdt, WDT_KEY_STOP); while (timeout--) { @@ -185,8 +223,7 @@ HAL_StatusTypeDef HAL_WDT_Stop(WDT_HandleTypeDef *hwdt, uint32_t timeout) void HAL_WDT_SetPrescale(WDT_HandleTypeDef *hwdt, HAL_WDT_Prescale prescale) { uint32_t conValue = (hwdt->Instance->CON & (~WDT_CON_PRESCALE_M)) | ((prescale << WDT_CON_PRESCALE_S) & WDT_CON_PRESCALE_M); - hwdt->Instance->KEY = WDT_KEY_UNLOCK; - hwdt->Instance->CON = conValue; + HAL_WDT_Write_Word_To_CON(hwdt, conValue); } /** @@ -198,6 +235,5 @@ void HAL_WDT_SetPrescale(WDT_HandleTypeDef *hwdt, HAL_WDT_Prescale prescale) void HAL_WDT_SetPreload(WDT_HandleTypeDef *hwdt, HAL_WDT_Prescale preload) { uint32_t conValue = (hwdt->Instance->CON & (~WDT_CON_PRELOAD_M)) | WDT_CON_PRELOAD(preload); - hwdt->Instance->KEY = WDT_KEY_UNLOCK; - hwdt->Instance->CON = conValue; + HAL_WDT_Write_Word_To_CON(hwdt, conValue); } \ No newline at end of file