Learn ARM development(21)

Publisher:自在自由Latest update time:2024-11-15 Source: cnblogs Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

First, declare the task pointer because it will be used later.

//Task pointer.

volatile TASK_TCB* volatile g_pCurrentTask = NULL;

volatile TASK_TCB* volatile g_pCurrentTask1 = NULL;

volatile TASK_TCB* volatile g_pCurrentTask2 = NULL;

Next, we need to initialize these task stacks. Use the following code to initialize them. For simplicity, all operations are done using memory addresses. Of course, we will change to dynamically allocate memory later. The code is as follows:

///////////////////////////////////////////////////////////////////////////////

//Function name: TaskInitStack

//Function function: Allocate task stack.

// Input parameters:

//Output parameters:

//Return value:

//Developer: Cai Junsheng

//Time: 2006/02/26

//Modification instructions:

//

///////////////////////////////////////////////////////////////////////////////

void TaskInitStack(void)

{

g_pCurrentTask1 = (PTASK_TCB)0x0c700000;

g_pCurrentTask1->pStackStart = (UINT*)(0x0c700000+0x200);

g_pCurrentTask1->pStackTop = g_pCurrentTask1->pStackStart + 0x100;

g_pCurrentTask2 = (PTASK_TCB)(0x0c700000 + 0x400);

g_pCurrentTask2->pStackStart = (UINT*)(0x0c700000+0x400 + 0x200);

g_pCurrentTask2->pStackTop = g_pCurrentTask2->pStackStart + 0x100;

}

Next, create two simple tasks, both of which output a line of string and wait for a while. The code is as follows:

//

void TaskTest1(void)

{

for(;;)

{

Lock();

puts("TaskTest1/n");

UnLock();

SoftDelay(100);

}

}

//

void TaskTest2(void)

{

for(;;)

{

Lock();

puts("TaskTest2/n");

UnLock();

SoftDelay(100);

}

}

Then initialize the task stack, the code is as follows:

void TaskStart(void)

{

//

UINT* pTemp = g_pCurrentTask1->pStackTop;

//

*g_pCurrentTask1->pStackTop =  (UINT)TaskTest1;

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x14141414; /* R14 */

g_pCurrentTask1->pStackTop--;

//       *g_pCurrentTask1->pStackTop = (UINT)pTemp;       /* R13 */

//       g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x12121212; /* R12 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x11111111;   /* R11 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x10101010; /* R10 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x09090909; /* R9 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x08080808; /* R8 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x07070707; /* R7 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x06060606; /* R6 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x05050505; /* R5 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x04040404; /* R4 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x03030303; /* R3 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x02020202; /* R2 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x01010101; /* R1 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0;       /* R0 */

g_pCurrentTask1->pStackTop--;

*g_pCurrentTask1->pStackTop = (UINT)0x13;  /* SPSR */

//

//

//

pTemp = g_pCurrentTask2->pStackTop;

//

*g_pCurrentTask2->pStackTop =  (UINT)TaskTest2;

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x14141414; /* R14 */

g_pCurrentTask2->pStackTop--;

//       *g_pCurrentTask2->pStackTop = (UINT)pTemp;       /* R13 */

//       g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x12121212; /* R12 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x11111111;   /* R11 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x10101010; /* R10 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x09090909; /* R9 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x08080808; /* R8 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x07070707; /* R7 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x06060606; /* R6 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x05050505; /* R5 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x04040404; /* R4 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x03030303; /* R3 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x02020202; /* R2 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x01010101; /* R1 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0;       /* R0 */

g_pCurrentTask2->pStackTop--;

*g_pCurrentTask2->pStackTop = (UINT)0x13;  /* SPSR */

//Set the first task to run to 1.

g_pCurrentTask = g_pCurrentTask1;

}

After the code initializes two task stacks, it then sets the first task as the priority task.

Finally, you need to interrupt the task scheduling task to run, the code is as follows:

///////////////////////////////////////////////////////////////////////////////

//Function name: EIntTickIsr

//Function function: clock interrupt function.

// Input parameters:

//Output parameters:

//Return value:

//Developer: Cai Junsheng

