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
Previous article:Learn ARM development(20)
Next article:Learn ARM development(22)
Recommended ReadingLatest update time:2024-11-15 17:56
- Popular Resources
- Popular amplifiers
- Wireless Sensor Network Technology and Applications (Edited by Mou Si, Yin Hong, and Su Xing)
- Foundations of ARM64 Linux Debugging, Disassembling, and Reversing Analyze Code, Understand Stack Me
- Algorithm Competition (Volume 2) (Scanned version) (Luo Yongjun and Guo Weibin)
- M5STACK CoreS3 Tic-Tac-Toe Game
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Keysight Technologies Helps Samsung Electronics Successfully Validate FiRa® 2.0 Safe Distance Measurement Test Case
- Innovation is not limited to Meizhi, Welling will appear at the 2024 China Home Appliance Technology Conference
- Innovation is not limited to Meizhi, Welling will appear at the 2024 China Home Appliance Technology Conference
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- How to download the executable file from PC to the development board?
- Automobile Camshaft Position Sensor Signal Measurement and Waveform Analysis - Oscilloscope
- FX3/CX3(CYUSB3065) thread locked issue:
- HC32F460 external interrupt PC3
- Application of Real-time Spectrum Analyzer in Radio Frequency Microwave Interference Analysis
- Toshiba's new stepper motor driver chip TB5128
- Keysight spectrum analyzer measurement abnormality maintenance--N9010A maintenance
- BQ4050 cannot be unlocked using BQStudio
- [New Year's flavor competition] + Zongzi brown sugar with fish every year, Guizhou's strong special New Year flavor
- The difference between brushed motor and brushless motor