diff --git a/APP_Framework/Applications/main.c b/APP_Framework/Applications/main.c index c100e5487..8ab957614 100644 --- a/APP_Framework/Applications/main.c +++ b/APP_Framework/Applications/main.c @@ -10,11 +10,78 @@ * See the Mulan PSL v2 for more details. */ +#include +#include #include #include + // #include #include +#ifdef BSP_USING_WDT + +atomic_uint_fast8_t task_status = 0; +static int watchdog_fd; +static pthread_t watch_dog_task; +static pthread_mutex_t task_status_lock; + +// receiveDataFromSENSORTask(0x01)、sendDataToServerTask(0x02) + #define TASK_NUM 0x03 + +void SetTaskStatus(uint8_t task_idx) { + atomic_fetch_or(&task_status, task_idx); +} + +static void ClearTaskStatus() { + atomic_store(&task_status, 0); +} + +static void* FeedWatchdogTask(void* parameter) { + uint8_t status = 0; + + while (1) { + status = atomic_load(&task_status); + + // task status + if (TASK_NUM == status) { + /* keep watchdog alive */ + struct PrivIoctlCfg ioctl_cfg; + ioctl_cfg.ioctl_driver_type = WDT_TYPE; + ioctl_cfg.args = NULL; + + PrivIoctl(watchdog_fd, OPER_WDT_KEEPALIVE, &ioctl_cfg); + + ClearTaskStatus(); + } + + PrivTaskDelay(4000); + } +} + +int WatchdogInit(uint16_t timeout) { + int ret = 0; + + PrivMutexCreate(&task_status_lock, 0); + watchdog_fd = PrivOpen("/dev/wdt0_dev", O_RDWR); + + /* set watchdog timeout time */ + struct PrivIoctlCfg ioctl_cfg; + ioctl_cfg.ioctl_driver_type = WDT_TYPE; + ioctl_cfg.args = &timeout; + + PrivIoctl(watchdog_fd, OPER_WDT_SET_TIMEOUT, &ioctl_cfg); + + pthread_attr_t attr; + attr.schedparam.sched_priority = 22; + attr.stacksize = 2048; + + PrivTaskCreate(&watch_dog_task, &attr, &FeedWatchdogTask, NULL); + PrivTaskStartup(&watch_dog_task); + + return ret; +} +#endif + extern int FrameworkInit(); extern void ApplicationOtaTaskInit(void); @@ -26,10 +93,10 @@ extern int OtaTask(void); extern int webserver(void); #endif -int main(void) -{ +int main(void) { printf("\nHello, world!\n"); FrameworkInit(); + #ifdef APPLICATION_OTA ApplicationOtaTaskInit(); #endif @@ -38,6 +105,12 @@ int main(void) OtaTask(); #endif +#ifdef BSP_USING_WDT + // the actual timeout is around 32s when tick is 0xfff + uint16_t timeout = 0xfff; /* timeout time 0xfff ticks */ + WatchdogInit(timeout); +#endif + #ifdef APPLICATION_WEBSERVER webserver(); #endif @@ -45,5 +118,3 @@ int main(void) return 0; } // int cppmain(void); - - diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/board.c b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/board.c index be89bb33d..9ed9c2b57 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/board.c +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/board.c @@ -43,6 +43,7 @@ #include "connect_lte.h" #include "connect_rs485.h" #include "connect_uart.h" +#include "connect_wdt.h" #include "core_riscv.h" #include "wchble.h" #include "xsconfig.h" @@ -81,6 +82,22 @@ void readRomConfiguration(void) { NVIC_SystemReset(); // 复位ch32v208 } + if (CFG->resetStage == 0) { + CFG->resetStage = 1; + CFG_WRITE(PAGE_WRITE_START_ADDR, (u8 *)CFG, MODULE_CFG_LEN); + } else { + CFG->resetStage = 0; + CFG_WRITE(PAGE_WRITE_START_ADDR, (u8 *)CFG, MODULE_CFG_LEN); + KPrintf("Chained reset: wait for 1s to reset again\n"); + + // wait for 1s + extern uint32_t SystemCoreClock; + for (uint32_t i = 0; i < SystemCoreClock; i += 2) { + __NOP(); + } + NVIC_SystemReset(); + } + /* 输出配置信息 */ KPrintf("\n*************rom configuration****************\n"); KPrintf("moduleName:\t%s\n", CFG->moduleName); @@ -241,6 +258,10 @@ void InitBoardHardware() { InitHwLte(); #endif +#ifdef BSP_USING_WDT + InitHwWdt(); +#endif + KPrintf("memory address range: [0x%08x - 0x%08x] SRAM_SIZE: %ld, ssize: %ld\n", (x_ubase)MEMORY_START_ADDRESS, (x_ubase)MEMORY_END_ADDRESS, SRAM_SIZE, __stack_size); KPrintf("board init done.\n"); diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Kconfig index 9d68ab25a..5a7b99c84 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Kconfig @@ -109,5 +109,13 @@ menuconfig BSP_USING_LTE config LTE_DEVICE_NAME_1 string "lte bus device 1 name" default "lte_dev1" - endif - \ No newline at end of file + endif + +menuconfig BSP_USING_WDT + bool "Using WATCHDOG TIMER device" + default n + select RESOURCES_WDT + if BSP_USING_WDT + source "$BSP_DIR/third_party_driver/wdt/Kconfig" + endif + diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Makefile b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Makefile index e963f22e5..21d487fdc 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Makefile @@ -22,4 +22,7 @@ endif ifeq ($(CONFIG_BSP_USING_LTE),y) SRC_DIR += lte endif +ifeq ($(CONFIG_BSP_USING_WDT),y) + SRC_DIR += wdt +endif include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/ModuleConfig.c b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/ModuleConfig.c index d47601343..aee71b00d 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/ModuleConfig.c +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/ModuleConfig.c @@ -40,7 +40,8 @@ __attribute__((aligned(4))) module_cfg defaultConfiguration = {.moduleName = "Xi .stopBits_Rs485 = 1, .parity_Rs485 = 1, .cfgFlag[0] = checkcode1, - .cfgFlag[1] = checkcode2}; // 默认配置信息 + .cfgFlag[1] = checkcode2, + .resetStage = 0}; // 默认配置信息 u8 Configbuf[MODULE_CFG_LEN]; // 从flash中读取的配置信息数组 pmodule_cfg CFG = (pmodule_cfg)Configbuf; // 从flash中读取的配置信息指针 diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/include/ModuleConfig.h b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/include/ModuleConfig.h index 3921094a7..a6c62577a 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/include/ModuleConfig.h +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/include/ModuleConfig.h @@ -26,7 +26,6 @@ #define FLASH_PAGE_SIZE 1024 #define NET_MODULE_DATA_LENGTH 60 // Maximum length of the data area -#define MODULE_CFG_LEN 272 // The length of configuration buff /*Communication command code*/ #define NET_MODULE_CMD_SET 0X01 // Configure module parameters @@ -86,8 +85,11 @@ typedef struct MODULE_CFG { unsigned char stopBits_Rs485; // stop bits of RS485, `1` -> `0x01`|`2` -> `0x02` unsigned char parity_Rs485; // parity of RS485, `None` -> `0x01`|` Odd` -> `0x02`|`Even` -> `0x03` unsigned char cfgFlag[2]; // Verification code, used to verify configuration information + unsigned char resetStage; // tell if this reset should do nothing at all, and wait for 1s to reset again (chained reset); 0 means normal reset, 1 means chained reset } module_cfg, *pmodule_cfg; +#define MODULE_CFG_LEN sizeof(module_cfg) // The length of configuration buff + extern u8 Configbuf[MODULE_CFG_LEN]; extern module_cfg defaultConfiguration; diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/include/connect_wdt.h b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/include/connect_wdt.h new file mode 100644 index 000000000..7e0f5d794 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/include/connect_wdt.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan + * PSL v2. You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY + * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the + * Mulan PSL v2 for more details. + */ + +/** + * @file connect_wdt.h + * @brief define ch32v208rbt6 watchdog function and struct + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2024-12-31 + */ + +#ifndef CONNECT_WDT_H +#define CONNECT_WDT_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int InitHwWdt(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/wdt/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/wdt/Kconfig new file mode 100644 index 000000000..b47dd9f77 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/wdt/Kconfig @@ -0,0 +1,15 @@ +if BSP_USING_WDT + config WDT_BUS_NAME_0 + string "watchdog bus 0 name" + default "wdt0" + + config WDT_DRIVER_NAME_0 + string "watchdog driver 0 name" + default "wdt0_drv" + + config WDT_0_DEVICE_NAME_0 + string "watchdog device 0 name" + default "wdt0_dev0" +endif + + diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/wdt/Makefile b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/wdt/Makefile new file mode 100644 index 000000000..9be59f003 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/wdt/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := connect_wdt.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/wdt/connect_wdt.c b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/wdt/connect_wdt.c new file mode 100644 index 000000000..bdedc40d0 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/wdt/connect_wdt.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2020 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan + * PSL v2. You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY + * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the + * Mulan PSL v2 for more details. + */ + +/** + * @file connect_wdt.c + * @brief support ch32v208rbt6 watchdog function and register to bus + * framework + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2024-12-31 + */ + +#include + +#define SCALE 256 +#define PRESCALER IWDG_Prescaler_256 + +static const uint16_t IWDG_CNT = 0xFFF; +static uint16_t timeout = IWDG_CNT; + +static void IWDG_FeedInit(u16 prescale, u16 reload_cnt) { + IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); + IWDG_SetPrescaler(prescale); + IWDG_SetReload(reload_cnt); + IWDG_ReloadCounter(); + IWDG_Enable(); +} + +static uint32 WdtOpen(void* dev) { + return EOK; +} + +static void WdtFeed(void) { IWDG_ReloadCounter(); } + +static uint32 WdtConfigure(void* drv, struct BusConfigureInfo* args) { + NULL_PARAM_CHECK(drv); + NULL_PARAM_CHECK(args); + + uint16_t timeout = *((uint32_t*)args->private_data); + + switch (args->configure_cmd) { + case OPER_WDT_SET_TIMEOUT: + IWDG_FeedInit(PRESCALER, timeout); + break; + case OPER_WDT_KEEPALIVE: + WdtFeed(); + + break; + default: + return ERROR; + } + return EOK; +} + +static const struct WdtDevDone dev_done = { + WdtOpen, + NONE, + NONE, + NONE, +}; + +/** + * @description: Watchdog function + * @return success: EOK, failure: other + */ +int StartWatchdog(void) { + // add feed watchdog task function + + return EOK; +} + +int InitHwWdt(void) { + x_err_t ret = EOK; + + static struct WdtBus wdt0; + + ret = WdtBusInit(&wdt0, WDT_BUS_NAME_0); + if (ret != EOK) { + KPrintf("Watchdog bus init error %d\n", ret); + return ERROR; + } + + static struct WdtDriver drv0; + drv0.configure = WdtConfigure; + + ret = WdtDriverInit(&drv0, WDT_DRIVER_NAME_0); + if (ret != EOK) { + KPrintf("Watchdog driver init error %d\n", ret); + return ERROR; + } + + ret = WdtDriverAttachToBus(WDT_DRIVER_NAME_0, WDT_BUS_NAME_0); + if (ret != EOK) { + KPrintf("Watchdog driver attach error %d\n", ret); + return ERROR; + } + + static struct WdtHardwareDevice dev0; + dev0.dev_done = &dev_done; + + ret = WdtDeviceRegister(&dev0, WDT_0_DEVICE_NAME_0); + if (ret != EOK) { + KPrintf("Watchdog device register error %d\n", ret); + return ERROR; + } + + ret = WdtDeviceAttachToBus(WDT_0_DEVICE_NAME_0, WDT_BUS_NAME_0); + if (ret != EOK) { + KPrintf("Watchdog device register error %d\n", ret); + return ERROR; + } + + return ret; +}