Comprender los códigos de función relacionados con eventos de uCOS

Bloque/identificador/estructura de control de eventos :

estructura os_flag_grp {                                       

    OS_OBJ_TYPE Tipo; /* Debe establecerse en OS_OBJ_TYPE_FLAG */

    CPU_CHAR *NamePtr; //Apunta al nombre del evento, tipo de cadena

    OS_PEND_LIST PendList; //Lista de espera para eventos

    OS_FLAG_GRP *DbgPrevPtr; //Apunta al evento anterior en la lista de depuración de eventos

    OS_FLAG_GRP *DbgNextPtr; //Apunta al siguiente evento en la lista de depuración de eventos

    CPU_CHAR *DbgNamePtr; //El nombre del evento en la lista de depuración

    OS_FLAGS Flags; //Estado de los bits del indicador de evento

    CPU_TS TS; //Guarda la marca de tiempo de la última vez que se lanzó el evento

    CPU_INT32U FlagID; //El ID único de los depuradores y rastreadores de terceros

};

Función de evento :

{

OSFlagCreate() : función de creación de eventos . Al igual que otras funciones que crean objetos del núcleo, primero se realizan varias comprobaciones y luego se inicializan los valores de los elementos de la estructura. Lo que es único aquí es que hay una variable de 32 bits que representa 32 eventos diferentes y generalmente se inicializa a 0, lo que indica que no han ocurrido todos los tipos de eventos . No olvide agregar 1 a la variable global del evento OSFlagQty después de que la creación sea exitosa. Esta es la tradición de uCOS. Cada vez que se crea un objeto del kernel, el número de objetos del kernel globales correspondientes debe aumentarse en 1.

OSFlagDel() : función de eliminación de eventos .

{

Las funciones que eliminan objetos del kernel borran su contenido. Entonces la función de eliminación del evento no es una excepción. Siempre hay dos opciones a la hora de eliminar: eliminar si no hay tareas en la lista de espera y eliminar independientemente de que haya tareas. Entonces, el primer paso es definitivamente verificar si hay tareas en la lista de espera y registrar el número. Luego , bajo la opción OS_OPT_DEL_NO_PEND, solo cuando el número de tareas en espera es 0, el evento se elimina de la lista de depuración; el número de eventos se reduce en 1. Y llame a OS_FlagClr() para borrar el contenido de la estructura. Para indicar que el evento se elimina después de ser creado, la función de borrar estructura asignará el elemento de tipo a ningún tipo; la posición del nombre es un nombre desconocido; la bandera del evento Flags es se borra a 0; y luego llama a OS_PendListInit () Inicializa la lista de espera al crearla, es decir, borra los elementos en la lista de espera a 0. Si está bajo la opción OS_OPT_DEL_ALWAYS, utilice un bucle while para eliminar primero todas las tareas de la lista de espera y luego realice la operación anterior. Vale la pena señalar que debido a que es posible que se eliminen tareas de la lista de espera, para mejorar el rendimiento en tiempo real del sistema, se llama a OSSched () para realizar el cambio de tareas.

Devuelve : el número de tareas en la lista de espera.

}

OSFlagPost() : función de configuración de eventos  

{

Idea de función : OSFlagPost () se utiliza para establecer el bit especificado en el grupo de eventos (establezca el indicador de evento a través del indicador de evento especificado por el parámetro). Cuando el bit está establecido (establecido en 1), indica que el evento ha ocurrido. o está pendiente. Luego recorra la lista de espera de eventos esperando en el objeto de evento para determinar si hay una tarea cuyo requisito de activación de evento coincida con el valor del indicador del objeto de evento actual. Si es así, active la tarea.

4 parámetros de entrada : puntero al evento; indicador de evento; opciones; tipo de error devuelto. Aquí hay tres opciones: OS_OPT_POST_FLAG_SET, OS_OPT_POST_FLAG_CLR, OS_OPT_POST_NO_SCHED, pero se debe incluir una de las opciones de establecer el bit de bandera en 1 y borrarlo en 0. Se puede activar estableciendo 1 o borrando 0 .

Devuelve : el valor de etiqueta actual del evento.

Nota : Debido a que los eventos tienen el mismo efecto de sincronización que los semáforos binarios, no solo pueden actuar entre tareas, sino también lograr la sincronización entre tareas e interrupciones. Entonces esta función se puede llamar en interrupción.

Proceso de función : ① Llame a OS_TS_GET () para obtener la marca de tiempo como marca de tiempo al publicar. ② Si la publicación retardada por interrupción está habilitada y se llama a la función de configuración de eventos OSFlagPost() en la interrupción, se debe llamar a OS_IntQPost() para publicar el evento en la cola de mensajes de interrupción. La interrupción de la publicación retrasada coloca la configuración (envío) de eventos (mensajes, etc.) en la tarea de publicación designada. En este momento, el sistema publica los eventos (mensajes, etc.) en la cola de mensajes de alquiler y espera hasta que se interrumpa la publicación. La tarea se activa antes de configurar el evento (enviar información). ③ Si la liberación retardada de interrupción no está habilitada, llame a OS_FlagPost() para configurar/borrar directamente el bit correspondiente al evento.

- Llamar a OS_FlagPost() :

5 parámetros de entrada : Además de los cuatro parámetros de OSFlagPost (), aquí se agrega un parámetro de marca de tiempo, que se usa para asignar la marca de tiempo a la variable de estructura del evento, por lo que la variable de marca de tiempo CPU_TS TS en la estructura del evento se usa para guardar el La marca de tiempo de la última vez que se publicó el evento.

Devuelve : el valor de etiqueta actual del evento.

Proceso de función : ① Desactive las interrupciones y modifique los elementos del indicador de evento en la estructura del evento de acuerdo con los parámetros de opción y los indicadores de parámetro del indicador de evento. La operación O se usa para establecer el bit y la operación Y se usa para borrarlo, porque cada bit de los indicadores del parámetro de entrada solo representa el indicador del evento. Según la opción establecida o clr, se realiza el elemento de estructura del evento Banderas . Borrar 0 significa invertir las banderas bit a bit y luego combinarlas con el evento. Los elementos de la estructura p_grp->Flags reciben un AND para que puedan borrarse a 0. Luego almacene la marca de tiempo en el evento. ② Obtenga el número de tareas en la lista de espera. Si no hay ninguna tarea esperando el evento (el número de tareas es 0), entonces se activa la interrupción y se devuelve directamente el valor de marca actual del evento. (Nota: un evento es como un semáforo. Es solo una señal. Solo necesita marcar qué eventos ocurren o no. A diferencia de la cola de mensajes, la cola de mensajes necesita enviar el mensaje a la lista de mensajes cuando no hay tareas. esperando el mensaje para evitar la pérdida de datos ). ③ Si hay una tarea esperando el evento, entonces es necesario recorrer las tareas en la lista de espera para ver si ocurre el evento que la tarea está esperando y verificar si se activan todos los eventos o solo uno de ellos. En el bucle while, el modo de evento de la tarea se obtiene aplicando un AND al elemento FlagsOpt de la opción de evento en la tarea TCB con la macro OS_OPT_PEND_FLAG_MASK, y luego usando la instrucción switch--case para juzgar el modo. El modo OS_OPT_PEND_FLAG_SET_ALL requiere que se produzcan todos los eventos de la tarea, luego permita que el indicador de evento y el indicador de evento de tarea en espera se apliquen con p_grp->Flags & p_tcb->FlagsPend, solo el resultado de AND es igual a p_tcb->FlagsPend (cuando la tarea llama a la función de evento en espera . En esa función, los eventos que le interesan a la tarea se asignarán al elemento p_tcb->FlagsPend.) indica que han ocurrido todos los eventos, entonces la tarea ya no está bloqueada y en espera, y se llama a la función OS_FlagTaskRdy() para asignar el elemento FlagsRdy del estado del evento de espera de la tarea a flags_rdy; luego la tarea se elimina de la lista de espera de acuerdo al estado de la tarea. Tenga en cuenta que si se agota el tiempo de espera, la tarea debe eliminarse de la lista de base de tiempo y luego agregarse a la lista lista. La función OS_PendListRemove() que elimina una tarea de la lista de espera solo elimina la tarea de la lista de espera y no está asociada con la operación de eliminar o insertar la tarea de la lista lista y de la lista de base de tiempo. El modo OS_OPT_PEND_FLAG_SET_ANY indica que cualquier evento en el evento de tarea en espera puede activar la tarea. Luego, siempre que el valor después del indicador de evento y el indicador de evento de tarea en espera se comparen con p_grp->Flags & p_tcb->FlagsPend no sea 0, significa que ha ocurrido un evento y se puede llamar a la función OS_FlagTaskRdy() preparar la tarea. Lo mismo es cierto para los dos indicadores OS_OPT_PEND_FLAG_CLR_ALL y OS_OPT_PEND_FLAG_CLR_ANY que deben borrarse a 0 indicadores de evento, excepto que ~p_grp->Flags & p_tcb->FlagsPend es para permitir que el indicador de evento se invierta bit a bit primero y luego se aplique AND. Debido a que ni los indicadores de parámetros de entrada aquí ni el elemento de indicador de evento en espera FlagsPend en TCB tienen atributos clr y set, como configurar o borrar los bits 0, 4 y 5, estos dos parámetros son iguales a 0x31, no se dirá que de acuerdo para los atributos, set es igual a 0x31 y clr es igual a 0xFFFFFFCE . Por supuesto, no es necesario calcular el valor de los indicadores de parámetros, la posición correspondiente se puede establecer mediante desplazamiento., por ejemplo, para configurar el bit 0 de la máscara de evento, luego #define EVENT_0 (0x01 << 0), para configurar el bit 1 de la máscara de evento, luego #define EVENT_1 (0x01 <<1), para configurar el enésimo bit, desplazarse hacia la izquierda n bits. Si es una combinación de múltiples eventos, simplemente O ellos. ④ Si no se selecciona OS_OPT_POST_NO_SCHED, llame a OSSched() para cambiar de tarea. ¿Lo encontraste? Las funciones de publicación del objeto del kernel son todas programación de tareas opcional. Porque cuando una tarea llama a la función de publicación, el estado de la tarea no cambiará. Si no es necesario, no es necesario cambiar; sin embargo, debido a que hay una tarea en la lista de espera que obtiene el objeto del núcleo, elimina el lista de espera y se inserta en la lista lista, si se elimina la nueva. La prioridad de la tarea es relativamente alta y la programación debe cambiarse para permitir una respuesta rápida a las tareas más urgentes . ⑤ Si no hay ningún error en la marca, obtenga la marca del evento actual flags_cur = p_grp->Flags; y devuelva flags_cur.

A continuación, echemos un vistazo al programa de selección del modo uCOS : el modo de evento de tarea se obtiene aplicando un AND al elemento de opción de evento FlagsOpt en la tarea TCB con la macro OS_OPT_PEND_FLAG_MASK. Los tipos de patrones son los siguientes:

#definir OS_OPT_PEND_FLAG_MASK (OS_OPT)(0x000Fu) 1111

#definir OS_OPT_PEND_FLAG_CLR_ALL (OS_OPT)(0x0001u) 0001

#definir OS_OPT_PEND_FLAG_CLR_ANY (OS_OPT)(0x0002u) 0010

#definir OS_OPT_PEND_FLAG_SET_ALL (OS_OPT)(0x0004u) 0100

#definir OS_OPT_PEND_FLAG_SET_ANY (OS_OPT)(0x0008u) 1000

Se puede observar que cada tipo de modo es de 16 bits (un 0 en hexadecimal representa 4 dígitos binarios, es decir, 4 ceros binarios). De hecho, cada tipo de modo aquí está representado por una posición única 1. A uCOS realmente le gusta usar este método. Dado que mode = p_tcb->FlagsOpt & OS_OPT_PEND_FLAG_MASK;, al elemento FlagsOpt de la opción de evento en TCB también se le debe asignar el tipo de valor anterior al ingresar a la lista de espera en la función de espera de evento .

}

OSFlagPend() : función de espera de eventos

{

Idea de función : cuando una tarea llama a la función de espera de eventos, se puede especificar un tiempo de espera (o no especificarlo, si es 0, significa esperar para siempre). Si el evento ha ocurrido, la opción de espera se usa para decidir si se borra el bit de bandera correspondiente del evento y devolver el valor del bit de bandera del evento. Si el evento aún no ha ocurrido, ingresa a la lista de espera y espera a que ocurra el evento; si se agota el tiempo de espera, se elimina automáticamente de la lista de espera y se restablece al estado listo. Refleja efectivamente la naturaleza en tiempo real del sistema operativo. Los indicadores de eventos se dividen en diferentes modos: incluyendo configurar 1/borrar 0 para todos los eventos y configurar 1/borrar 0 para cualquier evento. Por lo tanto, es necesario juzgar si la tarea debe ingresar a la lista de espera según el modo.

Nota : Las funciones de espera para semáforos y eventos se limitan a tareas y no se les permite llamarlas en interrupciones. Las interrupciones siguen el avance y la salida rápidos. La razón por la que las interrupciones pueden llamar a sus funciones de liberación es equivalente a establecer una bandera para indicar que el el semáforo está disponible o ocurre un evento, etc. Es estúpido poner la función del servicio de interrupción en la lista de espera.

6 parámetros de entrada : puntero de evento; indicador de evento; tiempo de espera; opciones; marca de tiempo devuelta (generalmente a la marca de tiempo de la función de espera del objeto del núcleo se le asigna la marca de tiempo de la última vez que se creó el evento cuando la tarea obtiene el evento); tipo de error devuelto.

Las opciones incluyen: OS_OPT_PEND_FLAG_CLR_ALL; OS_OPT_PEND_FLAG_CLR_ANY; OS_OPT_PEND_FLAG_SET_ALL; OS_OPT_PEND_FLAG_SET_ANY. Se debe seleccionar uno aquí. Además, también puede elegir OS_OPT_PEND_FLAG_CONSUME (el bit de bandera se invierte automáticamente después de la coincidencia); también puede elegir OS_OPT_PEND_NON_BLOCKING y OS_OPT_PEND_BLOCKING para ingresar a la lista de bloqueo de espera si el evento no ocurre.

Devuelve : flags_rdy, esperando banderas. El valor no es 0, lo que indica que el evento de espera fue exitoso ( generalmente el valor de los indicadores del parámetro de entrada de la función pend, es decir, el valor de marca de evento requerido por la tarea. El usuario compara este valor con el valor de marca de evento requerido por la tarea para ver si son iguales y luego determinar si ocurren todos los eventos de espera ); un valor de 0 indica que el evento de espera no tuvo éxito (como ingresar a la lista de espera, lo que indica que aún no se ha esperado; o hay no hay bloqueo y el programador está bloqueado).

Proceso de función : ① Primero, realice una verificación de seguridad, una verificación de llamadas ilegales durante una interrupción, una verificación de opciones de parámetros y una verificación de tipo de objeto. No hay o OS_OPT_PEND_BLOCKING en la verificación de opciones, porque el valor de la macro es 0x0000u, o los resultados son los mismos, lo que equivale a ingresar a la lista de espera de forma predeterminada si no ocurre ningún evento. ② Si el resultado de option y opt & OS_OPT_PEND_FLAG_CONSUME no es 0, significa que OS_OPT_PEND_FLAG_CONSUME está seleccionado, es decir, el bit de bandera se invierte automáticamente después de hacer coincidir. ③Debido a que los eventos no son como otros objetos del kernel, otros objetos del kernel no tienen tipos de modo . Por ejemplo, si hay un semáforo disponible se obtendrá, si no hay semáforo disponible se enviará a la lista de espera para esperar. Diferentes modos de eventos operan de manera diferente (por ejemplo, requerir que todos los eventos ocurran y requerir que ocurra solo un evento, las condiciones de juicio para que ocurran todos los eventos y las condiciones de juicio para que ocurra cualquier ocurrencia son diferentes; por lo tanto, diferentes tipos requieren códigos diferentes implementaciones, y no se pueden combinar entre sí) , por lo que para obtener el tipo de modo, es necesario determinar si un evento ocurre en diferentes modos y si ingresar a la lista de espera . Aquí, el tipo de modo se obtiene mediante opt & OS_OPT_PEND_FLAG_MASK, que es el requisito para el bit de bandera. Determine si todos los eventos requeridos de la tarea han ocurrido de acuerdo con la clasificación de cambio de modo-caso. ④ Si el modo es OS_OPT_PEND_FLAG_SET_ALL, entonces deje flags_rdy = p_grp->Flags & flags. Si ocurren todos los eventos (es decir, el resultado flags_rdy es igual a flags) , si se establece FLAG_CONSUME, deje p_grp->Flags &= ~flags_rdy, es decir, negar el indicador del evento (esto equivale a borrar 0, lo que indica que el evento ha sido procesado); asignar el valor de flags_rdy al elemento TCB de la tarea FlagsRdy y devolver flags_rdy.Si no ocurren todos los eventos (es decir, el resultado flags_rdy no es igual a flags) , debería ingresar a la lista de espera. Entonces determine si OS_OPT_PEND_NON_BLOCKING está seleccionado. Si es así, devuelva el error "Necesita esperar el bloqueo" y devuelva 0. Si no elige no ingresar a la lista de espera, se lo colocará en la lista de espera. Debido a que es necesario cambiar el estado de la tarea, es necesario determinar si el programador está bloqueado y devolver el error "el programador está bloqueado" y devolver 0; de lo contrario, bloquee el programador y llame a la función OS_FlagBlock() para enviar la tarea al Lista de espera. ⑤ Si el modo es OS_OPT_PEND_FLAG_SET_ANY, solo el juicio es diferente de set_all, solo necesita que el resultado de p_grp->Flags & flags no sea 0, y otras operaciones sean las mismas. ⑥ Si es el modo CLR, deje flags_rdy = ~p_grp->Flags & flags. Se analizó al crear la función de evento. Debido a que el indicador no tiene la naturaleza de borrar 0 o establecer 1, entonces, ¿qué bit desea borrar? 0 o establecido en 1, el valor son todos iguales, por lo que si el evento ha ocurrido, el bit correspondiente de p_grp->Flags se ha borrado a 0, por lo que se debe invertir primero. Si flags es 0x03, la naturaleza es clr; si el evento ocurre, debería ser 0xx0, y los bits 0 y 1 se han borrado a 0, por lo que se deben invertir primero y luego aplicar AND antes de realizar el siguiente juicio. De hecho, puede hacer AND directamente aquí, que no es más que juzgar si el resultado de AND es igual a 0, pero la negación aquí es principalmente para unificar la operación posterior al juicio y el valor de retorno. Después de hacer esto, la operación es la misma que set y, si ocurre el evento, el valor de retorno será el mismo que el valor de los indicadores del parámetro de entrada de la función; en otros casos, se devolverá 0 . Otra diferencia entre el modo CLR y el modo SET es que si se selecciona OS_OPT_PEND_FLAG_CONSUME, después de que ocurre el evento, p_grp->Flags |= flags_rdy realiza una operación OR para hacer coincidir e invertir los bits de bandera (SET se borra a 0, CLR se establece en 1) . ⑦ Llame a OSSched() para cambiar de tarea.Debido a que se puede ejecutar hasta este punto, significa que las tareas han entrado en la lista de espera, porque si esperan un evento o hay una operación no válida, ya regresaron . ⑧ Cuando la función se ejecuta aquí, significa que la tarea ha sido eliminada de la lista de espera, o el evento ha ocurrido, o ha expirado el tiempo de espera, o ha sido suspendida o eliminada; por lo tanto, se procesa de acuerdo con el estado de la tarea. A diferencia de otros objetos del kernel, debido a que existe la opción OS_OPT_PEND_FLAG_CONSUME, después de que ocurre este evento, la variable p_grp->Flag de la estructura del evento debe modificarse usando una operación AND o una operación OR según el modo del evento. Finalmente devuelve flags_rdy y sin errores.

- Llamar a OS_FlagBlock() :

① Primero asigne valores a los elementos TCB FlagsPend, FlagsOpt y FlagsRdy de la tarea. Debido a que en la función de creación de evento, se crea el evento y se recorrerá el estado de las tareas en la lista de espera, es necesario juzgar la tarea en espera en función del tipo de opción de evento de la tarea FlagsOpt (todos los eventos ocurren o cualquiera) y el indicador de evento en espera FlagsPend (qué eventos) El resultado es si llega el evento deseado. Si a FlagsRdy se le asigna un valor de 0, significa que el evento en espera aún no ha ocurrido, o si es 0, significa que el evento en espera no tuvo éxito. ② Llame a OS_Pend(). Esta función primero llama a OS_TaskBlock() para eliminar la tarea de la lista lista. Si hay un tiempo de espera, también insertará la lista de base de tiempo. Luego llame a OS_PendListInsertPrio() para insertar la tarea en la lista de espera según la prioridad.

}

}

Supongo que te gusta

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