Soy un miembro de pregrado de un equipo de investigación que trabaja en un proyecto que involucra un ASIC transmisor de RF y su receptor inalámbrico que finalmente debería enviar datos a una PC.
El receptor emite una señal serial rápida , continua, asíncrona, no estándar (es decir, no SPI, I2C, UART, etc.), por lo que mi trabajo es escribir un software de microcontrolador para conectar el receptor a la computadora. Actualmente, mi enfoque es utilizar interrupciones activadas por bordes para colocar los datos en un búfer circular y hacer todo el proceso de decodificación bit a bit en el bucle principal. El microcontrolador debe emitir simultáneamente estos datos mediante USB (puerto de comunicación virtual) a la computadora.
Aquí hay un problema que estoy teniendo y que estoy anticipando:
No puedo procesar los datos almacenados en el búfer lo suficientemente rápido, incluso con mi potente procesador ARM Cortex M3 de 72 MHz. La velocidad de bits es de 400 Kbps (2.5 us / bit). Como referencia, solo deja 180 ciclos por bit (incluida la decodificación Y el ISR, que tiene ~ 30 ciclos de sobrecarga). El MCU también tiene que manejar muchas otras tareas que sondea en el bucle principal.
El controlador del puerto de comunicaciones virtual USB también está basado en interrupciones. Esto me hace casi seguro de que el controlador eventualmente tendrá el procesador interrumpido durante tanto tiempo que se perderá la ventana de 2.5 microsegundos (180 ciclos) en la que se puede transmitir un bit. No estoy seguro de cómo normalmente se resuelven los conflictos / carreras de interrupción como esta.
Entonces, la pregunta es simple, ¿qué podría uno hacer para resolver estos problemas o no es este el enfoque correcto? Estoy dispuesto a considerar enfoques menos centrados en el software también. Por ejemplo, el uso de un chip USB dedicado con algún tipo de máquina de estado de hardware para la decodificación, pero este es un territorio desconocido.
Respuestas:
Otra respuesta: deja de usar interrupciones.
La gente salta para usar las interrupciones con demasiada facilidad. Personalmente, rara vez los uso porque en realidad pierden mucho tiempo, como están descubriendo.
A menudo es posible escribir un bucle principal que sondea todo tan rápido que su latencia está dentro de las especificaciones, y se desperdicia muy poco tiempo.
Puede haber algunas cosas en el ciclo que suceden con mucha más frecuencia que otras. Quizás los bits entrantes, por ejemplo, en cuyo caso, agreguen más de esas pruebas, de modo que una mayor parte del procesador se dedique a esa tarea.
Puede haber algunos eventos para los cuales la latencia de este enfoque es demasiado alta. Por ejemplo, es posible que necesite un evento cronometrado con mucha precisión. En cuyo caso, tenga ese evento en interrupción y tenga todo lo demás en el bucle.
fuente
Posiblemente podría usar un FPGA en lugar de un Microcontrolador para decodificar y almacenar en búfer el flujo de datos inalámbrico. Luego, use el procesador ARM para vaciar los búferes de FPGA (por ejemplo, usando una interfaz SPI) y envíe el contenido al puerto de comunicación USB. Es un trabajo, pero un FPGA debería ser capaz de mantenerse fácilmente siempre que pueda repararlo con la frecuencia suficiente para garantizar que sus memorias intermedias de hardware no se desborden (o si puede manejar los datos caídos en un nivel superior del protocolo) )
fuente
Fácil: use un microcontrolador PSoC5 .
Tiene toda la facilidad de uso de un microcontrolador, además contiene un CPLD, por lo que puede escribir sus propios periféricos de hardware en Verilog. Simplemente escriba su decodificador de datos en serie en verilog y use DMA para transmitirlo al puerto USB.
Mientras tanto, el poderoso núcleo ARM de 32 bits puede hacer girar sus instrucciones Thumb.
fuente
Creo que tiene que hacer una elección de ingeniería clásica: rápida, barata, funciona: elija dos.
La solución de @vicatcu es ciertamente una buena, pero si no puede o no le agregará más hardware (y esto incluye un procesador más rápido), entonces debe elegir. Si este enlace en serie es el más importante, debe sentarse en el ISR hasta que se hayan recopilado todos los bits. 180 instrucciones por bit en realidad no está nada mal, pero no intentes hacer todo. Cuando detecte el inicio de una transferencia, gire hasta que se complete la transferencia. Rellene el resultado en un FIFO y luego reanude el procesamiento normal.
No dice cuánto dura cada transmisión, pero si son cortas y con ráfagas, esta sería una solución viable. Estoy dispuesto a apostar que su implementación de puerto COM virtual también tiene algo de almacenamiento en búfer de hardware, por lo que un servicio de interrupción "lento" no debería presentar demasiados problemas. En cuanto al resto de lo que necesita hacer el MCU ... tiene que tomar algunas decisiones de diseño.
fuente
En primer lugar, me gustan algunas de las respuestas aquí, y algunas me han votado.
Pero solo para agregar otra posible solución: dadas las limitaciones de su proyecto, ¿sería malo agregar un segundo microcontrolador (eso implicaría otra ejecución de la placa)? Tal vez un microcontrolador simple de 8 bits que se conecta a su Cortex-M3 a través de un periférico rápido como SPI. El controlador de 8 bits de su elección sondearía los bits y formaría bytes al igual que en la respuesta seleccionada, pero cuando tiene un byte, podría volcarlo en el registro de datos SPI para transferirlo.
El lado de la corteza-M3 simplemente interrumpiría los datos SPI recibidos. Eso reduce su interrupción anterior activada por borde externo de 400 KHz a 50 KHz.
Las dos razones por las que sugiero esto se deben a que algunos de los otros métodos (PSoC o FPGA agregado) son un poco caros (aunque esto probablemente no importa para un proyecto académico de bajo volumen) y porque puede permitirle preservar algunos de La estructura de su código actual.
Aparte de eso, creo que la idea de PSoC es increíble con su propia transferencia periférica personalizada a través de DMA a USB.
fuente
Si su formato de datos es similar al de un UART, pero a una velocidad de transmisión impredecible pero constante, mi inclinación sería utilizar un CPLD para convertir cada palabra de datos entrantes en formato SPI o asíncrono estándar. No creo que haya ninguna necesidad de introducirse en el ámbito de los CPLD. En realidad, incluso la lógica discreta casi podría funcionar. Si pudiera generar un reloj que fuera un smidgin más de 5 veces su velocidad de datos deseada, podría usar un contador dividir por cinco y dividir por 16 con algunas puertas. Organice el contador de división por cinco para que se mantenga en restablecimiento siempre que la entrada esté inactiva y el contador de división por 16 esté en cero. De lo contrario, genere un pulso de reloj SPI y golpee el contador de división por 16 cada vez que el contador de división por cinco llegue a 2.
Dado el reloj 5x, uno podría generar el reloj SPI usando un 16V8 (el dispositivo lógico programable más pequeño y más barato disponible actualmente). Un segundo 16V8 o 22V10 podría usarse como un divisor de tasa fraccional para generar el reloj 5x, o uno podría usar un chip ligeramente más grande (CPLD) y hacer todo en uno.
Editar / Anexo
Tras una consideración adicional, si se va a utilizar un CPLD, se pueden agregar fácilmente algunas mejoras adicionales al circuito. Por ejemplo, uno puede agregar lógica con bastante facilidad para que el circuito se detenga hasta que reciba al menos 1,5 bits de bit de parada, seguido de 3,5 bits de bit de inicio; si recibe un bit de inicio demasiado corto, debería volver a buscar el bit de detención. Además, si uno está usando SPI, podría usar la señal / CS para asegurarse de que el dispositivo receptor verá los datos correctamente enmarcados. Si el dispositivo que recibe los datos SPI puede manejar tramas de 10 bits, uno podría enviar dichas tramas directamente. De lo contrario, cada trama de diez bits podría enviarse como una trama de 8 bits con el conjunto LSB (7 bits de datos) y una trama con todos los LSB libres (3 bits de datos); el reloj SPI se aceleraría durante los bits de parada, por lo que se enviarían todos los datos.
Algunos microcontroladores tienen módulos de generación PWM bastante versátiles que incluyen cosas como la capacidad de mantenerse en restablecimiento mediante una señal externa y sincronizar su sincronización con la liberación de dicha señal. Si su microcontrolador puede hacer eso, dependiendo de sus características exactas, eso podría simplificar considerablemente el CPLD o los circuitos de generación de tiempo.
Otro enfoque que Rocketmagnet mencionó de alguna manera sería tener un micro pequeño cuyo único propósito es decodificar los datos en serie y convertirlos a un formato que pueda usar el micro principal. Su velocidad de datos de 400KHz es bastante rápida para la decodificación de software, pero algo como un PIC podría manejarlo si no tuviera que hacer nada más al mismo tiempo. Dependiendo de los dispositivos con los que esté familiarizado, esto podría ser más fácil o más difícil que usar un CPLD.
fuente