Comprender las funciones relacionadas con el temporizador del software uCOS

Bloque de control del temporizador de software (estructura) :

estructura os_tmr {

OS_OBJ_TYPE Type; //El tipo de objeto del kernel es OS_OBJ_TYPE_TMR

    CPU_CHAR *NamePtr; //Nombre del temporizador de software 

    OS_TMR_CALLBACK_PTR CallbackPtr; //Puntero a la función de devolución de llamada

    void *CallbackPtrArg; //Puntero a los parámetros de la función de devolución de llamada   

    OS_TMR *NextPtr; //Apunta al siguiente temporizador

    OS_TMR *PrevPtr; //Apunta al temporizador anterior

    OS_TICK Remain; // ¿Cuántas bases de tiempo quedan hasta que se alcance el tiempo del temporizador?                       

    OS_TICK Dly; //Valor de tiempo inicial del temporizador

    OS_TICK Period; //Período de tiempo del temporizador, con la base de tiempo del temporizador como unidad mínima

    OS_OPT Opt; //Opción de temporizador

    OS_STATE Estado; //Estado del temporizador

    OS_TMR *DbgPrevPtr; //Apunta al temporizador anterior en la lista de depuración del temporizador

    OS_TMR *DbgNextPtr; //Apunta al siguiente temporizador en la lista de depuración del temporizador

};

Aquí hay dos opciones de temporizador: OS_OPT_TMR_ONE_SHOT (modo único, solo cronometrado una vez y no repetido), OS_OPT_TMR_PERIODIC (modo periódico).

Tareas del temporizador de software :

{

El proceso de creación de tareas del temporizador de software : La creación de tareas del temporizador de software se completa cuando el sistema inicializa OSInit(). OSInit() llama a OS_TmrInit() para inicializar el modelo de gestión del reloj cuando la macro OS_CFG_TMR_EN está habilitada. En OS_TmrInit(), se llama a OSTaskCreate() para crear una tarea de temporizador de software.

OS_TmrInit(): Inicializar el modelo de gestión del temporizador

{

1 parámetro de entrada : el tipo de error devuelto. Si el error *p_err! = OS_ERR_NONE ocurre al llamar a la función, entonces regresa.

Proceso funcional : ① Primero realice una verificación de seguridad. Luego determine si la depuración del temporizador del software está habilitada y, si está habilitada, asigne la variable de puntero global OSTmrDbgListPtr que apunta a la lista de depuración del temporizador a NULL, porque aún no se ha creado ningún temporizador y, naturalmente, no hay ningún temporizador en la lista de depuración. ② Deje que al puntero global OSTmrListPtr que apunta al temporizador se le asigne el valor NULL y a la variable global que cuenta el número de temporizadores se le asigne el valor 0; esta es la lista de temporizadores, que encadena todos los temporizadores creados para formar una lista doblemente enlazada. . ( El algoritmo hash utilizado por f103 en realidad aparece en la lista ). ③ Si el mutex está habilitado, llame a OSMutexCreate() para crear un mutex que proteja el temporizador. Al inicializar la variable de estructura del temporizador que definimos en la función de creación del temporizador OSTmrCreate(), se utilizará un mutex para proteger esta sección crítica ( posiblemente porque el temporizador del software se crea durante la ejecución de la tarea y el uso del método de interrupción de conmutación provocará retrasos en las interrupciones). f4 realizó algunas mejoras ) ( Este mutex está definido en os.h y tiene atributos globales. El mutex se adquiere al ingresar a la sección crítica para obtener el derecho a modificar el valor de la sección crítica; se libera al salir de la sección crítica. Varios temporizadores pueden utilizar solo un mutex ). ④ uCOS simplemente llama a OSTaskCreate() en esta función para crear una tarea. Naturalmente, al igual que cuando creamos una tarea, ya ha definido la pila global de tareas, la prioridad de la tarea y el tamaño de la tarea (os_cfg_app.c); también declara el Función de tarea del temporizador de software (os.h). Los usuarios pueden modificar estos parámetros, por lo que antes de crear una tarea, OSTaskCreate() verifica si la prioridad está fuera de rango, si el puntero de la pila apunta a NULL, etc. ⑤ Llame a OSTaskCreate() para crear una tarea de temporizador de software.

}

OS_TmrTask(): función de tarea del temporizador

