Cargar y almacenar registros de CPU en el contexto de la aplicación

2

Hace poco empecé a trabajar con un STM32F103C8T6 (un ARM Cortex M3) y me encontré con algunas dificultades.

He configurado un SysTick_Handler para cambiar el contexto actual de la aplicación. El controlador invoca un PendSV_Handler en el que quiero guardar los registros de la CPU en una estructura de datos. Este es el código simplificado:

typedef struct Registers {
    int r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12;
    int sp, lr, pc, xPSR;
} Registers;

void PendSV_Handler()
{
    Registers reg;

    register int r0 asm("r0");
    reg.r0 = r0;
    /* and so on with all other registers */
}

Sin embargo, mientras probaba el asm en línea encontré un problema. He adaptado mi controlador de esta manera:

void PendSV_Handler()
{
    asm volatile(
      "movw r0 100"  // This should store the integer 100 in register r0
    );

    register int temp asm("r0");  // This should store the value in
                                  // register r0 into temp

    toggleLED();     // Toggles an LED to visualise the behavior
    delay_ms(temp);  // Delays the execution by [temp] ms, known to work
    toggleLED();
}

Ahora el problema es que el LED que se va a encender solo se enciende una vez y luego se queda atascado. También en el SysTick_Handler se enciende otro LED con SysTick-frequency, que también deja de alternar después de la primera llamada PendSV . Sé que tienen la misma prioridad, por lo que llego a la conclusión de que el Tick-LED está atascado, porque el retraso es demasiado largo y esto me permite concluir que el valor del registro no se almacena correctamente. ¿Me perdí la forma de almacenar datos de los registros de la CPU o hay alguna falla en mis conclusiones?

    
pregunta flashingx

2 respuestas

4

No estoy seguro si está al tanto de que la lógica ya almacena el estado de la máquina durante un evento / interrupción. Si desea usar esto para cambiar de tarea, debe eliminar / reconstruir la pila para tener en cuenta el cambio. Es posible que desee extraer esa información y guardarla para el cambio de nuevo seguro.

Echa un vistazo a Atomthreads o FreeRTOS u otros para ver cómo hacer un cambio de tarea completo en un Cortex-M (no es como otros procesadores donde usted toma el control de los registros y cambia la dirección de retorno. Para empezar, el La "dirección de retorno" en LR de un evento / interrupción no es una dirección válida - " Guía genérica del usuario para dispositivos Cortex-M3: entrada y devolución de excepción ").

    
respondido por el old_timer
2
  

en el SysTick_Handler otro LED se conmuta con SysTick-frequency,   que también deja de alternar después de la primera llamada PendSV. Yo sé eso   tienen la misma prioridad

Si SysTick y PendSV tienen la misma prioridad, entonces SysTick_Handler no se volverá a invocar hasta que PendSV_Handler regrese. Eso es un problema porque delay_ms() generalmente depende de que SysTick_Handler actualice un contador. Eso nunca sucederá, por lo tanto, su programa se quedará allí.

Usar delay_ms() en un controlador de interrupciones es una mala idea, pero si desea tenerlo allí para propósitos de prueba, asegúrese de que SysTick_Handler tenga mayor prioridad que cualquier interrupción que use delay_ms() . (O modifique delay_ms() para usar un temporizador de hardware).

    
respondido por el berendi

Lea otras preguntas en las etiquetas