Files
kunlun/os/freertos/src/hook.c
2024-09-28 14:24:04 +08:00

315 lines
11 KiB
C
Executable File

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "iot_io.h"
#include "ledc.h"
#include "watchdog.h"
#include "irq.h"
#include "cpu.h"
#include "snapshot.h"
#include "iot_config.h"
#include "iot_system.h"
/* common includes */
#include "iot_module.h"
#include "iot_dbglog_parser.h"
#include "iot_dbglog_api.h"
#include "iot_pkt_api.h"
#include "hw_war.h"
#include "iot_busmon.h"
#include "iot_oem_api.h"
#include "iot_rtc.h"
#include "platform.h"
extern int g_feed_dog;
extern int g_disable_feed_dog;
extern iot_wdg_info g_wdg_info;
#if DUAL_WDG_ON_ONE_CPU_ENABLE
extern iot_wdg_info g_wdg_info_1;
#endif
extern uint32_t total_mem;
extern uint32_t g_snapshot_triggered;
extern uint32_t g_stick_triggered;
extern unsigned int _heap_end;
uint32_t os_task_lost_sceduler_cnt = 0;
uint64_t os_task_total_time = 0;
uint32_t g_idle_task_cpu_ratio = 0;
#if IOT_PKT_INFO_DUMP_DEBUG
extern void iot_pkt_dump_info(void);
#endif
#if INTERRUPT_LATENCY_DEBUG
extern void dump_interrupt_stat_info();
#endif
#if IOT_MAP_GPIO_SIGNAL_INFO_DUMP_DEBUG
extern void gpio_signal_mapping_dump();
#endif
extern uint32_t os_get_system_state(TaskStatus_t * const pxTaskStatusArray,
const uint32_t uxArraySize, uint32_t * const pulTotalRunTime);
uint32_t os_idle_task_cpu_ratio()
{
return g_idle_task_cpu_ratio;
}
static void os_write_interrupt_err_trigger_cnt_to_flash(uint8_t force_write)
{
#if IOT_INTERRUPT_ERR_TRIGGER_WRITE_FLASH_ENABLE
uint32_t interrupt_err_trigger_cnt = interrupt_get_err_trigger();
static uint32_t invoking_cnt = 0;
static uint32_t interrupt_err_trigger_cnt_last = 0;
if (force_write) {
iot_dbglog_input(IOT_DRIVER_MID, DBGLOG_ERR,
IOT_DRIVER_INTERRUPT_TRIGGER_ERR_ID, 1,
interrupt_err_trigger_cnt);
return;
}
/* write log per 1 hours */
if (0 == invoking_cnt % IOT_INTERRUPT_ERR_TRIGGER_WRITE_FLASH_PER) {
if ((interrupt_err_trigger_cnt_last != interrupt_err_trigger_cnt) ||
(0 == invoking_cnt %
IOT_INTERRUPT_ERR_TRIGGER_WRITE_FLASH_FIXED_TIME)) {
iot_dbglog_input(IOT_DRIVER_MID, DBGLOG_ERR,
IOT_DRIVER_INTERRUPT_TRIGGER_ERR_ID, 1, interrupt_err_trigger_cnt);
if (IOT_INTERRUPT_ERR_TRIGGER_WRITE_FLASH_FIXED_TIME == invoking_cnt) {
invoking_cnt = 0;
}
interrupt_err_trigger_cnt_last = interrupt_err_trigger_cnt;
}
}
++invoking_cnt;
#endif
return ;
}
static void os_dump_taskinfo()
{
TaskStatus_t *pxTaskStatusArray;
volatile UBaseType_t uxArraySize, x;
uint32_t ulTotalRunTime = 0, ulStatsAsPercentage;
uint32_t ulTotalTaskTime = 0;
uint32_t ulTotalRun = 0;
uint32_t tmpData = 0;
static uint32_t ulTotalRunPrev = 0;
uint8_t cpuRatio = 0;
static uint8_t cpuRatioMax = 0;
static uint8_t fistRun = 1;
// Take a snapshot of the number of tasks in case it changes while this
// function is executing.
uxArraySize = uxTaskGetNumberOfTasks();
// Allocate a TaskStatus_t structure for each task. An array could be
// allocated statically at compile time.
pxTaskStatusArray = (TaskStatus_t*)&_heap_end;
if( pxTaskStatusArray != NULL ){
// Generate raw status information about each task.
uxArraySize = os_get_system_state( pxTaskStatusArray, uxArraySize,
&ulTotalRun );
//Handling of the overflow situation.
if(ulTotalRun < ulTotalRunPrev){
tmpData = 0xffffffff - ulTotalRunPrev;
ulTotalRunTime = tmpData + ulTotalRun + 1;
//iot_printf("total run time!!!:%u, %u, %u\n", ulTotalRunTime, ulTotalRun, ulTotalRunPrev);
ulTotalRunPrev = ulTotalRun;
} else{
ulTotalRunTime = ulTotalRun - ulTotalRunPrev;
ulTotalRunPrev = ulTotalRun;
}
// For percentage calculations.
ulTotalRunTime /= 100UL;
// Avoid divide by zero errors.
if( ulTotalRunTime > 0 ){
for( x = 0; x < uxArraySize; x++){
// IDLE and TmrSvr
if((pxTaskStatusArray[ x].xTaskNumber != 2)
&& (pxTaskStatusArray[ x].xTaskNumber !=3)){
ulTotalTaskTime += pxTaskStatusArray[ x ].ulRunTimeCounter;
}
}
if(ulTotalTaskTime == os_task_total_time){
os_task_lost_sceduler_cnt++;
} else{
os_task_total_time = ulTotalTaskTime;
os_task_lost_sceduler_cnt = 0;
}
// For each populated position in the pxTaskStatusArray array,
// format the raw data as human readable ASCII data
for( x = 0; x < uxArraySize; x++ ){
// What percentage of the total run time has the task used?
// This will always be rounded down to the nearest integer.
// ulTotalRunTimeDiv100 has already been divided by 100.
ulStatsAsPercentage =
pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime;
if(ulStatsAsPercentage > 100){
ulStatsAsPercentage = 100;
}
/* IDLE task */
if(pxTaskStatusArray[ x ].xTaskNumber == 2){
g_idle_task_cpu_ratio = ulStatsAsPercentage;
cpuRatio = 100 - ulStatsAsPercentage;
}
if( ulStatsAsPercentage > 0UL ){
iot_printf("%8d %8d %8d %2d%% #%08x %s\n",
pxTaskStatusArray[ x ].xTaskNumber,
pxTaskStatusArray[ x ].usStackHighWaterMark,
pxTaskStatusArray[ x ].ulRunTimeCounter,
ulStatsAsPercentage,
pxTaskStatusArray[ x ].pxStackBase,
pxTaskStatusArray[ x].pcTaskName);
} else {
// If the percentage is zero here then the task has
// consumed less than 1% of the total run time.
iot_printf("%8d %8d %8d <1%% #%08x %s\n",
pxTaskStatusArray[ x ].xTaskNumber,
pxTaskStatusArray[ x ].usStackHighWaterMark,
pxTaskStatusArray[ x ].ulRunTimeCounter,
pxTaskStatusArray[ x ].pxStackBase,
pxTaskStatusArray[ x ].pcTaskName);
}
}
if(cpuRatio > cpuRatioMax){
if(fistRun != 1){
cpuRatioMax = cpuRatio;
iot_dbglog_input(IOT_STATISTICS_MID, DBGLOG_WARN, OS_CPU_RATIO, 1, cpuRatioMax);
} else {
fistRun = 0;
}
}
iot_printf("the max cpu ratio:%d%%, intc fault %d.\n", cpuRatioMax,
interrupt_get_err_trigger());
os_write_interrupt_err_trigger_cnt_to_flash(0);
#if IOT_MAP_GPIO_SIGNAL_INFO_DUMP_DEBUG
/* print the mapping of signal and gpio. */
gpio_signal_mapping_dump();
#endif
}
}
}
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
{
/* This function will get called if a task overflows its stack. If the
parameters are corrupt then inspect pxCurrentTCB to find which was the
offending task. */
( void ) pxTask;
( void ) pcTaskName;
iot_printf("%s:Stack overflow\n", pcTaskName);
IOT_ASSERT(0);
}
void vApplicationMallocFailedHook( void )
{
/* vApplicationMallocFailedHook() will only be called if
configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
function that will get called if a call to pvPortMalloc() fails.
pvPortMalloc() is called internally by the kernel whenever a task, queue,
timer or semaphore is created. It is also called by various parts of the
demo application. If heap_1.c or heap_2.c are used, then the size of the
heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
to query the size of free heap space that remains (although it does not
provide information on how the remaining heap might be fragmented). */
iot_printf("Malloc Failed\n");
iot_printf("total:%dK\n", (total_mem>>10));
IOT_ASSERT(0);
}
#if IOT_INTERRUPT_ERR_TRIGGER_CRASH
extern uint32_t err_trigger_assert;
#endif
void vApplicationIdleHook( void )
{
/* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
task. It is essential that code added to this hook function never attempts
to block in any way (for example, call xQueueReceive() with a block time
specified, or call vTaskDelay()). If the application makes use of the
vTaskDelete() API function (as this demo application does) then it is also
important that vApplicationIdleHook() is permitted to return to its calling
function, because it is the responsibility of the idle task to clean up
memory allocated by the kernel to any task that has since been deleted. */
static int count = 0;
if (iot_wdg_need_feed()) {
iot_wdg_do_feed_dog();
}
count++;
if((count%5000) == 0){
/* update rtc count */
iot_rtc_count_update();
uint32_t free_mem = xPortGetFreeHeapSize();
uint32_t lowest_mem = xPortGetMinimumEverFreeHeapSize();
iot_printf("core id:%d idle: %d, cpu1:%d\n", cpu_get_mhartid(), xTaskGetTickCount(), iot_cpu1_count_get());
iot_printf("free:%lu lowest:%lu\n", free_mem, lowest_mem);
os_dump_taskinfo();
#if IOT_PKT_INFO_DUMP_DEBUG
iot_pkt_dump_info();
#endif
if(iot_cpu1_crash_get()){
iot_cpu1_crash_dump();
}
iot_led_blink_from_hook(IOT_PLC_TX_LED, 1);
#if IOT_INTERRUPT_ERR_TRIGGER_CRASH
if (interrupt_get_err_trigger()) {
os_write_interrupt_err_trigger_cnt_to_flash(1);
err_trigger_assert = 1;
IOT_ASSERT(0);
}
#endif
#if INTERRUPT_LATENCY_DEBUG
dump_interrupt_stat_info();
#endif
}
#if SNAPSHOT_MONITOR_DEBUG
iot_busmon_cap();
#endif
if(os_task_lost_sceduler_cnt > 200){
IOT_ASSERT(0);
}
__asm volatile ("wfi");
__asm volatile ("nop");
__asm volatile ("nop");
__asm volatile ("nop");
}