Implemented iwdg as xiuos device and chained reset
This commit is contained in:
parent
8e2baf1ee3
commit
4358ce4d9f
|
@ -10,11 +10,78 @@
|
||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
// #include <user_api.h>
|
// #include <user_api.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
|
|
||||||
|
#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 int FrameworkInit();
|
||||||
extern void ApplicationOtaTaskInit(void);
|
extern void ApplicationOtaTaskInit(void);
|
||||||
|
|
||||||
|
@ -26,10 +93,10 @@ extern int OtaTask(void);
|
||||||
extern int webserver(void);
|
extern int webserver(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int main(void)
|
int main(void) {
|
||||||
{
|
|
||||||
printf("\nHello, world!\n");
|
printf("\nHello, world!\n");
|
||||||
FrameworkInit();
|
FrameworkInit();
|
||||||
|
|
||||||
#ifdef APPLICATION_OTA
|
#ifdef APPLICATION_OTA
|
||||||
ApplicationOtaTaskInit();
|
ApplicationOtaTaskInit();
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,6 +105,12 @@ int main(void)
|
||||||
OtaTask();
|
OtaTask();
|
||||||
#endif
|
#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
|
#ifdef APPLICATION_WEBSERVER
|
||||||
webserver();
|
webserver();
|
||||||
#endif
|
#endif
|
||||||
|
@ -45,5 +118,3 @@ int main(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// int cppmain(void);
|
// int cppmain(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "connect_lte.h"
|
#include "connect_lte.h"
|
||||||
#include "connect_rs485.h"
|
#include "connect_rs485.h"
|
||||||
#include "connect_uart.h"
|
#include "connect_uart.h"
|
||||||
|
#include "connect_wdt.h"
|
||||||
#include "core_riscv.h"
|
#include "core_riscv.h"
|
||||||
#include "wchble.h"
|
#include "wchble.h"
|
||||||
#include "xsconfig.h"
|
#include "xsconfig.h"
|
||||||
|
@ -81,6 +82,22 @@ void readRomConfiguration(void) {
|
||||||
NVIC_SystemReset(); // 复位ch32v208
|
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("\n*************rom configuration****************\n");
|
||||||
KPrintf("moduleName:\t%s\n", CFG->moduleName);
|
KPrintf("moduleName:\t%s\n", CFG->moduleName);
|
||||||
|
@ -241,6 +258,10 @@ void InitBoardHardware() {
|
||||||
InitHwLte();
|
InitHwLte();
|
||||||
#endif
|
#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,
|
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);
|
(x_ubase)MEMORY_END_ADDRESS, SRAM_SIZE, __stack_size);
|
||||||
KPrintf("board init done.\n");
|
KPrintf("board init done.\n");
|
||||||
|
|
|
@ -111,3 +111,11 @@ menuconfig BSP_USING_LTE
|
||||||
default "lte_dev1"
|
default "lte_dev1"
|
||||||
endif
|
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
|
||||||
|
|
||||||
|
|
|
@ -22,4 +22,7 @@ endif
|
||||||
ifeq ($(CONFIG_BSP_USING_LTE),y)
|
ifeq ($(CONFIG_BSP_USING_LTE),y)
|
||||||
SRC_DIR += lte
|
SRC_DIR += lte
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(CONFIG_BSP_USING_WDT),y)
|
||||||
|
SRC_DIR += wdt
|
||||||
|
endif
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
||||||
|
|
|
@ -40,7 +40,8 @@ __attribute__((aligned(4))) module_cfg defaultConfiguration = {.moduleName = "Xi
|
||||||
.stopBits_Rs485 = 1,
|
.stopBits_Rs485 = 1,
|
||||||
.parity_Rs485 = 1,
|
.parity_Rs485 = 1,
|
||||||
.cfgFlag[0] = checkcode1,
|
.cfgFlag[0] = checkcode1,
|
||||||
.cfgFlag[1] = checkcode2}; // 默认配置信息
|
.cfgFlag[1] = checkcode2,
|
||||||
|
.resetStage = 0}; // 默认配置信息
|
||||||
|
|
||||||
u8 Configbuf[MODULE_CFG_LEN]; // 从flash中读取的配置信息数组
|
u8 Configbuf[MODULE_CFG_LEN]; // 从flash中读取的配置信息数组
|
||||||
pmodule_cfg CFG = (pmodule_cfg)Configbuf; // 从flash中读取的配置信息指针
|
pmodule_cfg CFG = (pmodule_cfg)Configbuf; // 从flash中读取的配置信息指针
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#define FLASH_PAGE_SIZE 1024
|
#define FLASH_PAGE_SIZE 1024
|
||||||
|
|
||||||
#define NET_MODULE_DATA_LENGTH 60 // Maximum length of the data area
|
#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*/
|
/*Communication command code*/
|
||||||
#define NET_MODULE_CMD_SET 0X01 // Configure module parameters
|
#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 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 parity_Rs485; // parity of RS485, `None` -> `0x01`|` Odd` -> `0x02`|`Even` -> `0x03`
|
||||||
unsigned char cfgFlag[2]; // Verification code, used to verify configuration information
|
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;
|
} module_cfg, *pmodule_cfg;
|
||||||
|
|
||||||
|
#define MODULE_CFG_LEN sizeof(module_cfg) // The length of configuration buff
|
||||||
|
|
||||||
extern u8 Configbuf[MODULE_CFG_LEN];
|
extern u8 Configbuf[MODULE_CFG_LEN];
|
||||||
|
|
||||||
extern module_cfg defaultConfiguration;
|
extern module_cfg defaultConfiguration;
|
||||||
|
|
|
@ -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 <ch32v20x_wwdg.h>
|
||||||
|
#include <device.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int InitHwWdt(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
SRC_FILES := connect_wdt.c
|
||||||
|
|
||||||
|
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -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 <connect_wdt.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
Loading…
Reference in New Issue