Preguntas sobre cómo obtener el código de implementación de la función mutex OSMutexPend() en la función mutex oficial de uCOS (stm32F4)

OSMutexPend() : Obtener la función mutex

{

Idea de función : la tarea tiene propiedad exclusiva del mutex. El mutex solo puede ser retenido por una tarea a la vez. Si el mutex está en el estado desbloqueado, entonces la tarea que adquiere el mutex adquirirá con éxito el mutex. y tiene el derecho a usar el mutex; si el mutex está en un estado bloqueado, la tarea que obtiene el mutex no podrá obtener el mutex y la tarea se suspenderá. La herencia prioritaria se realizará antes de que se suspenda la tarea . Si la prioridad de la tarea actual es mayor que la prioridad de la tarea que contiene el mutex, entonces la prioridad de la tarea que contiene el mutex aumentará temporalmente .

Cinco parámetros de entrada : puntero al mutex; tiempo de espera; opciones; marca de tiempo cuando se libera (0 significa que el mutex no se adquirió ni se liberó después de su creación; o el mutex está ocupado por otras tareas y la tarea no pudo obtener el mutex incluso después tiempo de espera); tipo de error de devolución

Proceso de función : ① Verificación de seguridad, verificación de opciones de parámetros, etc. Solo hay dos opciones: OS_OPT_PEND_BLOCKING y OS_OPT_PEND_NON_BLOCKING, que indican si la tarea debe bloquearse si otras tareas mantienen el mutex. ② Al ingresar a la sección crítica, si el mutex está disponible (estado desbloqueado) (el valor de OwnerNestingCtr es 0), luego modifique el valor del elemento mutex OwnerTCBPtr y asígnele el TCB actual; luego aumente OwnerNestingCtr en 1, lo que indica que el mutex es estado bloqueado; y asigne la marca de tiempo devuelta al valor del elemento de marca de tiempo en el mutex; llame a OS_MutexGrpAdd() para agregar el mutex a la lista vinculada de la tarea retenida por mutex, salga de la sección crítica; devuelva un tipo libre de errores, y volver volver. ③ Si la tarea actual adquiere el mutex nuevamente, entonces es necesario modificar el elemento OwnerNestingCtr del mutex para aumentar su valor en 1; devolver la marca de tiempo; salir de la sección crítica; devolver el tipo de error "OS_ERR_MUTEX_OWNER" y regresar. ④ Si el mutex está ocupado por otras tareas y el tipo de opción es OS_OPT_PEND_NON_BLOCKING, se devolverá el error "OS_ERR_PEND_WOULD_BLOCK". ( Bajo la condición de que la tarea seleccione "sin bloqueo", puede utilizar este tipo de retorno para determinar si el mutex está ocupado por otras tareas ). ⑤ Si el mutex está ocupado por otras tareas, el tipo de opción es "OS_OPT_PEND_BLOCKING", primero verifique si el programador está bloqueado ( porque la tarea debe agregarse a la lista de espera, si el programador está bloqueado, no se pueden realizar operaciones de tareas); si no está bloqueado, llame a OS_CRITICAL_ENTER_CPU_EXIT() para bloquear el planificador pero habilite las interrupciones; si la prioridad de la tarea actual es mayor que la prioridad de la tarea que obtiene el mutex, llame a OS_TaskChangePrio() para modificar la prioridad del tarea que obtiene el mutex; llame a OS_Pend() para agregar la tarea a la lista de espera del mutex; llame a OS_CRITICAL_EXIT_NO_SCHED() para desbloquear el programador y no cambiar; luego llame a OSSched() para cambiar (porque la tarea aquí ha entrado en la lista de espera del mutex y está bloqueado, así que cambie). ⑥ El contexto se guarda después del cambio. Si se ejecuta aquí nuevamente, significa que la tarea debe haberse recuperado del estado de bloqueo antes de que pueda continuar programándose. Luego se debe juzgar de acuerdo con el estado de la tarea si se debe esperar hasta que se restaura el mutex o se agota el tiempo de recuperación, etc. Si el estado de la tarea es "OS_STATUS_PEND_OK", significa que obtuvimos el mutex, devuelve la marca de tiempo y no hay error; si el estado de la tarea es "OS_STATUS_PEND_ABORT", devuelve la marca de tiempo de espera de terminación y el error de "espera de terminación"; si es "OS_STATUS_PEND_TIMEOUT", la marca de tiempo de retorno es 0, lo que indica que no se ha obtenido el mutex y se devuelve un error de "tiempo de espera de espera"; si es "OS_STATUS_PEND_DEL", se devuelve un error de que el mutex se ha eliminado; otro Los estados no relacionados con la espera no son válidos.

- Llamar a OS_TaskChangePrio() :

Nota : ① Porque mientras la tarea contenga el mutex, tendrá propiedad sobre él. Solo esperar a que la tarea llame a la función que libera el mutex hará que el mutex esté disponible. Por lo tanto, la tarea puede estar en varios estados antes de llamar a la función de liberación mutex , como estado listo: después de crear la tarea, la tarea se insertará en la lista lista. Si la inserción es exitosa, el estado de la tarea se modificará a listo. estado Durante el proceso de ejecución de la tarea, si Cuando se llaman funciones que involucran cambios de estado de la tarea, el estado de la tarea es el estado listo. Por ejemplo, en el estado de retraso: si se llama a la función de retraso de bloqueo, la tarea se eliminará de la lista lista, se insertará en la lista de base de tiempo, la inserción será exitosa y el estado cambiará a retraso. estado; si se llama antes de que la tarea haya liberado el mutex, la tarea está en un estado retrasado. Por lo tanto, la prioridad de la tarea debe modificarse según el estado de la tarea . ② Esta función se llama en la función OSMutexPend() que obtiene el mutex. Antes de llamar a esta función, se ha llamado a OS_CRITICAL_ENTER_CPU_EXIT() para bloquear el programador para evitar el cambio de tareas y cambios de estado (como insertar la lista de base de tiempo, lista de espera, etc.). ③ Después de modificar la prioridad, la tarea debe insertarse en la lista lista bajo la prioridad correspondiente.

Dos parámetros de entrada : puntero a la tarea TCB que contiene el mutex; la prioridad a reemplazar

Proceso de función : Es un bucle do- while y la condición del bucle es que el puntero TCB no esté vacío. El cuerpo del bucle es modificar la prioridad de la tarea de acuerdo con el estado de la tarea y las operaciones realizadas para modificar la prioridad. ( El propósito del bucle do- while aquí es resolver el problema de que la tarea que contiene el mutex está bloqueada en la lista de espera de otros mutex al acceder a recursos protegidos por otros mutex ). ① Si está en el estado listo, significa que la tarea aún se está ejecutando o no se ha cambiado a la tarea . Para evitar que se modifique el estado de ejecución de la tarea cuando se modifica la prioridad de la tarea, primero llame a OS_RdyListRemove() para eliminar la tarea de la lista lista (si no hay tareas bajo esta prioridad después de la eliminación, esta función borrará la prioridad correspondiente tabla al mismo tiempo. bit de prioridad ); así que después de modificar la prioridad de la tarea, llame a OS_PrioInsert() para establecer 1 en la posición correspondiente de la tabla de prioridades. Esta función utiliza el algoritmo o para establecer 1, por lo que no hay necesidad de preocuparse por la duplicación y afectando otras posiciones; porque el estado listo tiene Hay dos situaciones: la tarea se está ejecutando, por lo que después de modificar la prioridad, se debe insertar en el encabezado de la lista lista para que pueda continuar ejecutándose; la segunda situación es que es posible que aún no se haya cambiado a él (pero contiene el mutex y (no liberado), la tarea actual no es igual a la tarea que contiene el mutex, luego la tarea que contiene el mutex se inserta al final de la lista lista. Debido a que la prioridad aumenta, no se puede insertar en el cabezal para permitir otras tareas de alta prioridad y el tiempo de espera para que se ejecuten las tareas se vuelve más largo.. ② Si el estado de la tarea es retrasado, suspendido, retrasado + suspendido, solo se cambia la prioridad de la tarea que contiene el mutex, porque cuando la tarea está en estos estados, se elimina de la lista lista y se modifica la prioridad. cambian al estado listo, se insertan automáticamente en la lista lista según su prioridad. ③ Si está esperando, tiempo de espera de espera, espera + colgado, tiempo de espera de espera + colgado, porque también se elimina de la lista lista, además de modificar la prioridad como ②, también necesita acceder al elemento pendiente de la tarea para ver lo que espera la tarea. . Si no está esperando un mutex (como esperar un semáforo, una cola de mensajes, etc.), debe llamar a OS_PendListChangePrio () para modificar la posición de la tarea en la lista de espera, porque la lista de espera es unidireccional. La lista vinculada se encadena de acuerdo con la prioridad de la tarea. La prioridad de la tarea modificada, por supuesto, debe modificarse en la lista vinculada. ④ Debido a que una tarea puede contener múltiples mutex y acceder a múltiples recursos protegidos, si está esperando un mutex, además de llamar a OS_PendListChangePrio () para modificar la posición de la tarea en la lista de espera de mutex, porque la tarea está en otros mutex En el lista de espera de mutex, y debido a que se ha aumentado la prioridad, es necesario determinar si es necesario aumentar la prioridad de otra tarea de mutex. Si es necesario, debe repetir el proceso anterior, porque esta función se usa para modificar la prioridad de la tarea que contiene el mutex ; si no, entonces no es necesario repetir el proceso anterior y salir del bucle . Sólo hay una situación necesaria: la prioridad de la tarea en la lista de espera es mayor que la prioridad de la tarea que tiene el mutex. Sin embargo, los funcionarios de uCOS no escribieron el código de sentencia como se muestra a continuación.

Debido a que la función OS_TaskChangePrio() no solo puede cambiar la prioridad a un nivel superior, sino también cambiar la prioridad a un nivel inferior , y no solo cambia la prioridad de las tareas que contienen mutex, otras tareas también pueden llamar a esta función para cambiar la prioridad durante la ejecución.nivel . Es solo que la función mutex OSMutexPend () se obtiene aquí y llama a OS_TaskChangePrio () para heredar la prioridad y cambiar la prioridad a un valor mayor. Por lo tanto, uCOS distingue oficialmente dos situaciones: una es cambiar la prioridad a un valor menor, prio_cur > prio_new; la otra es mantenerla sin cambios o cambiarla a un valor mayor .

Pero sigo pensando que la lógica oficial es errónea :

Publicaré mi lógica y espero que puedan darme algún consejo:

Supongo que te gusta

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