Tengo una situación en la que un microcontrolador debe realizar una gran cantidad de conversiones de ADC y formatear los resultados en comandos (o paquetes de datos) y enviarlos a una PC utilizando el UART. Para medir continuamente mientras envío datos, creé un búfer circular (cola / FIFO-buffer) para almacenar los paquetes pendientes, y el microcontrolador vaciará (lo ideal) esta cola tan rápido como lo permita la PC.
El microcontrolador envía automáticamente el siguiente comando (si lo hubiera) después de que se haya recibido un carácter ACK (en este caso, un ''! ''). El controlador de interrupciones de UART es así:
if (ch == '!') // ch is the received character
{
cmd_rx_ack = '!';
cmd_tx_pop_cmd();
}
La función cmd_tx_pop_cmd () está sacando un paquete del búfer circular y colocando los bytes en una matriz cmd_tx [] y la longitud del paquete en cmd_tx_length.
En el bucle principal:
if (cmd_rx_ack == ‘!’)
{
cmd_rx_ack = 0; // Reset ack status
// Transmit the command
if (cmd_tx_length > 0)
{
cmd_tx_transmit();
}
}
La función cmd_tx_transmit () simplemente transmite los bytes en cmd_tx [] uno por uno (esto se hace en el bucle principal, ya que lleva mucho tiempo hacerlo en el controlador UART).
Esto funciona bien, si el consumidor de la cola (en este caso, el controlador UART) tiene una prioridad más alta que el productor (un temporizador que periódicamente hace que el ADC convierta y envíe un paquete de datos con el resultado en la cola). Anteriormente tuve problemas de concurrencia (consulte Problemas de concurrencia con el búfer circular en incrustado programa ) pero ahora tengo otro problema:
Quiero que el microcontrolador envíe el siguiente paquete en la cola, no solo cuando se haya recibido un ACK, sino también en las situaciones enumeradas a continuación:
- El primer paquete que se transmitirá
- Si las mediciones se realizan a una velocidad más lenta que el tiempo que se tarda en enviar un paquete.
En la primera situación, el paquete nunca se transmite, ya que no se recibe ningún ACK después de que el paquete se coloca en la cola.
En la segunda situación, los paquetes nunca se sacan de la cola por el mismo motivo que en la primera situación. (Supongamos que el primer paquete es ACKed y el controlador UART desea transmitir el siguiente, pero la cola está vacía en este momento). En este caso, la cola es cada vez más grande y no se transmiten paquetes.
Puedo resolver el primero transmitiendo el primer paquete manualmente (sin el uso de la cola) y poner el resto en la cola. Sin embargo, no es una solución bonita, pero funciona ... todavía tengo que resolver el segundo problema.
Por lo tanto, creo que el controlador UART no es el lugar correcto para hacer la cola de espera ya que no puede tomar en cuenta las dos situaciones que acabo de mencionar. Pero no puedo ponerlo en el bucle principal, ya que tiene la prioridad más baja y luego los problemas de concurrencia se convierten en un problema.
¿Cuál sería una buena manera de implementar esto?
Gracias de antemano :-)
BTW 1: un ACK se transmite al microcontrolador si la PC acepta el paquete transmitido. He hecho una codificación especial de los paquetes para poder determinar su longitud. Esto funciona bien y cmd_tx_pop_cmd () solo mostrará el primer paquete disponible en la cola. He probado todo esto muchas, muchas veces y funciona perfectamente, así que no se centre en esta parte ya que no es el problema.
BTW 2: El microcontrolador es un TM4C123GH6 de la serie Tiva C que se encuentra en el Launchpad de la serie C de Tiva. Estoy usando gcc-arm-none-eabi.