{

Idea de función : Como dijimos antes, la razón por la que existe una tarea de temporizador es para determinar si ha llegado el tiempo del temporizador y, si es así, llamar a la función de devolución de llamada correspondiente. Entonces, ¿cómo determina la tarea del temporizador cuándo se acaba el tiempo programado ? Tenga en cuenta que este es un temporizador de software y no tiene los registros ni otras estructuras del temporizador de hardware. Cuando expire el tiempo del temporizador de hardware, el bit de bandera correspondiente en el registro se establecerá en 1. Entonces, para los temporizadores de software, podemos simular los bits de bandera de los temporizadores de hardware. Sin embargo, la cantidad de temporizadores de software es incierta y no podemos usar una cierta cantidad de variables globales para marcar . Recuerde el proceso de sincronización del temporizador de hardware : primero determine el tiempo del temporizador de hardware y luego asigne el valor de tiempo (es decir, el número de tiempos de tiempo) al temporizador de hardware. Cuando el número de tiempo llega a 0, la posición de la bandera es 1. De hecho, la aparición del bit de bandera es para sincronización. Por lo tanto, los temporizadores de software también siguen este proceso : determine el ritmo del temporizador de software y luego cada temporizador tiene un valor de tiempo diferente. Para determinar todos los temporizadores en una tarea, todos los temporizadores de software se agrupan en una lista de temporizadores. Y es necesario para recorrer la lista completa cuando llega cada latido del temporizador para determinar si algún temporizador ha expirado . Para sincronizar el latido del temporizador del software, el semáforo se obtiene en la tarea del temporizador del software . Solo cuando el latido del temporizador libera el semáforo, la tarea obtiene el semáforo y luego regresa al estado listo, indicando la llegada de un latido, para determinar si hay un tiempo El cronómetro finaliza.

Proceso de función : Al igual que otras funciones de tarea, la función de tarea del temporizador también tiene un bucle infinito sin retorno y solo hay un parámetro de entrada, que es el tipo de error devuelto. ① Ingrese al bucle while (p_tmr! = (OS_TMR *) 0) y llame a la función de espera del semáforo de la tarea OSTaskSemPend (). Nota : Si la función que espera el semáforo no espera el semáforo, entrará en el estado de bloqueo hasta que la espera expire, termine o espere el semáforo. ② Si espera el semáforo, recorra toda la lista para ver si ha expirado algún temporizador. Ingresando a la sección crítica; aquí se mide el tiempo de ejecución de la función de tarea del temporizador del software, por lo que se obtiene la marca de tiempo actual; se aumenta el registro de tiempo del temporizador actual y el valor de la variable global OSTmrTickCtr se incrementa en 1; la variable global OSTmrListPtr es el reloj que apunta al encabezado de la lista. A través del bucle while (), recorre cada reloj de la lista. Nota : Aquí se llama a OSSchedLock() para bloquear el programador cuando se recorre la lista de relojes; de hecho, el programador debe bloquearse para evitar que otras tareas de alto nivel interrumpan la tarea y aumenten la inexactitud del tiempo. ③ ¿Cómo juzgar cuando se acaba el cronómetro? Porque un elemento de la estructura del reloj es Permanecer, que indica cuántas bases de tiempo hay hasta que llegue el tiempo del temporizador, y este parámetro se inicializó cuando se creó. Por lo tanto, en el ciclo while, solo necesita dejar que el elemento Remain disminuya y determine si disminuye a 0. Disminuir a 0 significa que el tiempo ha expirado. ④Si se agota el tiempo, determine si el reloj está en modo de disparo único o en modo periódico de acuerdo con la opción del elemento de estructura del reloj. Si está en modo periódico, asigne Permanecer a Período nuevamente; si está en modo de disparo único, llame la función OS_TmrUnlink() para eliminar el temporizador de la lista. Elimínelo y cambie el estado del temporizador a OS_TMR_STATE_COMPLETED, indicando que el temporizador está completo. Independientemente del modo, debe determinar si el puntero CallbackPtr en la estructura del reloj que apunta a la función de devolución de llamada existe. Si existe, llame a la función de devolución de llamada y luego llame a OS_TmrUnlock para desbloquear el programador.. (La función OS_TmrUnlink() se utiliza para eliminar nodos de lista doblemente enlazados. Debido a que hay un puntero principal OSTmrListPtr para administrar la lista enlazada, eliminar el primer nodo no es lo mismo que eliminar otros nodos. En esta función, después de una eliminación exitosa, cambie el estado del temporizador a OS_TMR_STATE_STOPPED y disminuir el número de temporizadores de lista OSTmrListEntries en 1). ⑤ Salga del ciclo while(), obtenga la marca de tiempo nuevamente y compárela con la marca de tiempo que ingresó al ciclo antes, y llame a OS_TmrUnlock() para liberar el mutex o desbloquear el programador. Si el tiempo máximo de ejecución de la tarea del temporizador variable global OSTmrTaskTimeMax es menor que esta diferencia, el valor se asigna a la diferencia.

Suplemento --- Llamar a funciones mediante punteros de función :

{

Generalmente, cuando llamamos funciones, usamos el nombre de la función + parámetros de la función. Dado que el compilador siempre convierte el nombre de la función en un puntero de función cuando se usa, podemos obtener el nombre de la función a través del puntero de función, que es (*puntero de función) + parámetros de función. Este formulario se usa para llamar a la función de devolución de llamada. aquí. * Puntero de función  = nombre de la función .

}

--Suelte el semáforo del tiempo del cronómetro :

{

uCOS usa la tarea Tick (OS_TickTask) para administrar el tiempo del sistema, y ​​nuestro tiempo del temporizador se divide por el tiempo del sistema, por lo que, por supuesto, el lugar donde envía el semáforo también está en la función del servicio de interrupción SysTick, OS_CPU_SysTickHandler()-- --OSTimeTick(). Sin embargo, uCOS admite el uso de retardo de interrupción. Si se utiliza el retardo de interrupción, el lugar donde se envía el semáforo de la tarea será la tarea que emite la interrupción (OS_IntQTask).

 Como se puede ver en el código anterior : el temporizador del software envía el semáforo juzgando si OSTmrUpdateCtr es igual a 0. Porque cada vez que se ingresa una interrupción del sistema, finaliza un tiempo de tic y generalmente configuramos un ciclo de 1 ms. Aquí viene cada ciclo de tick, OSTmrUpdateCtr se disminuye y cuando se reduce a 0, se envía el semáforo del temporizador del software, lo que equivale a que la base de tiempo del temporizador del software sea OSTmrUpdateCtr*tick ciclo. En la función de temporizador del software de inicialización OS_TmrInit(), tanto OSTmrUpdateCtr como OSTmrUpdateCnt son 100, lo que significa que la base de tiempo del temporizador del software es 100 ms (10 Hz) . }

Funciones relacionadas con el temporizador de software :

{

OSTmrCreate: función de creación de temporizador .

{

Nota : La función de creación del objeto del kernel no significa crear el objeto del kernel. El objeto del kernel primero debe definirse en el archivo. La función de creación del objeto del kernel es equivalente a inicializar el bloque de control del objeto del kernel. Equivalente a una tarea, primero definimos la tarea en el archivo. Para controlar la tarea de gestión, definimos una estructura de bloque de control de tareas, que contiene todo el contenido de la tarea. El contenido del TCB se inicializa en la creación de la tarea. función .

8 parámetros de entrada : puntero al temporizador; nombre del temporizador; valor de tiempo inicial; valor de tiempo periódico; opciones (únicas o periódicas); puntero a la función de devolución de llamada; parámetros formales que apuntan a la función de devolución de llamada; tipo de error devuelto.

Proceso de función : ① Realice una serie de comprobaciones, incluida la verificación de opciones: si es un modo único, debe verificar si el parámetro dly es 0. Si es 0, se devolverá el error "el parámetro inicial de sincronización no es válido". Si es el modo periódico, verifique si el período del parámetro es 0. Si es 0, se devuelve el error "El parámetro de recarga del período no es válido". ② El tipo de objeto del kernel es OS_OBJ_TYPE_TMR y el estado inicial del temporizador es OS_TMR_STATE_STOPPED. Excepto por asignar valores a los elementos en el bloque de control del temporizador de software de acuerdo con los parámetros de entrada, todo lo demás es 0 o NULL. ③Llame a OS_TmrLock(). Esta función significa que si el mutex está habilitado, llame a OSMutexPend() para obtener un mutex y use el mutex para proteger el temporizador. No hay necesidad de bloquear el programador y no se causará ninguna interrupción. El problema de retraso (en realidad, está intentando usar un mutex para proteger la estructura del temporizador para inicializar la operación de asignación, y la creación de otros objetos del núcleo es usar directamente la protección de la sección crítica). Si el mutex no está habilitado, simplemente llame a OSSchedLock() para bloquear el programador . ④ Pasos convencionales: llame a OS_TmrDbgListAdd() para insertar el temporizador en la lista de depuración del temporizador. El temporizador se crea correctamente y la variable global OSTmrQty que registra el número de temporizadores se incrementa en 1. ⑤ Llame a OS_TmrUnlock(). Esta función significa que si el mutex está habilitado (habilitado de forma predeterminada), llame a OSMutexPost() para liberar el mutex; de lo contrario, llame a OSSchedUnlock() para desbloquear el programador. ( Nota: la sección crítica de protección de interrupción del interruptor todavía se usa en f103 . La creación mutex del temporizador de protección en f407 se realiza en la función del modelo OS_TmrInit() )

}

OSTmrStart() : inicia la función de temporizador del software 

{

Propósito principal : Agregar el temporizador de software creado a la lista de temporizadores. f4 es para agregarlo a la lista doblemente enlazada. OSTmrListPtr es el puntero principal de la lista vinculada. Una vez que la función de creación del temporizador inicializa el temporizador, se detiene .

2 parámetros de entrada : puntero al temporizador de software; tipo de error devuelto

Retorno : 0/1. 0 significa que hay un error y el temporizador no pudo iniciarse; 1 significa que el temporizador se inició correctamente.

Proceso de función : ① Realizar verificación de seguridad, verificación de llamadas ilegales en interrupción, verificación de parámetros, verificación de tipo de objeto de parámetro, etc. La verificación de seguridad aquí es verificar si el puntero del tipo de error del parámetro es un puntero nulo NULL y si el puntero nulo no se puede operar. ② Clasifique las operaciones según el estado del temporizador, caja de interruptor ( no encontrada, uCOS lo ha considerado de manera muy exhaustiva, por temor a que el usuario inicie el temporizador a voluntad, realizó una serie de verificaciones y enumeró todos los estados del temporizador , clasificó la operación según el estado y devolvió diferentes mensajes de error para la depuración del usuario ). ③ Si el temporizador está funcionando, reinícielo y reasigne el elemento de estructura del temporizador Permanecer a Dly (valor de temporización inicial del temporizador). Debido a que el temporizador se está ejecutando, significa que se ha agregado a la lista de temporizadores y no es necesario volver a insertar la lista de temporizadores. ④ Si el temporizador está detenido o ha sido programado, cambie el estado a en ejecución y asigne un valor a Permanecer de acuerdo con si el valor de Dly es 0. Si es 0, entonces Permanecer = Período. Si no es 0, Permanecer = Dly . Luego está el trabajo de inserción de la lista doblemente enlazada, aquí está la operación de insertar el nodo en el encabezado, principalmente para determinar si no hay otros nodos en la lista enlazada y modificar el valor del temporizador OSTmrListEntries en la lista del temporizador. No devuelve errores y 1. ⑤ Si el temporizador no se ha creado (no se ha utilizado), se devuelve un error de no creación y se devuelve 0; en otros estados, se devuelve un tipo de error ilegal y se devuelve 0.

}

OSTmrStop: Función de parada del temporizador

{

La función del temporizador de parada de uCOS tiene dos funciones : Primero, el temporizador de parada no realiza ninguna operación. El segundo es detener el temporizador y llamar a la función de devolución de llamada, y puede elegir los parámetros de la función de devolución de llamada (ya sean los parámetros al crear o nuevos parámetros, opere de acuerdo con la opción de opción). La segunda función equivale a querer finalizar el temporizador antes y dejar que ejecute la función de devolución de llamada rápidamente para obtener los datos que quiero o implementar algunas funciones.

Retorno : 0, la parada falló. 1. Detener con éxito.

Proceso de función : ① Para detener el temporizador, llame a OS_TmrUnlink() para eliminar el temporizador de la lista de temporizadores. En la función OS_TmrUnlink(), además de eliminar nodos en la lista doblemente enlazada, el estado del temporizador también se cambiará a OS_TMR_STATE_STOPPED y disminuya el número de temporizadores en la lista OSTmrListEntries en 1. ② Luego opere de acuerdo con el estado del temporizador. Solo en el estado en curso, se realizará el paso ① y, dependiendo de la opción elegida, se verá si se llama a la función de devolución de llamada. Si es OS_TMR_STATE_COMPLETED y OS_TMR_STATE_STOPPED, lo que indica que se completó un tiempo y se detuvo pero no se inició, entonces se devolverá el tipo de error "OS_ERR_TMR_STOPPED" y 1. Otros estados son que el temporizador no se ha creado (tal vez se eliminó después de la creación) o está en un estado ilegal, simplemente devuelve el tipo de error correspondiente y 0.

}

OSTmrDel(): eliminar la función del temporizador

{

La diferencia entre eliminar y detener : a diferencia de la operación de detener el temporizador, detener el temporizador simplemente se elimina de la lista de temporizadores y se puede reiniciar llamando a la función de inicio del temporizador. Eliminar un temporizador significa borrar el contenido del temporizador. Si desea usarlo nuevamente, primero debe crearlo y luego llamar a la función de inicio.

Proceso de función : debido a que el temporizador se agregará a la lista de temporizadores y se administrará de manera uniforme a través de tareas del temporizador, se deben realizar diferentes operaciones según el estado del temporizador. Lo principal es si el temporizador está en estado de ejecución. Si está en estado de ejecución, debe eliminarse de la lista de temporizadores. Para otros estados válidos, como el estado "Completo o Detenido", solo necesita llamar a OS_TmrClr() para borrar el contenido de la estructura del temporizador. En esta función, principalmente cambia el estado del temporizador a "OS_TMR_STATE_UNUSED"; luego reduce el conteo del temporizador valor OSTmrQty por 1. , no devuelve errores y 1.

}

}

Uso del temporizador de software : ① Primero defina una estructura de temporizador. ② Llame a OSTmrCreate() para inicializar el temporizador (debe escribir una función de devolución de llamada antes de inicializar). ③ Llamar a OSTmrStart() para iniciar el temporizador en realidad agrega el temporizador a la lista de relojes. ④ También puede llamar a operaciones como eliminar y detener.

Resumen de temporizadores de software : Después de crear e iniciar el temporizador de software, el temporizador se agrega a la lista de temporizadores para que la tarea del temporizador de software lo administre. Cuando el sistema operativo cambia a la tarea del temporizador de software, la tarea del temporizador de software esperará Llegada del temporizador de software semáforo. Si el semáforo no está disponible, significa que la base de tiempo de un temporizador de software aún no ha finalizado y entonces ingresa a la lista de espera. El semáforo del temporizador de software se envía en la interrupción del sistema. Cuando finaliza un temporizador de tick, se ingresará la interrupción. En la interrupción, se juzga si una base de tiempo del temporizador también ha finalizado. Si finaliza, se envía el semáforo del temporizador. La función de semáforo, si hay una tarea en la lista de espera, la tarea se elimina de la lista de espera y se inserta en la lista lista. Entonces, aquí, la tarea del temporizador previamente bloqueada se inserta en la lista lista. Cuando el sistema operativo cambia a la tarea, juzga si el tiempo del temporizador ha finalizado. Si hay un tiempo de sincronización del temporizador, se llama a su función de devolución de llamada. Por lo tanto, si desea medir la precisión del tiempo, debe obtener una marca de tiempo después de llamar a OSTmrStart() para iniciar el temporizador, porque el temporizador se ha insertado en la lista de temporizadores en este momento y cada base de tiempo del temporizador será juzgado cuando llega. Si el temporizador expira es equivalente a que el temporizador comience a cronometrar. Luego obtenga una marca de tiempo en la función de devolución de llamada. La función de devolución de llamada es una función llamada después de que expira el temporizador, por lo que obtener la marca de tiempo es equivalente al final del temporizador. Restando los dos es el tiempo previsto. ( Preste atención aquí a distinguir entre la prioridad de las tareas y la prioridad de las interrupciones. En el análisis final, las tareas son solo funciones de bucle infinito, y cualquier interrupción puede interrumpir la ejecución de estas funciones. Las interrupciones tienen prioridad en comparación con las interrupciones, y las tareas tienen prioridad a las tareas ) .

Supongo que te gusta

Origin blog.csdn.net/m0_43443861/article/details/126251274
Recomendado
Clasificación