Red de conocimiento informático - Conocimiento informático - Preguntas del examen para expertos integrados

Preguntas del examen para expertos integrados

Recomendación 1: OS_CPU.H

1. Defina tipos de datos que no estén relacionados con el compilador.

Simplemente escriba los tipos de datos correspondientes según diferentes compiladores. correspondiente al tipo de datos de ARM7 se escribe de la siguiente manera

typedef unsigned char BOOLEAN;/* variable booleana*/

typedef unsigned char INT8U /* variable entera de 8 bits sin signo*; /

typedef char INT8S con signo /* variable entera de 8 bits con signo*/

typedef unsigned short INT16U /* variable entera de 16 bits sin signo*/

<; p>typedef con signo corto INT16S; /* variable entera de 16 bits con signo*/

typedef unsigned int INT32U; /* variable entera de 32 bits sin signo*/

typedef con signo int INT32S ; /* Variable entera de 32 bits con signo*/

typedef float FP32; /*Número de coma flotante de precisión simple (32 bits)*/

typedef double FP64; número de coma flotante (64 bits)*/

/*Seleccione INT32U de acuerdo con el ancho de la pila de ARM7 entre los tipos de datos definidos anteriormente*/

typedef INT32U OS_STK /* La pila es Ancho de 32 bits*/

La siguiente parte es el código escrito para ser compatible con los tipos de datos de versiones inferiores de UCOS, que no se considerarán en UCOS-II por el momento.

2 Código relacionado con el procesador

Primero defina el método de implementación de interrupción. Hay tres métodos de interrupción preestablecidos en ARM7, está configurado en el método 2

#define OS_CRITICAL_METHOD 2/. *Seleccione el método de activación o desactivación de interrupciones*/

El siguiente párrafo es una parte que aún no he entendido completamente. Solo sé que se configuran 12 funciones de interrupción de software cuando se llaman estas funciones.

Las cosas correspondientes al número de interrupción se ejecutarán antes.

Debería poder comprender completamente la implementación de las interrupciones de software después de verlo en detalle.

Este código se explicará en detalle en los siguientes archivos, por lo que no lo analizaré aquí por ahora.

p>

Definición de pila El núcleo ARM7 admite dos métodos de crecimiento, pero el compilador del lenguaje ADS C solo admite el método de crecimiento de arriba hacia abajo. Por lo tanto:

#define OS_STK_GROWTH 1 /* La pila crece desde. de arriba a abajo, 0: el método de crecimiento de abajo hacia arriba*/

Las últimas líneas definen respectivamente el modo de usuario 01, el modo de sistema 1f y la instrucción de interrupción IRQ deshabilitada 80 tres. Un número inmediato, conveniente para llamar. .

También hay dos funciones predefinidas cuyas funciones se deben conocer más adelante, pero no se consideran por ahora. No son muy importantes.

Interrupción suave:

La interrupción no devuelve el formulario:

void _swi(swi_num) swi_name(argumentos);

Devuelve un resultado a R0

int _swi(swi_num) swi_name (argumentos);

Puede devolver hasta cuatro resultados R0-R3 a una estructura struct type{ int a,b,c,d}

type (tipo de retorno) _value_in_regs( Modificador que devuelve múltiples resultados) _swi(swi_num) swi_name(arguments);

He buscado muchos artículos en el blog sobre cómo implementar interrupciones suaves en ARM, pero no encontré nada que explique Es mejor verlo usted mismo.

El código trasplantado de ARM primero define un montón de números de interrupción suave, entre los cuales las subrutinas de servicio de interrupción de 0 y 1 están escritas en ensamblador.

p>

Otros Todos están en la subrutina del servicio de interrupción SWI_Exception escrita en lenguaje C.

__swi(0x00) void OS_TASK_SW(void);

/* Función de cambio de tarea a nivel de tarea*/

__swi(0x01) void _OSStartHighRdy(void) ;

/* Ejecutar la tarea con la mayor prioridad*/

__swi(0x02) void OS_ENTER_CRITICAL(void);

