Actualización crítica del Serial-libOpenCM3

¡IMPORTANTE!

Como habrían visto en mi blog, codifique una lib para utilizar el puerto Serie (UART) con la BluePill con libOpenCM3. Pero debo hacer un mea culpa, ya que debido a un pequeño error la comunicación se congelaba después de transmitir/recibir 65536 datos. Por ello, deben sí o sí utilizar la versión v0.4.3 (la actual) en adelante.

El error

Para entender el error, debemos analizar la implementación del buffer circular y la arquitectura de 32bits. Mi lib, para manejar los buffers, utiliza indices declarados como enteros sin signo de 16bits. Como analizamos en un post de AVR, los buffers circulares tienen 2 índices, uno de entrada [tail](por donde se insertan los datos), y otro de salida [head]. La condición para que empiece la transmisión es que la resta entre el de entrada y salida sea 1, lo cual codifiqué de la siguiente manera:

if((index_in - index_out) == 1) { strart_tx(); }

Lo cual no supone problemas, ya que cuando estamos en el desborde (0 – 65535), el resultado es 1… claro, siempre y cuando el 0 y el 65535 sean enteros sin signo de 16bits. ¿Por qué? Muy fácil, para entenderlo tenemos que recordar como restan las computadoras (en CA2), es decir que la resta es la suma del Complemento a 2:

  3  -   4  =>   3  + (-4) =  -1
0011 - 0100 => 0011 + 1100 = 1111

Entonces, ¿qué pasa cuando estamos en el mayor número entero natural? Veamos:

  0  -  15  =>   0  +   1  =   1
0000 - 1111 => 0000 + 0001 = 0001

Esto ocurre porque el 15 en binario natural equivale al -1 en CA2, así que mi código como estaba más arriba no debería de fallar pero, pero, pero… El problema es que el STM32F103 es un ARM Cortex-M de 32 bits, por lo tanto las operaciones son en 32bits y la comparación con [resultado] == 1 este es de 32bits y el resultado también, o sea, que la operación de dos variables de 16bits estaban siendo promocionadas a 32bits, por lo tanto, el resultado estaba lejos de ser 1.

La solución

La solución es muy sencilla, se podría declarar una variable auxiliar, como:

uint16_t res = index_in - index_out;
if(res == 1) { strart_tx(); }

Pero, gastar una variable de más no sería una solución apropiada. Por ello, lo mejor, es «exigirle» al compilador de que el resultado sea un entero sin signo de 16bits. Con un simple casteo, santo remedio:

if ((uint16_t)(index_in - index_out) == 1) { start_tx(); }

Conclusión

Este pequeño (e imperceptible) error, nos recuerda que debemos ser cuidadosos con las operaciones que hacemos y testear bien las funcionalidades en los límites. En C tenemos el control absoluto de lo que ocurre, y con este casteo es aún más portable a otras arquitecturas (8, 16, 64, etc.)

Pueden ver el repo en gitlab o la lib en PlatformIO.

En un futuro próximo voy a extender la lib para poder utilizarla con cualquier STM32F1xx y luego a los otros STM32Fxxx.

msavalos

Soy un hobbista: toco la guitarra, mandolina, descompongo en partituras; también soy aficionado a la fotografía, he hecho algún cursillo por ahí; me encanta la programación, sea de un programa de PC para procesar datos, una interfaz gráfica o un microcontrolador; evidentemente linuxero; y, cayéndose de maduro, geek. Hincha del más grande, técnico en electrónica, ex-estudiante de ingeniería en electrónica en la UTN FRBA, Técnico Superior en Informática y Profesor. Doy clases en el nivel medio en el Gobierno de la Ciudad de Buenos Aires e instituciones privadas y a nivel terciario en una sede dependiente de la UTN. Sobre mi afinidad política, bueno, podría decir que soy militante del Software Libre y medio zurdito (no me ofende).

Entradas recientes

Páginas embebidas con ESP8266 (WebServer)

Nivel: Básico ¿Qué tengo que saber para este post? Diseño básico de páginas con HTML…

3 años hace

Modificación de fuente ATX para laboratorio.

Nivel: Avanzado. La modificación de fuentes ATX para su utilización en laboratorio o comunicaciones es…

3 años hace

FLISoL Shield ARDUINO

El pasado 23 de abril se celebró la 18° edición del FLISoL en la que…

3 años hace

Regulador de tensión MOSFET para Moto.

Circuito del regulador, con los elementos de simulación. Típicamente, las motocicletas de baja cilindrada utilizan…

3 años hace

Review Analizador Lógico de menos de u$s10 en Linux

¿Qué puedo decir? Siempre quise tener un analizador lógico, había visto estos pequeños y baratos…

4 años hace

Oversampling con bajos recursos (+Bits ADC)

Nivel: Intermedio ¿Qué tengo que saber para este post? Entender el uso de un ADC.Programación…

4 años hace

Esta web usa cookies.