移植FreeRTOS到A核

1.1       可以参考此工程移植:

https://github.com/FreeRTOS/FreeRTOS/tree/main/FreeRTOS/Demo/CORTEX_A53_64-bit_UltraScale_MPSoC

1.2       链接脚本

MEMORY

{

   ddr_0_MEM_0 : ORIGIN = 0x88000000, LENGTH = 0x40000000

}

/* Specify the default entry point to the program */

ENTRY(_vector_table)   //入口

1.3       汇编入口

_vector_table

-》b _boot //此时位于EL2

                              -》mrs  x0, currentEL  //获取当前的EL级别

                              -》cmp x0, #0x8  //如果为8,表明当前是EL2

                              -》beq  switch_to_el1_from_el2  //EL2切换到EL1

                                             -》el1_entry

                                                            -》b _boot  //进入EL1

                                                                           -》bl      invalidate_dcaches  //无效cache

                                                                           -》Enable MMU  //使能MMU

-》b       _startup //jump to start

               -》bl __libc_init_array

               -》bl      main  //进入main函数

                              -》prvSetupHardware()

                                             -》XScuGic_LookupConfig( XPAR_SCUGIC_SINGLE_DEVICE_ID )

                                             -》XScuGic_CfgInitialize( &xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress )

                                                                                          -》vTaskStartScheduler();  //开启调度

                                                                                                         -》prvCreateIdleTasks()

                                                                                                         -xTimerCreateTimerTask()  //创建调度用的timer

                                                                                                         -xPortStartScheduler()  //配置调用用的 timer 硬件

                                                                                                                        -》configSETUP_TICK_INTERRUPT()

                                                                                                                                       -》vConfigureTickInterrupt()

                                                                                                                                                      -》enable_generic_timer(TICK_INIT_VALUE); //初始化arm v8 generic timer

                                                                                                                                                      -》Register_Irq(29, FreeRTOS_Tick_Handler, NULL, portLOWEST_USABLE_INTERRUPT_PRIORITY, ucLevelSensitive);

                                                                                                                                                                     XScuGic_SetPriorityTriggerType( &xInterruptController, Int_Id, Priority << portPRIORITY_SHIFT, ucLevelSensitive ) //配置GIC-400的优先级寄存器

                                                                                                                                                                     XScuGic_Connect( &xInterruptController, Int_Id, (Xil_ExceptionHandler) Handler, ( void * ) CallBackRef ) //配置中断处理函数

                                                                                                                                                                     XScuGic_Enable( &xInterruptController, Int_Id) //使能该中断呈

                                                                                          -》while(1) {}  //死循环

1.4       初始化armv8 generic timer

/*******************************************************************/

#define ARCH_TIMER_PHYS_ACCESS                       0

#define ARCH_TIMER_VIRT_ACCESS                        1

#define ARCH_TIMER_MEM_PHYS_ACCESS           2

#define ARCH_TIMER_MEM_VIRT_ACCESS            3

#define ARCH_TIMER_CTRL_ENABLE                      (1 << 0)

#define ARCH_TIMER_CTRL_IT_MASK                    (1 << 1)

#define ARCH_TIMER_CTRL_IT_STAT                      (1 << 2)

enum arch_timer_reg {

               ARCH_TIMER_REG_CTRL,

               ARCH_TIMER_REG_TVAL,

};

#define __stringify_1(x...)             #x

#define __stringify(x...)  __stringify_1(x)

/*

 * Unlike read_cpuid, calls to read_sysreg are never expected to be

 * optimized away or replaced with synthetic values.

 */

#define read_sysreg(r) ({                                                                          \

               u64 __val;                                                                                      \

               asm volatile("mrs %0, " __stringify(r) : "=r" (__val));          \

               __val;                                                                                              \

})

/*

 * The "Z" constraint normally means a zero immediate, but when combined with

 * the "%x0" template means XZR.

 */

#define write_sysreg(v, r) do {                                                                \

               u64 __val = (u64)(v);                                                                    \

               asm volatile("msr " __stringify(r) ", %x0"                              \

                                   : : "rZ" (__val));                                                         \

} while (0)

static void arch_timer_reg_write_cp15(enum arch_timer_reg reg, u32 val)

{

               switch (reg) {

               case ARCH_TIMER_REG_CTRL:

                              write_sysreg(val, cntp_ctl_el0);

                              break;

               case ARCH_TIMER_REG_TVAL:

                              write_sysreg(val, cntp_tval_el0);

                              break;

               }

}

static u32 arch_timer_reg_read_cp15(enum arch_timer_reg reg)

{

               switch (reg) {

               case ARCH_TIMER_REG_CTRL:

                              return read_sysreg(cntp_ctl_el0);

               case ARCH_TIMER_REG_TVAL:

                              return read_sysreg(cntp_tval_el0);

               }

}

static u32 arch_timer_reg_read(enum arch_timer_reg reg)

{

               u32 val;

               val = arch_timer_reg_read_cp15(reg);

               return val;

}

static void arch_timer_reg_write(enum arch_timer_reg reg, u32 val)

{

               arch_timer_reg_write_cp15(reg, val);

}

static __always_inline void enable_generic_timer(unsigned long evt)

{

               unsigned long ctrl;

               ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);

               ctrl |= ARCH_TIMER_CTRL_ENABLE;

               ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;

               arch_timer_reg_write(ARCH_TIMER_REG_TVAL, evt);

               arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);

}

1.5       Freertos中断处理过程

FreeRTOS_IRQ_Handler

               -》BL vApplicationIRQHandler

                              -》pxVectorEntry->Handler( pxVectorEntry->CallBackRef )  // Handler ()XScuGic_Connect()注册进来

-》portSAVE_CONTEXT   //保存当前任务上下文

               -》BL vTaskSwitchContext 

                              -》vTaskSwitchContext

                                             -》taskSELECT_HIGHEST_PRIORITY_TASK()

                                                            -》listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) )  //找到当前要执行的TCB

               -》portRESTORE_CONTEXT   //真正进行任务切换

1.6       注册CLI命令行

void vUARTCommandConsoleStart( uint16_t usStackSize, unsigned portBASE_TYPE uxPriority )

{

  vRegisterSampleCLICommands();

/* Create that task that handles the console itself. */

    xTaskCreate(    prvUARTCommandConsoleTask,          /* The task that implements the command console. */

                    "CLI",                              /* Text name assigned to the task.  This is just to assist debugging.  The kernel does not use this name itself. */

                    usStackSize,                        /* The size of the stack allocated to the task. */

                    NULL,                               /* The parameter is not used, so NULL is passed. */

                    uxPriority,                         /* The priority allocated to the task. */

                    NULL );                             /* A handle is not required, so just pass NULL. */

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值