Ucos system initialization and startup process

Source: Internet
Author: User

Previously omitted a variable in Ucos multi-task switching,

OSCTXSWCTR Identification System task switching times

It should be used primarily in debugging functions.

The Ucos system initialization function is Osinit (), which mainly accomplishes the following functions

Global variable Initialization

Ready Task Table Initialization

Empty task control block initialization

Event control block List initialization

Semaphore Set Initialization

Memory Management Initialization

QS Queue Control Initialization

System Idle Task Initialization

System Statistics Task Initialization

Some functions need to rely on macro definition open in addition to note that a variable ostaskctr identifies the total number of system tasks, after the initialization is complete, you can create the task, and after the creation of the task is completed, the system starts using the Osstart function, the code is as follows

void Osstart (void)

{

if (osrunning = = Os_false) {

Os_schednew ();

Ospriocur = Ospriohighrdy;

Ostcbhighrdy = Ostcbpriotbl[ospriohighrdy];

Ostcbcur = Ostcbhighrdy;

Osstarthighrdy ();

}

}

The start stage does not call Os_schednew directly, because at this time the system is no task in the execution, there is no interruption lock, so it is important to note that before the system starts, it is best to leave only the system interruption, start and then open the interrupt, otherwise it may cause problems

Then still get the priority, get the TCB, and finally call the Osstarthighrdy function according to the current highest priority task, the function is a function that requires assembly language porting, in Os_cpu_a.asm, the code is as follows

Osstarthighrdy

LDR R4, =nvic_syspri2; Set the PENDSV exception priority

LDR R5, =nvic_pendsv_pri

STR R5, [R4]

MOV R4, #0; Set the PSP to 0 for initial context switch call

MSR PSP, R4

LDR R4, =osrunning; osrunning = TRUE

MOV R5, #1

STRB R5, [R4]

; Switch to the highest priority task

LDR R4, =nvic_int_ctrl; rigger the PENDSV exception (causes context switch)

LDR R5, =nvic_pendsvset

STR R5, [R4]

Cpsie I; Enable interrupts at processor level

Osstarthang

B Osstarthang; should never get here dead loop

The stack is zeroed, then osrunning is set to true, and finally the interrupt is triggered because the previous os_schednew has been given the highest priority task, so after the interrupt is triggered, the interrupt can be switched directly to the highest priority task we want to switch, enabling the system to start

Also need to note that if the use of statistical tasks, then the system must start the statistical task, otherwise open the macro does not initialize the statistical task will be in a certain exception

About System Critical segments

In the system running process, sometimes a piece of code can not be interrupted, and the time of interruption is often more random, in order to solve this problem, the concept of critical section, Ucos general use three ways to deal with the critical section

    1. How the switch is interrupted
    2. By saving the program status Word and closing the interrupt mode
    3. Save the program status Word to the CPU_SR variable

The first method is simple and rough, the second method is a little more complicated, but it allows the processor to interrupt the token before and after the interrupt, but the third way the state is pressed into the stack uses local variables to hold the interrupt state word, without using the stack, more flexible

When porting, you can choose one of the options, generally choosing a third way, such as the following

Os_cpu_sr_save

MRS R0, Primask; read Primask to R0,R0 for return value

Cpsid I; Primask=1, off interrupt (NMI and hardware fault can respond)

BX LR; back

Os_cpu_sr_restore

MSR Primask, R0; read R0 to Primask, R0 as parameter

BX LR; back

#if Os_critical_method = = 3

#define Os_enter_critical () {cpu_sr = Os_cpu_sr_save ();}

#define Os_exit_critical () {os_cpu_sr_restore (CPU_SR);}

#endif

Ucos Clock

Ucos in order to deal with waiting, delay and other time-related time, the introduction of a periodic signal, that is, the Ucos clock, the clock depends on the hardware environment, we need to determine the timing of the hardware processor, with the relevant macro has a, as follows

OS_TICKS_PER_SEC, the macro defines the number of interrupts in the system class 1s, for example, we define the macro as 1000, then we need to ensure that the system interrupts every 1ms, and call the following code in the interrupt handler

Osintenter (); Enter interrupt

Ostimetick (); Call Ucos's Clock service program

Osintexit (); Trigger Task Toggle Soft Interrupt