/* Desactivar interrupciones*/

__swi(0x03) void OS_EXIT_CRITICAL(void);

/* Habilitar interrupciones*/

__swi(0x40) void *GetOSAddr(int Index);

/* Obtener la entrada de la función de servicio del sistema*/

__swi(0x41) void *GetUsrAddr(int Index);

/* Obtener la entrada de la función de servicio personalizada */

__swi(0x42) void OSISRBegin(void);

/* Iniciar procesamiento de interrupción*/

__swi(0x43) int OSISRNeedSwap(void);

/* Determinar si es necesario cambiar la interrupción*/

__swi(0x80) void ChangeToSYSMode(void);

/* Cambiar la tarea al sistema mode*/

__swi(0x81) void ChangeToUSRMode(void);

/* Cambia la tarea al modo de usuario*/

__swi(0x82) void TaskIsARM (INT8U prio);

/* El código de la tarea es código ARM*/

__swi(0x83) void TaskIsTHUMB(INT8U prio);

/* El El código de tarea es THUMB */

Por ejemplo, cuando el programa se ejecuta y llama a la función OS_TASK_SW(void), se genera una interrupción de software y luego se ingresa la subrutina del servicio de interrupción.

¿Qué instrucciones se deben seguir? Bueno, simplemente siga el siguiente código. Este código sirve para conectar el controlador de excepciones de interrupción del software al kernel.

Se implementa en el código de inicio:

LDR PC, SWI_Addr

p>

SWI_Addr DCD SoftwareInterrupt

Entonces, cuando se genera una interrupción suave, la PC salta a SoftwareInterrupt y luego ingresa a la parte de procesamiento de interrupción de excepción de software

, y luego ejecute el siguiente código ensamblador SoftwareInterrupt

LDR SP, StackSvc

/*Reset the stack pointer*/

STMFD SP!, {R0-R3 , R12, LR}

/*Guardar R0, R1, R2, R3, R12, LR (R14), preste atención a por qué solo se guardan estos pocos

registros, porque R4-R11 almacena variables locales y el compilador las protege automáticamente*/

MOV R1, SP /* R1 apunta a la ubicación de almacenamiento de parámetros*/

MRS R3, SPSR /

*Guardar el registro de estado del modo de gestión*/

TST R3, #T_bit /* Si estaba en estado Thumb antes de la interrupción*/

