nt9856x/rtos/code/application/source/cardv/SrcCode/Startup/startup.c
2023-03-28 15:07:53 +08:00

255 lines
7.4 KiB
C
Executable File

#include <stdio.h>
#include <FreeRTOS.h>
#include <queue.h>
#include <task.h>
#include <kwrap/cpu.h>
#include <kwrap/semaphore.h>
#include <kwrap/flag.h>
#include <kwrap/mailbox.h>
#include <kwrap/task.h>
#include <kwrap/debug.h>
#include <kwrap/cmdsys.h>
#include <kwrap/ker_dump.h>
#include <comm/timer.h>
#include "comm/hwclock.h"
#include <plat/interrupt.h>
#include <timers.h>
#include <arm_gic.h>
#include <stdlib.h>
#include <libfdt.h>
#include <compiler.h>
#include <rtosfdt.h>
#include "startup.h"
#define DAEMON_TASK_TIMEOUT 5000000
TimerHandle_t wdt_timer;
static UINT64 prev_wdt_timer_time = 0;
/**
* @brief User defined assertion call. This function is plugged into configASSERT.
* See FreeRTOSConfig.h to define configASSERT to something different.
*/
void vAssertCalled(const char * pcFile,
uint32_t ulLine)
{
volatile uint32_t ulBlockVariable = 0UL;
volatile char * pcFileName = (volatile char *)pcFile;
volatile uint32_t ulLineNumber = ulLine;
(void)pcFileName;
(void)ulLineNumber;
printf("vAssertCalled %s, %ld\n", pcFile, (long)ulLine);
/* Setting ulBlockVariable to a non-zero value in the debugger will allow
* this function to be exited. */
taskDISABLE_INTERRUPTS();
vos_dump_stack();
//coverity[no_escape]
while (ulBlockVariable == 0UL)
{
}
taskENABLE_INTERRUPTS();
}
void vApplicationStackOverflowHook( TaskHandle_t xTask,
char * pcTaskName )
{
printf("### Stack overflow, Task: %s ###\r\n", pcTaskName);
( void ) pcTaskName;
( void ) xTask;
/* Run time stack overflow checking is performed if
configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
function is called if a stack overflow is detected. */
taskDISABLE_INTERRUPTS();
//coverity[no_escape]
for( ; ; )
{
/* Loop here */
};
}
void vApplicationIdleHook( void )
{
static BOOL is_hang_dump = FALSE;
UINT64 hook_time, cur_time;
hook_time = prev_wdt_timer_time;
cur_time = hwclock_get_longcounter();
if ((FALSE == is_hang_dump) && hook_time && (cur_time - hook_time > DAEMON_TASK_TIMEOUT)) {
printf("\r\n### TimerTask my hang, diff %lld us! ht = %lld us, cur = %lld us\r\n", (cur_time - hook_time), hook_time, cur_time);
nvt_cmdsys_runcmd("ker dump");
is_hang_dump= TRUE;
}
// cpu enter sleep
asm volatile ("wfi");
}
/*-----------------------------------------------------------*/
static ID sem_shutdown;
static void wdt_timer_cb(TimerHandle_t expiredTimer)
{
prev_wdt_timer_time = hwclock_get_longcounter();
//printf("prev_wdt_timer_time = %lld\r\n", prev_wdt_timer_time);
//vos_sem_wait(sem_shutdown);
}
static void start_wdt_timer(void)
{
wdt_timer = xTimerCreate( "wdtTimer", // Just a text name, not used by the kernel.
( 1000 / portTICK_PERIOD_MS), // The timer period in ticks.
pdTRUE, // The timer is a one-shot timer.
0, // The id is not used by the callback so can take any value.
wdt_timer_cb // The callback function that switches the LCD back-light off.
);
if( wdt_timer != NULL ) {
if( xTimerStart( wdt_timer, 0 ) != pdPASS ) {
printf("start wdt_timer fail\r\n");
}
}
}
void constructors_init(void)
{
typedef void (*pfunc) (void);
extern pfunc __CTOR_LIST__[];
extern pfunc __CTOR_END__[];
pfunc *p;
//coverity[negative_returns]
for (p = &__CTOR_END__[-1]; p >= __CTOR_LIST__; p--) {
(*p) ();
}
}
static void env_init(void)
{
unsigned char *fdt = (unsigned char *)fdt_get_base();
if (fdt == NULL) {
printf("p_fdt is NULL.\n");
return;
}
int len;
int nodeoffset;
nodeoffset = fdt_path_offset(fdt, "/nvt_info");
if (nodeoffset != -FDT_ERR_NOTFOUND) {
// other fields in nvt_info
for (nodeoffset = fdt_first_property_offset(fdt, nodeoffset);
(nodeoffset >= 0);
(nodeoffset = fdt_next_property_offset(fdt, nodeoffset))) {
const struct fdt_property *prop_reg;
if (!(prop_reg = fdt_get_property_by_offset(fdt, nodeoffset, &len))) {
break;
}
const char *name = fdt_string(fdt, fdt32_to_cpu(prop_reg->nameoff));
const char *value = (const char *)prop_reg->data;
setenv(name, value, 1);
}
}
}
static void os_init(void)
{
extern unsigned char _section_01_addr[];
extern unsigned char _image_general_zi_zi_base[];
extern unsigned char _image_general_zi_zi_limit[];
extern unsigned char _rtos_heap_start[];
extern unsigned char _rtos_heap_end[];
extern unsigned char _libc_heap_start[];
extern unsigned char *_libc_heap_end;
OSINIT_PARAM init_parm = {0};
init_parm.total.addr = 0;
init_parm.total.size = (UINT32)_libc_heap_end;
init_parm.resv.addr = 0;
init_parm.resv.size = (UINT32)_section_01_addr;
init_parm.code.addr = (UINT32)_section_01_addr;
init_parm.code.size = (UINT32)_image_general_zi_zi_base - (UINT32)_section_01_addr;
init_parm.zi.addr = (UINT32)_image_general_zi_zi_base;
init_parm.zi.size = (UINT32)_image_general_zi_zi_limit - (UINT32)_image_general_zi_zi_base;
init_parm.os_heap.addr = (UINT32)_rtos_heap_start;
init_parm.os_heap.size = (UINT32)_rtos_heap_end - (UINT32)_rtos_heap_start;
init_parm.libc_heap.addr = (UINT32)_libc_heap_start;
init_parm.libc_heap.size = (UINT32)_libc_heap_end - (UINT32)_libc_heap_start;
ker_dump_os_init(&init_parm);
}
static void rtos_main_tsk(void * p_param)
{
vos_sem_create(&sem_shutdown, 1, "sem_shutdown");
vos_sem_wait(sem_shutdown); //clear shutdown semaphore
// init os info for ker dump memory
os_init();
// init necessary for debug message
// others hw init please do at insmod
arm_gic_init();
irq_init();
#if !defined(_FW_TYPE_PARTIAL_) && !defined(_FW_TYPE_PARTIAL_COMPRESS_)
// !!!!! global c++'s constructors will be out of control on partial load tech. !!!!
// !!!!! so we only allow to use c++ after section_10 loaded. !!!!
// c++'s constructors init
constructors_init();
#endif
// start wdt timer for monitor if freertos daemon task work normally
start_wdt_timer();
// environment init from fdt/nvt-info
env_init();
// do the first program
rtos_main();
// wait system trigger shutdown
vos_sem_wait(sem_shutdown);
vos_sem_destroy(sem_shutdown);
}
int main(void)
{
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//!! Here only initiate OS dependency, others initialization please do at rtos_main()
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// to avoid calling malloc on printf.
THREAD_HANDLE main_hdl;
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IONBF, 0);
// set freertos heap size for heap_5 method (https://www.freertos.org/a00111.html)
extern unsigned char _rtos_heap_start[];
extern unsigned char _rtos_heap_end[];
HeapRegion_t xHeapRegions[] = {
{ (uint8_t *) _rtos_heap_start, _rtos_heap_end-_rtos_heap_start },
{ NULL, 0 } //Terminates the array.
};
vPortDefineHeapRegions(xHeapRegions);
// init cpu (cache, memory)
rtos_cpu_init(NULL);
// init semaphore and set the initial state
rtos_sem_init(512);
// init flag and set the initial state
rtos_flag_init(256);
// init mailbox and set the initial state
vos_mbx_init(16);
// create test tasks
rtos_task_init(90);
// create first task to do initialization
main_hdl = vos_task_create(rtos_main_tsk, NULL, "rtos_main_tsk", 20, 8192);
vos_task_resume(main_hdl);
// start the scheduler.
vTaskStartScheduler();
#if 0 // here not be reached.
rtos_sem_exit();
rtos_flag_exit();
rtos_task_exit();
#endif
return 0;
}