vxWorks系统中多核cpu的使能

来源:互联网 发布:conor maynard知乎 编辑:程序博客网 时间:2024/06/07 21:59
    平台介绍:

vxWorks6.7,CPU为loongson3A1000(4核)

基本过程就是首先0号cpu初始化(这段代码还没分析),之后就是0号cpu对1,2,3号CPU进行初始化。这里主要记录下对0号之外的cpu的初始化。

 

函数调用:

usrRootusrSmpInitkernelCpuEnableInternalvxCpuStateInitsysCpuEnablesysCpuStartgodson3_cpu_start


 

#define CPUSET_SET(cpuset, n)         (cpuset |= (1 << n)) //某位置1#define CPUSET_ISSET(cpuset, n)       (cpuset & (1 << n))  //判断某位是否为1#define CPUSET_CLR(cpuset, n)         (cpuset &= ~(1 << n))//把某位置0#define CPUSET_ZERO(cpuset)           (cpuset = 0)         //清0LOCAL void usrEnableCpu (void)    {    int cpu;    int numCpus = vxCpuConfiguredGet ();    cpuset_t enabledCpus;    ULONG timeoutTicks, timeoutStart, currentTickCount;    CPUSET_ZERO (enabledCpus);    CPUSET_SET (enabledCpus, 0);    vxCpuEnableTimeout = VX_ENABLE_CPU_TIMEOUT;    timeoutTicks = vxCpuEnableTimeout * sysClkRateGet ();    //对0号之外cpu进行使能操作    for (cpu = 1; cpu < numCpus; cpu++)        {        //kernelCpuEnableInternal是做使能操作的函数,如果使能失败打印信息,没有失败则记录下该cpu已使能        if (kernelCpuEnableInternal (cpu) == ERROR)            {    logMsg ("usrEnableCpu: error when enabling additional CPU: %x\n"    "userEnableCpu: kernelCpuEnableInternal failed\n"     ,cpu, 0, 0, 0, 0, 0);            }        else            CPUSET_SET (enabledCpus, cpu);}//在指定延迟的时间下还没有使能就打印,并循环执行等待使能    timeoutStart = vxAbsTicksGet ();    do      {currentTickCount = vxAbsTicksGet ();   if ((currentTickCount - timeoutStart) > timeoutTicks)    {    for ( cpu = 1 ; cpu < numCpus ; cpu ++)       {if (!CPUSET_ISSET (_WRS_CPU_ENABLED (),cpu))         logMsg ("usrEnableCpu: Timeout (%d secs) wating to enable "          "additional CPU: %x\n", vxCpuEnableTimeout, cpu,            0, 0, 0, 0);                 }      break;     }      } while (_WRS_CPU_ENABLED () != enabledCpus);//执行钩子函数    for ( cpu = 1 ; cpu < numCpus ; cpu ++)     {        if (CPUSET_ISSET (_WRS_CPU_ENABLED(), cpu))   {          usrSmpCpuEnableHook (cpu);    }      } }
本函数调用kernelCpuEnableInternal对每个cpu进行使能。
STATUS kernelCpuEnableInternal     (    unsigned int cpuToEnable    )    {    char *pStackBase;#ifdef _WRS_ARCH_SUPPORTS_VX_CPU_STATE_INIT    WIND_CPU_STATE cpuState;#endif /* _WRS_ARCH_SUPPORTS_VX_CPU_STATE_INIT */    /*     * cpu can be enabled in any sequence.     *     * return ERROR if input parameter is out of range     * or CPU is already enabled     */    if ((cpuToEnable >= _WRS_CPU_CONFIGURED ()) ||(CPUSET_ISSET (_WRS_CPU_ENABLED (), cpuToEnable)))         return (ERROR);    /*     * idle task's exception stack will be used to     * bring up the specified CPU     */    pStackBase = (_WRS_KERNEL_CPU_GLOBAL_GET (cpuToEnable, idleTaskId))->pExcStackBase;#ifdef _WRS_ARCH_SUPPORTS_VX_CPU_STATE_INIT    /* Init arch-specific WIND_CPU_STATE struct */    vxCpuStateInit (cpuToEnable, &cpuState, pStackBase, kernelCpuEntry);    return sysCpuEnable (cpuToEnable, &cpuState);#else /* _WRS_ARCH_SUPPORTS_VX_CPU_STATE_INIT */        return sysCpuEnable (cpuToEnable, kernelCpuEntry, pStackBase);     #endif /* _WRS_ARCH_SUPPORTS_VX_CPU_STATE_INIT */}


kernelCpuEnableInternal调用vxCpuStateInit设置要填写到cpu寄存器的值(也就是把cpu设置为一个可用的状态),sysCpuEnable使能cpu。


 

STATUS vxCpuStateInit    (    unsigned int cpu,    WIND_CPU_STATE *pCpuState,    char *pStackBase,    void (*entry) (void)    )    {    /*     * return ERROR if input parameter is out of range     * or CPU is already enabled     */     if ((cpu >= vxCpuConfiguredGet()) ||(CPUSET_ISSET (_WRS_CPU_ENABLED (), cpu)))return (ERROR);    if ((pCpuState == NULL) || (entry== NULL) || (pStackBase == NULL))return (ERROR);    bzero ((char *)pCpuState, sizeof(WIND_CPU_STATE));    vxKernelVars[cpu].vars.cpu_archVars.cpu__mipsSrImask = SR_IMASK;    pCpuState->regs.sr = taskSrDefault & ~SR_IE;#if defined(MIPSXX_xlr)    pCpuState->regs.regEIMR = taskEimrDefault;#endif     /*      * initialize gp (small data area pointer). We use an assembler function     * since _gp must be referenced as far data.      */     vxSdaSet (&pCpuState->regs);   //设置_gp    pCpuState->regs.spReg = (_RType)pStackBase;    pCpuState->regs.pc = (INSTR *)entry;    }

这里主要是对pCpuState结构体进行设置,这是要写进cpu寄存器的值。其中entry是一个函数,作用为设置cpu已经使能标志(全局变量vxCpuEnabled),并加载idle程序。

entry:

_WRS_FUNC_NORETURN void kernelCpuEntry (void)    {    unsigned int currentCpu = _WRS_CPU_INDEX_GET ();    //得到tcb指针(没看太明白)    WIND_TCB *pTcb = _WRS_KERNEL_CPU_GLOBAL_GET (currentCpu, idleTaskId);    pTcb->windSmpInfo.cpuIndex = currentCpu;    //设置栈(也不是很明白)    windIntStackSet (_WRS_KERNEL_CPU_GLOBAL_GET (currentCpu, vxIntStackBase));    //设置cpu使能的全局变量,标志该cpu初始化完成.    /*vxCpuEnabled=1表示:0号cpu使能    * 3表示:0号1号cpu使能    * 7表示:0号1号2号cpu使能    *       F表示:0号1号2号3号cpu使能    */    CPUSET_ATOMICSET (_WRS_CPU_ENABLED (), currentCpu);    //加载idle    windLoadContext ();}


sysCpuEnable:

    STATUS sysCpuEnable(unsigned int cpuNum, WIND_CPU_STATE *cpuState)    {    if ((cpuNum < 1) || (cpuNum > (sysCpuAvailableGet ()-1)))        {return -1;        }    sysCpuInitTable[cpuNum] = (FUNCPTR) cpuState->regs.pc;    return sysCpuStart(cpuNum, cpuState);    }STATUS sysCpuStart(int cpu, WIND_CPU_STATE *cpuState)    {godson3_cpu_start(cpu,  (void (*)(void))SYS_CPU_INIT,  (long)cpuState->regs.spReg,  (long)cpuState->regs.gpReg,  (long)cpuState->regs.a1Reg);return OK;    }    


其中godson3_cpu_start函数为:

#define MAILBOX_BUF1    0x900000003ff01120  //核间寄存器,放置启动参数#define MAILBOX_BUF2    0x900000003ff01220  //#define MAILBOX_BUF3    0x900000003ff01320  //.globl godson3_cpu_start.ent godson3_cpu_startgodson3_cpu_start:       //a0 a1  a2  a3  a4都是参数lit0,0x1             //t0=1bne a0,t0,1f           //如果a0!=t0,就跳转到下面紧接着的标号1处nop                    //dlit0,MAILBOX_BUF1    //相等就加载MAILBOX_BUF1到t0中,并跳转到标号2处b2f                   //1:                       //lit0,0x2             //bnea0,t0,1f           //nop                    //dlit0,MAILBOX_BUF2    //b2f                   //1:                       //lit0,0x3             //bnea0,t0,1f           //nop                    //dlit0,MAILBOX_BUF3    //b2f                   //2:                       //sd  a1,0(t0)           //把a1的值放在t0存储的地址的偏移地址0处sda2,8(t0)           //把a2的值放在t0存储的地址的偏移地址8处sda3,0x10(t0)        //把a3的值放在t0存储的地址的偏移地址0x10处sda4,0x18(t0)        //把a4的值放在t0存储的地址的偏移地址0x18处1:                       //jrra                 //.end godson3_cpu_start //#endif                   //



 

原创粉丝点击