Osintenter and Osintexit have said before, look at the composition of Ostimetick, as follows

while (Ptcb->ostcbprio! = Os_task_idle_prio) {

Os_enter_critical ();

if (ptcb->ostcbdly! = 0u) {

ptcb->ostcbdly--;

if (ptcb->ostcbdly = = 0u) {

if ((Ptcb->ostcbstat & os_stat_pend_any)! = Os_stat_rdy) {

Ptcb->ostcbstat &= (int8u) ~ (int8u) Os_stat_pend_any;

Ptcb->ostcbstatpend = os_stat_pend_to;

} else {

Ptcb->ostcbstatpend = OS_STAT_PEND_OK;

}

if ((Ptcb->ostcbstat & os_stat_suspend) = = Os_stat_rdy) {

Osrdygrp |= ptcb->ostcbbity;

OSRDYTBL[PTCB->OSTCBY] |= ptcb->ostcbbitx;

}

}

}

PTCB = ptcb->ostcbnext;

Os_exit_critical ();

}

As you can see, in this function, the system iterates over the entire TCB control structure, decrements the ostcbdly element in each element, and when the delay time of a task control block is ostcbdly to 0, the state of the task is checked for the suspended state, if not the suspended state, To modify the system Readiness table to set the current task to Reday, waiting for the system to perform task scheduling, which is the last sentence in the previous three sentences osintexit () completed, which is why the design of a break in the function of the task to switch the reason, This ensures that a task does not release the processor at the time of the machine and can switch to the task immediately when a higher-priority task occurs.

In order not to allow the highest priority task in the system to monopolize the processor, Ucos designed a delay function for the high priority task to actively release the CPU ownership, in the actual embedded system, this release is also very common, such as waiting for the device response, human eye vision residue, and related to the important function is

ostimedly parameter is the number of delay beats

OSTIMEDLYHMSM long time delay, the parameters are delay hours, seconds, minutes, milliseconds, respectively

Ostimedlyresume delay of a task that cancels a specific priority

Ostimeget get current system beats

Ostimeset setting current system beats

Basically, we just have to focus on ostimedly and Ostimedlyresume, first look at ostimedly.

if (osintnesting > 0u) {

Return

}

if (oslocknesting > 0u) {

Return

}

if (Ticks > 0u) {

Os_enter_critical ();

y = ostcbcur->ostcby;

Osrdytbl[y] &= (Os_prio) ~ostcbcur->ostcbbitx;

if (osrdytbl[y] = = 0u) {

Osrdygrp &= (Os_prio) ~ostcbcur->ostcbbity;

}

ostcbcur->ostcbdly = ticks;

Os_exit_critical ();

Os_sched ();

When the delay time of setting is greater than 0, the ready flag of the current task in the System Readiness table is canceled first, then the ostcbdly parameter of the system control block is set to the number of Beats set, and finally the system task scheduling function is called to complete the system task scheduling. And the ostcbdly is set up and the previous interrupt processing Ostimetick function is correlated, thus realizing the system delay

The delay function for canceling the task is ostimedlyresume, and the useful code is

PTCB = Ostcbpriotbl[prio];

*******

ptcb->ostcbdly = 0u;

if ((Ptcb->ostcbstat & os_stat_pend_any)! = Os_stat_rdy) {

Ptcb->ostcbstat &= ~os_stat_pend_any;

Ptcb->ostcbstatpend = os_stat_pend_to;

} else {

Ptcb->ostcbstatpend = OS_STAT_PEND_OK;

}

if ((Ptcb->ostcbstat & os_stat_suspend) = = Os_stat_rdy) {

Osrdygrp |= ptcb->ostcbbity;

OSRDYTBL[PTCB->OSTCBY] |= ptcb->ostcbbitx;

Os_exit_critical ();

Os_sched ();

} else {

Os_exit_critical ();

}

First get the task TCB that wants to cancel the delay (based on the priority), then see if the task is suspended, if it is not suspended and the task is ready, set the task Readiness table to be Raday, and call os_sched for task switching, but not that the cancellation will run. It depends on the priority of the task.

Here we can say that the scheduling time of the task is the time when the system is interrupted and the system calls the time delay function. (There are other time delays later).

Ucos system initialization and startup process

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.