//Time: 2006/02/26

//Modification instructions:

//

///////////////////////////////////////////////////////////////////////////////

void EIntTickIsr(void) __attribute__((naked));

void EIntTickIsr(void)

{

//Save R0-R12 registers to the stack.

asm volatile(" STMDB  SP!, {R0-R12} ");

//Disable TICK interrupt.

INTMSK |= BIT_GLOBAL|BIT_TICK;

//Get the LR address of the saved IRQ and save the LR.

asm volatile (" LDR     R0,=g_dwIRQLR" );

asm volatile (" SUBS    LR,LR,#4 ");

asm volatile (" STR           LR,[R0] ");

// Retrieve the previously saved R0-R12 register values.

asm volatile (" LDMIA       SP!, {R0-R12} ");

//Get the last returned SPSR, which is the CPSR in SVC mode.

//Switch from IRQ mode back to SVC mode.

asm volatile (" MRS          LR,SPSR ");

asm volatile (" ORR           LR,#0xc0 ");

asm volatile (" MSR          CPSR,LR ");

//Now we have switched back to SVC mode, retrieve the LR saved in IRQ mode.

//Save the value of R0 to the second position in the stack.

asm volatile (" STR     R0,[SP,#-8] ");

// Retrieve the LR value saved in IRQ mode from the saved location.

asm volatile (" LDR     R0,=g_dwIRQLR" );

asm volatile (" LDR     R0,[R0] ");

//Save the LR in IRQ mode to the stack, which is the PC value when popping the stack.

asm volatile (" STMDB   SP!,{R0} ");

// Retrieve the previously saved R0 value from the second position in the stack.

asm volatile (" SUBS    SP,SP,#4 ");

asm volatile (" LDMIA   SP!,{R0} ");

//Save R0-R12, LR to the stack, the order of stacking is exactly the opposite.

asm volatile (" STMDB   SP!,{R0-R12,LR} ");

//Save the value of CPSR to the stack, which is the location of SPSR.

asm volatile (" MRS     R4,CPSR ");

asm volatile (" BIC     R4,#0xc0 ");

asm volatile (" STMDB   SP!,{R4} ");

//Save the top of the stack to the task pointer.

asm volatile ( "LDR           R0, %0" : : "m" (g_pCurrentTask) );

asm volatile ( "STR           SP, [R0]" );

//Increase the clock count.

g_dwTickCount++;

//

printf("g_dwTickCount = (%d)/n",g_dwTickCount);

//

// Clear the mask bit.

I_ISPC = BIT_TICK;

INTMSK &= ~(BIT_GLOBAL|BIT_TICK);

//

if (g_dwTickCount < 3)

{

g_pCurrentTask = g_pCurrentTask1;

}

else if (g_dwTickCount < 4)

{

g_pCurrentTask = g_pCurrentTask2;

}

else

{

g_dwTickCount = 0;

}

//Get the new task pointer

asm volatile ( "LDR           R0, %0" : : "m" (g_pCurrentTask) );

asm volatile ( "LDR           SP, [R0]" );

//Get the SPSR value.

asm volatile ( "LDMIA       SP!, {R0}" );

asm volatile ( "MSR          SPSR, R0" );

// Get back R0-R12, LR, PC values, and run the last task.

asm volatile ( "LDMIA       SP!, {R0-R12,LR,PC}^" );

}

After writing the above code, you can actually implement task scheduling. With the above code, it becomes very easy to write and debug other complex tasks. These codes are not easy to come by. I went through several weeks of debugging before I passed them.

These are all debugged on my S3C44B0 development board


Reference address:Learn ARM development(21)

Previous article:Learn ARM development(20)
Next article:Learn ARM development(22)

Recommended ReadingLatest update time:2024-11-15 17:56

Mouser Electronics Signs Global Distribution Agreement with M5Stack
June 25, 2021 – Mouser Electronics, an electronic component distributor focused on introducing new products and offering a wide range of inventory Announced a global distribution agreement with M5Stack, a technology company dedicated to developing stackable open source Internet of Things (IoT) development kits. Afte
[Security Electronics]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号