LDRNEH R0, [LR,#-2 ] /* Si es así, obtenga el número SWI del estado del pulgar*/

BICNE R0, R0, #0xff00 /*El número de función SWI del comando THUMB es de 8 dígitos*/

LDREQ R0, [LR,#- 4] /* Si es cero, la instrucción ARM obtiene el número SWI*/

BICEQ R0, R0, #0xFF000000

/*En la instrucción ARM configurado, el número de función SWI es de 24 bits, por lo que el valor alto es 8 bits claro r0=número SWI*/

CMP R0, #1 /*

LDRLO PC, =OSIntCtxSw /* Dudoso */

/* El número de función es 0 para OSIntCtxSw para ejecutar la función de cambio de tarea de interrupción */

LDREQ PC, =__OSStartHighRdy/*SWI es 1 y el primero cambio de tarea*/

BL SWI_Exception /* De lo contrario, ingrese la función de interrupción escrita en c*/

LDMFD SP!, {R0-R3, R12, PC}/*R0-R3, R12, LR pop */

StackSvc

DCD (SvcStackSpace + SVC_STACK_LEGTH * 4 - 4)

¿Cómo ingresar a la subrutina del servicio de interrupción SWI_Exception escrita en C? A través de la siguiente declaración

IMPORTAR SWI_Exception; controlador de excepción de interrupción suave

significa conectar la función en el programa c en este código ensamblador, la misma razón

EXPORTAR __OSStartHighRdy

EXPORTAR OSIntCtxSw; Entrada cuando sale la interrupción

Ver IRQ_Handler en startup.s

EXPORTAR SoftwareInterrupt Declaración sobre la entrada de interrupción suave El código ensamblador está enlazado a el exterior,

Por lo tanto, el nombre de la función se puede llamar directamente desde el exterior

Continúe mirando otras partes del código OS_CPU_A.S, que son dos procesamiento de interrupciones de excepción de software Los códigos Las funciones OSIntCtxSw y OSStarHighRdyOSIntCtxSw se llaman cuando la subrutina del servicio de interrupción pone una tarea de mayor prioridad en el estado listo y necesita cambiar a la tarea después de que regresa la interrupción. Esto se debe a que el valor del registro de CPU de la tarea conmutada ha cambiado después. responder a la interrupción se almacena en la pila, por lo que no es necesario guardarlo repetidamente y simplemente cambiar de tarea directamente para el proceso específico, consulte el código OSIntCtxSw

; entorno de tareas cuando responde a la interrupción de excepción del software, ingresa al modo de sistema. En el código anterior, podemos ver que la estructura de la pila guardada al ingresar al modo de sistema es: R0, R1, R2, R3, R12, LR de arriba a abajo. abajo, mientras que la estructura de pila de la tarea en modo de usuario debe ser: OsEnterSum, CPSR, RO-12, LR, PC, por lo que la estructura de pila de la tarea original debe guardarse antes de cambiar las tareas de interrupción del software.

LDR R2, [SP, #20] ;Obtener PC

LDR R12, [SP, #16] ;Obtener R12

MRS R0, CPSR MSR CPSR_c, #(NoInt | SYS32Mode)

MOV R1, LR

STMFD SP!, {R1-R2} ;Guardar LR, PC

STMFD SP! , {R4-R12} ;Guardar R4-R12 MSR CPSR_c, R0

LDMFD SP!, {R4-R7} ;Obtener R0-R3

AGREGAR SP, SP, #8 ;Pop R12, PC

MSR CPSR_c, #(NoInt | SYS32Mode)

STMFD SP!, {R4-R7} ;Guardar R0-R3

LDR R1, =OsEnterSum; Obtener OsEnterSum

LDR R2, [R1]

STMFD SP!, {R2, R3}; Guardar CPSR, OsEnterSum; TCB actual de la tarea

LDR R1, =OSTCBCur

LDR R1, [R1]

STR SP, [R1] BL OSTaskSwHook función de gancho de llamada

LDR R1, =OSTCBCur

LDR R1, [R1]

STR SP, [R1] BL OSTaskSwHook p >

;OSPrioCur <= OSPrioHighRdy

LDR R4, =OSPrioCur

LDR R5, =OSPrioHighRdy

LDRB R6, [R5]

STRB R6, [R4]

;OSTCBCur <= OSTCBHighRdy

LDR R6, =OSTCBHighRdy

LDR R6, [R6]

LDR R4, =OSTCBCur

STR

R6, [R4]

OSIntCtxSw_1

;Obtener nuevo puntero de pila de tareas

LDR R4, [R6]

AGREGAR SP, R4 , #68 ;17 registro CPSR, OsEnterSum, R0-R12, LR, SP

LDR LR, [SP, #-8]

MSR CPSR_c, #(NoInt | SVC32Mode) ;Entrar en modo de gestión

MOV SP, R4 ;Establecer puntero de pila LDMFD SP!, {R4, R5} ;CPSR,OsEnterSum

;Restaurar OsEnterSum de nueva tarea

LDR R3, =OsEnterSum

STR R4, [R3]

MSR SPSR_cxsf, R5;Restaurar CPSR

LDMFD SP!, {R0-R12, LR, PC }^ ;Ejecutar nueva tarea

__OSStartHighRdy

MSR CPSR_c, #(NoInt | SYS32Mode) ;Ajustar al modo de administración

;Dígale a uC/OS -II ya se está ejecutando

LDR R4, =OSRunning

MOV R5, #1

STRB R5, [R4] Marcar el indicador de ejecución multitarea; como verdadero BL OSTaskSwHook; llame a la función de enlace para ejecutar la función definida por el usuario LDR R6, =OSTCBHighRdy almacena la dirección del bloque de control de la tarea lista de mayor prioridad

LDR R6, [R6]

B OSIntCtxSw_1; Vaya al código de la parte de salto de tarea del bloque de función de retorno de interrupción escrito anteriormente, porque ambas funciones usarán esta parte del código y el control de tarea de la tarea lista de alta prioridad antes de ingresar a esta. código La dirección rápida se almacena en R6.

AREA SWIStacks, DATA, NOINIT,ALIGN=2

SvcStackSpace SPACE SVC_STACK_LEGTH * 4 ;Código del espacio de pila del modo de gestión OSIntCtxSw_1: OSIntCtxSw_1

;Obtener nuevo puntero de pila de tareas

LDR R4, [R6] ;El puntero de pila del bloque de control de tareas se colocó en R6 y ahora se coloca en R4

ADD SP, R4, #68;17 registros CPSR, OsEnterSum, R0- R12, LR,SP

LDR LR, [SP, #-8]

MSR CPSR_c, #(NoInt | SVC32Mode) ;Ingrese al modo de administración

MOV SP, R4;Establece el puntero de pila, R4 almacena el puntero de pila no modificado LDMFD SP!, {R4, R5};CPSR,OsEnterSum

;Restaura el OsEnterSum de la nueva tarea

LDR R3 , =OsEnterSum

STR R4, [R3]

MSR SPSR_cxsf, R5 ;Restaurar CPSR

LDMFD SP!, {R0-R12, LR, PC} ^; Ejecute una nueva tarea, restaure la escena y regrese del procesamiento de excepciones; la lista de registros de la instrucción de retorno de interrupción debe incluir el símbolo ^ después de la PC, lo que indica que se trata de una forma especial de instrucción. Esta instrucción carga la PC desde la memoria y restaura el CPSR. El puntero de pila SP utilizado aquí es un registro que pertenece al modo de excepción, y cada modo de excepción tiene su propio puntero de pila.

SoftwareInterrupt

LDR SP, StackSvc; Restablecer puntero de pila

STMFD SP!, {R0-R3, R12, LR}; Guardar registro

MOV R1, SP ; R1 apunta a la ubicación de almacenamiento de parámetros MRS R3, SPSR

TST R3, #T_bit; Si estaba en estado Thumb antes de la interrupción

LDRNEH R0, [LR,#-2] ; Sí: Obtener el número SWI del estado del pulgar

BICNE R0, R0, #0xff00

LDREQ R0, [LR,#-4] No: Obtener el número SWI del estado del brazo

BICEQ R0, R0, #0xFF000000

; r0 = número SWI, R1 apunta a la ubicación de almacenamiento de parámetros

CMP R0, #1

LDRLO PC, =OSIntCtxSw

LDREQ PC, =__OSStartHighRdy; SWI 0x01 es la primera tarea que cambia BL SWI_Exception

LDMFD SP!, {R0-R3, R12, PC}^

StackSvc DCD (SvcStackSpace + SVC_STACK_LEGTH * 4 - 4)OSIntCtxSw

;El siguiente es el entorno de tareas para guardar

LDR R2, [SP, #20] ;Obtener PC (LR)

p>

LDR R12, [SP, #16] ;Obtener R12

MRS R0, CPSR MSR CPSR_c, #(NoInt | SYS32Mode)

MOV R1, LR

STMFD SP!, {R1-R2} ;Guardar LR,PC

STMFD SP!, {R4-R12} ;Guardar R4-R12 MSR CPSR_c , R0

LDMFD SP!, {R4-R7} ;Obtener R0-R3

AGREGAR SP, SP, #8 ;Pop R12,PC

MSR CPSR_c, #(NoInt | SYS32Mode)

<

p> STMFD SP!, {R4-R7} ;Guardar R0-R3

LDR R1, =OsEnterSum ;Obtener OsEnterSum

LDR R2, [R1]

STMFD SP!, {R2, R3}; Guardar CPSR, OsEnterSum; Guarda el puntero de la pila de tareas actual en el TCB

LDR R1, =OSTCBCur

LDR R1, [ R1 ]

STR SP, [R1] BL OSTaskSwHook ;Función de gancho de llamada

;OSPrioCur <= OSPrioHighRdy

LDR R4, =OSPrioCur

LDR R5, =OSPrioHighRdy

LDRB R6, [R5]

STRB R6, [R4] ; Pasar la tarea lista de mayor prioridad de OSPrioHighRdy a OSPrioCur

;OSTCBCur <= OSTCBHighRdy

LDR R6, =OSTCBHighRdy

LDR R6, [R6]

LDR R4, =OSTCBCur

STR R6, [R4] ; Pasa el puntero del bloque de control de tareas de mayor prioridad al puntero del bloque de control de tareas actual

En cuanto a las interrupciones y los tiempos de reloj, UCOS-II es el ensamblaje y c de la rutina de servicio de interrupción universal ARM7. La interfaz de la función es la siguiente: las directivas MACRO y MEND se utilizan para la definición de macro, MACRO identifica el comienzo de la definición de macro y MEND identifica el final de la definición de macro.

Después de la definición, puede llamar a este código varias veces en el programa mediante instrucciones macro MACRO

$IRQ_Label HANDLER $IRQ_Exception_ EXPORT $IRQ_Label; Etiqueta de salida

IMPORT $IRQ_Exception_ Etiqueta de referencia externa $; IRQ_Label

SUB LR, LR, #4; Calcular dirección de devolución

STMFD SP!, {R0-R3, R12, LR}; MRS R3, SPSR; Guardar estado

STMFD SP, {R3, SP, LR}^ Guardar R3, SP, LR del estado del usuario, tenga en cuenta que no se puede volver a escribir

; Si se vuelve a escribir el SP del usuario, el SP debe ajustarse más tarde

LDR R2, =OSIntNesting++

LDRB R1, [R2]

AGREGAR R1, R1, #1

STRB R1, [R2] SUB SP, SP, #4*3

MSR CPSR_c, #(NoInt | SYS32Mode) ; mode

p>

CMP R1, #1

LDREQ SP, =StackUsr

BL $IRQ_Exception_ ; Llame al controlador de interrupciones del lenguaje c MSR CPSR_c, #(NoInt SYS32Mode); cambia al modo del sistema

LDR R2, =OsEnterSum; OsEnterSum, para que la interrupción se desactive cuando OSIntExit sale

MOV R1, #1

STR R1, [R2] BL OSIntExit LDR R2, =OsEnterSum Debido a que la rutina del servicio de interrupción necesita salir, OsEnterSum=0

MOV R1, #0

STR R1, [R2] MSR CPSR_c, #(NoInt | IRQ32Mode); volver al modo irq

LDMFD SP, {R3, SP, LR}^; Restaurar el estado del usuario R3, SP, LR, tenga en cuenta no hacerlo; escribir de nuevo

Si lo que se escribe de nuevo es el SP del usuario, entonces el SP debe ajustarse más adelante

>

LDR R0, =OSTCBHighRdy

LDR R0, [R0]

LDR R1, =OSTCBCur

LDR R1, [R1]

CMP R0, R1 AGREGAR SP, SP, #4*3 ;

MSR SPSR_cxsf, R3

LDMEQFD SP!, {R0-R3, R12, PC}^ ; No realizar cambio de tareas

LDR PC, =OSIntCtxSw; Realizar cambio de tareas

MEND 2: Los archivos OS_CPU_C.C requieren que el usuario escriba 10 funciones C simples, pero solo 1 A. La función es necesaria y el resto de las funciones deben declararse, pero no necesariamente contienen ningún código. Después de una mirada aproximada, parece que se usa para depurar. Lo único que debe escribirse es OSTaskStkInit (). La función de la función OSTaskStkInit () es inicializar la estructura de pila de la tarea. La estructura de pila de la tarea está estrechamente relacionada con la arquitectura de la CPU y el compilador. Desde la estructura ARM, se puede escribir la siguiente estructura de pila: contador de programa PC, vinculador de programa LR, R12-R1, R0 se usa para pasar el primer parámetro pdata, CPSR/SPSR, contador de interrupciones fuera (usado para contar el número de interrupciones off , realizando así el anidamiento de interrupciones), el puntero de dirección devuelto apunta a los últimos datos almacenados, no a una dirección vacía. Excepción de interrupción de software Programa de servicio SWI Parte del lenguaje C void SWI_Exception (int SWI_Num, int *Regs): el parámetro SWI_Num corresponde al número de función definido en el archivo anterior, de las cuales las funciones 0 y 1 se definen en el archivo posterior, solo otras Aquí se definen 10 funciones. 2 y 3 corresponden respectivamente a la interrupción de apagado y la interrupción de encendido: MRS R0, SPSR // Cuando el software interrumpe, el registro de guardado del estado del programa SPSR se opera directamente, que es la operación del CPSR

ORR R0, R0, #NoInt //En lenguaje ensamblador, use ORR para establecer la posición correspondiente del registro y use BIC para borrarlo.

MSR SPSR_c, R0 //SPSR_c representa el 8- código de bits que solo cambia la sección de control de SPSR, y los otros tres Los bits de bandera en los segmentos _f, _s y _x están en el segmento _f, y los otros bits son bits reservados para habilitar interrupciones: MRS R0, SPSR //En habilitación interrupciones, es básicamente lo mismo que el anterior, excepto que ORR se cambia a BIC clear

BIC R0, R0, #NoInt

MSR SPSR_c, R Debido a la necesidad de implementar interrupciones Al anidar, las interrupciones solo se pueden habilitar cuando el contador que deshabilita las interrupciones disminuye a 0, y cada vez que se deshabilita la interrupción, este contador debe incrementarse en 1. Además, utilice la instrucción _asm al insertar lenguaje ensamblador.

80, 81, 82 y 83 corresponden respectivamente al modo del sistema, modo de usuario, conjunto de instrucciones ARM y conjunto de instrucciones THUMB: MRS R0, SPSR

BIC R0, R0, #0x1f //Primero. cambiar el modo de control Borrar los 5 bits inferiores

ORR R0, R0, #SYS32Mode //Establecer en 1F en modo sistema

MSR SPSR_c, R0 Modo de usuario: MRS R0, SPSR

BIC R0, R0, #0x1f

ORR R0, R0, #USR32Mode //Establecer en modo de usuario 10

MSR SPSR_c, conjunto de instrucciones R0 ARM y THUMB conjunto de instrucciones El código es el siguiente: ptcb = OSTCBPrioTbl[Regs[0]];

if (ptcb != NULL)

{

ptcb -> OSTCBStkPtr[1] & = ~(1 << 5);

} ptcb = OSTCBPrioTbl[Regs[0]];

if (ptcb != NULL)

{

ptcb -> OSTCBStkPtr[1] |= (1 << 5);

} Vi esto ayer y me di cuenta de que el lugar donde puedo' No se deje engañar por el concepto de bloque de control de tareas OS_TCB en UCOS, por lo que la tarea de hoy es echar un vistazo a esta parte. . . Probablemente recordé lo que hice anoche y comencemos el trabajo de hoy.

Paso a paso, aprende todo lo que no sabes y aprende todo lo que no sabes. . . No hay problema siempre y cuando trabajes duro. . . . . . __OSStartHighRdy

MSR CPSR_c, #(NoInt | SYS32Mode) ;MSR: en ARM, solo MSR puede configurar directamente el registro de estado CPSR o SPSR, que puede ser un número inmediato o un registro de origen, lo que significa que las interrupciones son. deshabilitado y SYS32Mode es el modo del sistema

;Dígale a uC/OS-II que ya se está ejecutando

LDR R4, =OSRunning ;OSRunning es una señal de que se está ejecutando multitarea, = OSRunning carga la dirección de OSRunning en R4. Lo que se almacena en R4 es una dirección. . .

MOV R5, #1

STRB R5, [R4] ; Almacene R5 en la variable OSRunning en la dirección almacenada en R4, es decir, configure OSRunning en 1 BL OSTaskSwHook; La función de enlace, OSTaskSwHook, se utiliza para la expansión y ejecuta funciones definidas por el usuario al cambiar de tarea. LDR R6, =OSTCBHighRdy; OSTCBHighRdy apunta al puntero al bloque de control TCB de la tarea de mayor prioridad. ! ! Coloque la dirección del puntero en R6.

LDR R6, [R6] ; Lee los datos en la dirección R6, es decir, la dirección de OSTCBHighRdy y colócalos en R6

B OSIntCtxSw_1 Salta a OSIntCtxSw_1 AREA SWIStacks, DATA, NOINIT ,ALIGN=2

SvcStackSpace SPACE SVC_STACK_LEGTH * 4 ;El espacio de pila del modo de administración continúa con el código OSIntCtxSw que no leí ayer

;El siguiente es el entorno de tareas guardadas

LDR R2, [SP, #20] ;Obtener PC y ponerlo en R2

LDR R12, [SP, #16] ;Obtener R12, //¿Qué almacena R12?

MRS R0, CPSR MSR CPSR_c, #(NoInt | SYS32Mode) ;Entra en modo sistema y desactiva las interrupciones

MOV R1, LR ;R1 pone el valor de LR

STMFD SP!, {R1-R2} ;Guardar LR, PC, almacenar R1, R2 en SP

STMFD SP!, {R4-R12} ;Guardar R4-R12, almacenar R4-12 SP MSR CPSR_c, R0 ;Volver al modo anterior

LDMFD SP!, {R4-R7} ;Obtener R0-R3

ADD SP, SP, #8 ;Abre la pila R12, PC

MSR CPSR_c, #(NoInt | SYS32Mode)

STMFD SP!, {R4-R7} ;Guardar R0-R3

LDR R1, =OsEnterSum ; Obtener OsEnterSum

LDR R2, [R1]

STMFD SP!, {R2, R3}; Guardar CPSR, OsEnterSum Guarda el puntero de la pila de tareas actual en el TCB actual; tarea

LDR R1, =OSTCBCur

LDR R1, [R1]

STR SP, [R1] BL OSTaskSwHook Llamar a la función de enlace

;OSPrioCur <= OSPrioHighRdy

LDR R4, =OSPrioCur

LDR R5, =OSPrioHighRdy

LDRB R6, [R5]

STRB R6, [R4]

;OSTCBCur <= OSTCBHighRdy

LDR R6, =OSTCBHighRdy

LDR R6, [R6]

LDR R4, =OSTCBCur

STR R6, [R4]

OSIntCtxSw_1

;Obtener el nuevo puntero de pila de tareas

LDR R4, [ R6 ] ;Asigne el puntero OSTCBHighRdy que apunta al bloque de control TCB de la tarea de mayor prioridad a R4

AGREGAR SP, R4, #68 ;17 registro: CPSR, OsEnterSum, R0-R12, LR, SP

LDR LR, [SP, #-8] ;Eliminar LR y ponerlo en LR

MSR CPSR_c, #(NoInt | SVC32Mode) ;Ingresar al modo de administración y mantener las interrupciones deshabilitadas

MOV SP, R4 ;Establezca el puntero de pila LDMFD SP!, {R4, R5} ;CPSR,OsEnterSum. Los datos LDMFD se sacan de la pila y se colocan en R4, R5

;Restaura el OsEnterSum de la nueva tarea

LDR R3, =OsEnterSum;La dirección de OsEnterSum se almacena en R3

STR R4, [R3] ;Asignar el valor de R4 a OsEnterSum

MSR SPSR_cxsf, R5 ;Restaurar CPSR; modificar SPSR en modo de gestión

LDMFD SP !, {R0-R12 , LR, PC }^ ;Ejecute nuevas tareas, restaure la escena y regrese del manejo de excepciones