2 Introduction of development environment
APCI5096 is a DSP target board developed by Beijing Kangtuo Industrial Computer Company, which is mainly used for sampling and processing analog signals. The target board uses TMS320VC32 as CPU, which has complete input and output functions and can realize 30 channels, 16 bits and 300KSPS analog input. The compiler used for debugging is the Code Composer' C3X-'C4X of TI company, and the version is 4. 10.
3 transplant process
3. System structure of1μ c/OS-II
Figure 1 illustrates the hardware and software architecture of μ C/OS-II. The application software is at the top of the whole system, and it only relates to μ C/OS-II code unrelated to the processor and μ C/OS-II code related to the application. This ensures the reusability of the application software.
The processor-independent code of μ C/OS-II provides the system service of μ C/OS-II. Using these API functions, applications can manage memory, communicate between tasks, and create and delete tasks. The application-related code of μ C/OS-II provides the reduction of μ C/OS-II itself, and the number of tasks and the size of task stack can be set according to actual needs.
Most of μ C/OS-II codes are written in ANSI C language, so μ C/OS-II has good portability. Nevertheless, you still need to write some processor-related code in C and assembly language. What the porting work needs to rewrite is the processor-related code, including three files: OS_ CPU. H and OS_ CPU_ C? c、OS_ CPU_ A? ASM focuses on the initialization of task stack and the adjustment of stack pointer during task switching.
3.2 OS_ CPU。 H
Different processors have different word lengths, so a series of data types must be redefined to ensure the correctness of transplantation. In OS_ CPU? The H file should be completed: redefining data type, defining stack data type, defining stack growth direction, the method of opening/closing critical section interrupt, and the macro definition of task switching function OS_TASK_SW.
(1) data type declaration: All integer data (char, short, int, long) in VC33 are of the same type and are represented by 32 bits. Float-point data (double) belongs to the same type and is represented by 32-bit single-precision floating-point numbers in VC33. Redefinition of data types:
Typedef unsigned character Boolean value;
Typedef unsigned character INT8U
Typedef signed character INT8S
Typedef floating point FP32
Typedef dual FP64
(2) 2) The data width of VC33 stack is 32 bits, which is defined by the data type redefined above to ensure the consistency of stack data types. Data type declaration of stack:
typedef int 32u OS _ STK;
(3) When μ C/OS-II accesses the critical section of the code, it is necessary to disable the interrupt first, and then allow the interrupt after the access. μ C/OS-II uses two macros to disable and allow interrupts, which are enabled by the interrupt enable bit switch in the status register.
Cregister unsigned integer ST; /* Declare CPU internal registers */
# define OS _ ENTER _ CRITICAL()ASM(" ANDN 2000h,ST "); /* Clear the interrupt enable bit */
# define OS _ EXIT _ CRITICAL()ASM(" OR 2000h,ST "); /* Set the interrupt enable bit */
3.3 operating system _ CPU_ C.C
In the OS_ CPU_ C.C file, the OSTaskStkInit () function is mainly completed, and the other five functions can be left unattended. The OSTaskStkInit () function completes the initialization of the task stack, so that the structure of the task stack looks like an interrupt during the execution of the task, and all registers are saved in the stack. Different compilers will have different stack ways when calling functions, such as the stack order of parameters and return addresses, the stack order between parameters, whether parameters are stored in registers or stacks, and so on. The implementation needs to be adjusted according to the requirements of the compiler.
When calling CCS function, the stack rules are as follows: first put the parameters on the stack from left to right, and then put the function return address on the stack. The initial structure of the task stack designed according to this rule is shown in Figure 2. VC33*** has 28 registers, all of which should be stacked in the program and realized by OSTaskStkInit:
{
OS _ STK * STK; /* Define the data structure of the stack */
opt = opt
STK =(OS _ STK *)ptos; /* Load the top pointer of the stack */
* STK =(OS _ STK)pdata; /* Parameters are stacked */
*++stk=(OS_ STK) task; /* Task return address */
*++stk=(OS_ STK) task; /* Interrupt Return Address */
* ++ STK =(OS _ STK)0x 2000; /* status register, interrupt */All other CPU registers are put on the stack and initialized to 0.
}
3.4 operating system CPU assembly
In OS_ CPU_ A? ASM file requires users to write four simple assembly language functions: OSStartHighRdy (), OSCtxSw (), OSIntCtxSw () and OSTickISR (). These four functions have exactly the same common parts: registering on the stack and registering off the stack. Just follow the stack structure designed above. Note that R0 to R7 of VC33 are 40-bit extended precision registers. It takes two sentences to enter and exit the stack, as follows:
Into the stack: out of the stack:
Press R0 POPF R0.
PUSHF R0 POP R 1
There is a special part of the function of OSIntCtxSw, which is used to switch tasks when returning from an interrupt. Because the interrupt occurred before calling the function of _ OSIntCtxSw, the interrupt service program has saved the CPU register in the stack, so register saving is not performed here. At the same time, we should adjust the stack pointer, remove some unnecessary contents from the stack, and then pop up all the registers. Because this function is the only compiler-related function in μ C/OS-II, it is necessary to check whether the stack pointer is correctly adjusted by multitasking after transplantation.
3.5 clock interrupt source initialization
μ C/OS-II also requires users to provide a clock resource for delay and acknowledgement timeout. According to the hardware settings of APCI5096, clock resources need to be set in three files.
( 1)OS_ CPU_ A? ASM:
In APCI5096, the timer 1 of VC33 has been used in the frequency measurement channel, so the unoccupied timer 0 is used to generate the timing interrupt. The realization method is to put a jump instruction in the interrupt vector entry of TINT0 and jump to the OSTickISR written by yourself.
Sect " Color 0_ Vector "
TINT0 br _ OSTickISR
(2)CMD file
After jumping TINT0 to OSTickISR, you should also specify the vector entry address of TINT0. VC33 on APCI5096 board is set to BootLoader mode, where the entry address of TINT0 is fixed to 0x809FC9. Specify the following in the SECTIONS section of the CMD file:
tint 0 _ vector:& gt; 0x809FC9
(3)Main? C file
μ C/OS-II requires users to initialize the beat interrupt in the first task that μ C/OS-II starts running after OSStart () runs. Write a function TimerInit () by yourself, and call this function at the beginning of the first task to complete the initialization of Timer0. In this function, TIM0_ XXX represents the addresses of three registers of Timer0. After setting Timer 0, global interrupt and clock interrupt should be turned on.
{
* TIM0 _ PRD = 0x7530/* Set the period as 1 kHz */
* TIM0 _ CNT = 0
* Tim 0 _ CTL = 0x2c 1; /* Start clock */
ST | = 0x2000/* Open interrupt */
IE | = 0x 100; /* Turn on the clock interrupt */
}
Test and write drivers and applications.
After finishing the above work, we need to test whether the transplant is successful. In the initial test, you can run the operating system itself first, and schedule some simple tasks and clock beat interrupt tasks. Mainly test the correctness of the system itself. If the debugging is successful, you can continue to develop the driver and add applications to it.