
Sending 16 floats and a frame sync byte via UART.
00,00,00... F8
Thumbs up, all good, no warnings, no errors, no fuss, all good. Even watched the UART TDR register clocking 00's and even caught an F8 going out.
Working?
Hell no. That's not what the chip sends. It sends something completely different. The scope sees this:
00,00,00... 10 FF
Maybe the scope is wrong.
typedef struct Statistics_struct {
float rms[8];
float peak[8];
char FRAME_SYNC;
} Statistics_t;
Statistics_t stats[2];
Statistics_t *busy_stats = &stats[0];
Statistics_t *available_stats = &stats[1];
HAL_UART_Transmit_DMA(&huart2, (uint8_t*)&stats[0], sizeof(Statistics_t) * 2);
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart) {
if (huart == &huart2) {
busy_stats = &stats[1];
available_stats = &stats[0];
return;
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
if (huart == &huart2) {
busy_stats = &stats[0];
available_stats = &stats[1];
return;
}
Debug_UART_TxCpltCallback(huart);
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
Debug_UART_ErrorCallback(huart);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
Debug_UART_RxCpltCallback(huart);
}
bool handled = Analysis_Handle();
if (handled) {
haveHandled++;
}
if (haveHandled>10) {
haveHandled=0;
// snip LED indicator code
available_stats->rms[0] = *output1L.active_rms;
available_stats->rms[1] = *output1R.active_rms;
available_stats->rms[2] = *output2L.active_rms;
available_stats->rms[3] = *output2R.active_rms;
available_stats->peak[0] = *output1L.active_peak;
available_stats->peak[1] = *output1R.active_peak;
available_stats->peak[2] = *output2L.active_peak;
available_stats->peak[3] = *output2R.active_peak;
}
Nor can I keep 4 bytes alignment for floats that doesn't include the "char" somewhere.
There has to be padding or memory corruption.
The waveform for the full struct is too long to fit on the scope screen or it's decode list.
The waveform for the full struct is too long to fit on the scope screen or it's decode list.
Is it 5 ms/division for the bottom trace?
char* hex_char(char* tail_txt, uintptr_t* value)//44
{
int32_t tmp, jump; jump = 0;
*tail_txt = 0;
uint32_t vall = (uint32_t)value;
do{
tmp = vall & 0x0F;
if (tmp > 9 ) tmp += 0x37; else tmp += 0x30;
*(--tail_txt) = tmp;
jump += 4095;
vall >>= 4;
}while ((vall )||((jump & 4096) == 0));
*(volatile char*)--tail_txt = 'x';
*(volatile char*)--tail_txt = '0';
return tail_txt;
};
Very big nonsense to send a binary stream through UART. Not so - infinitely big nonsense!!!
UART is designed to transmit text, any control character will drown in the binary stream.
Any number can be made hex with minimal effort.
Arduino, ESP32, etc. all use UARTs
Absolutely nothing wrong with binary over UART.
The worst debugging nightmares I have seen have been with ASCII parsers, specifically those where the authors are not fully aware of all possible linefeed, implicit linefeed conversions due to existing systems, and how to write code that is robust regardless of any linefeed type (or conversions) used. That is entirely possible to do, just that even big companies like HP fail at it regularly.
Much more pain comes with deciding how to handle, if at all, backscpace and DEL controls. If not, there goes most of the human interoperability. If yes, that explodes parser complexity yet again. Whereas, the binary protocol has trivially simple parsers.
Binary is much slower to read and produce "by hand", but in all other respects, it's so much easier to deal with that I go with binary protocols a lot. This ease includes ease of debugging, due to having much simpler parsers.
Arduino, ESP32, etc. all use UARTs
Besides, the legacy of binary UART protocols go much further than that. MODBUS from 1970's is a relatively simple binary protocol over UART. There is an ASCII version because someone thought it would be simpler, but no one uses or wants to use that. MODBUS has a lot of weird complications but using binary is not among them - the ASCII version shares all the oddities, plus the increased agony of having to use ASCII.