Hello,
MBED still keeps me up at night. After being depressed for a while, I threw myself into work - I can’t walk away from an unresolved problem. Despite the problems with libraries, I still believe that the MBED concept is a good one, and if I can solve it, maybe it will help others…
I have made progress since last time.
Summary:
- I am working on my own board with STM32L433RC
- MCU is working with HSI clock (configured in mbed_app.json, others clock configurations are default)
- I use 3x UART and 1x LPUSART
- SPI to where the Wiznet W5500 IC is connected
- HW USB port to receive info messages
- I compile in MBED studio
- MBED OS 6.17
- I have the target set to Nucleo-L433RC-P (except for the different addresses of some pins that I don’t use the RC-P should have the same core as my RC)
So far the test program works by forwarding data to the USB when it receives data on the UART. In addition, once a minute it tries to connect to the LAN and MQTT broker and if connected sends a test message to the broker.
#include "TCPSocketConnection.h"
#include "mbed.h"
#include "USBSerial.h"
#include "EthernetInterface.h"
#include "MQTTClient.h"
#include "MQTTNetwork.h"
#include "MQTTmbed.h"
#include "cmsis.h"
#include <cstdio>
#define DEVICE_NAME "QRF reader"
#define DEVICE_ID "1707130195"
#define CLIENT_ID "17"
#define DEVICE_VERSION "v1.01"
#define MQTT_BROKER "192.168.0.103"
#define MQTT_PORT 1883
#define WATCHDOG_TIMEOUT_MS 20000 // 20 sekund
#define LOOP_SLEEP_MS 99
#define MQTT_KEEPALIVE 6000 // 100 minut udrzuje spojeni
#define NET_TIMEOUT_MS 2000
#define MAXIMUM_RX_BUFFER_SIZE 64
#define CARD_ID "123123123"
#define CARD_SOURCE "RFID reader"
// KONFIGURACE HW A PROPUSTNOSTI ZPRAV
bool RFID_reader_enabled = 1; // RFID reader je povolen prijem
bool QR_reader_enabled = 1; // QR reader je povolen prijem
bool Enable_USB = 1; // povoleni USB
bool connected_USB = 1; //
bool USB_Header_flag = 1; // posilani zprav s hlavickou
bool Enable_USBconfigMess = 1; // povoleni pomocných zpráv na USB
bool Enable_Ethernet = 1; // povoleni ethernetu
bool Enable_MQTT = 1; // povoleni MQTT
bool Enable_MODBUS = 0; // povoleni 485 MODBUS
bool Enable_IQRF = 0; // povoleni IQRF
uint8_t IQRF_NtwAdr = 0; // adresa IQRF zarizeni
// PRACOVNI PRIZNAKY
bool flag_publish_QRFinfo = 0; // priznak posilani pravidelneho info
bool flag_publish_info;
bool Button_flag = 0; // priznak stisku tlacitka
bool Block_front_LEDs_flag = 0; // blokovani LED na celnim panelu
char systemUSBmessage[] = ""; // pro USB zpravy
Watchdog &wd = Watchdog::get_instance();
uint8_t mac_addr[6]={0x00, 0x00, 0x00, 0xBE, 0xEF, 0x99};
const char* mqtt_broker = MQTT_BROKER;
const int mqtt_port = MQTT_PORT;
char const *topic_sub = "QRF/request/"DEVICE_ID;
char const *topic_cmnd = "cmnd/"DEVICE_ID"/";
char const *topic_pub = "QRF/response/"DEVICE_ID;
char lwt_topic[] = "QRF/"DEVICE_ID"/online";
char lwt_msg[] = "0";
char mqtt_clientid[] = CLIENT_ID;
unsigned long uptime_sec = 0;
bool connected_net = false;
bool connected_mqtt = false;
uint8_t conn_failures = 0;
USBSerial USB_port(false, 0x1f00, 0x2012, 0x0001); // USB port
//static BufferedSerial IQRF_port(PC_1, PC_0); // LPUART - IQRF reader port
BufferedSerial RFID_port(PA_9, PA_10); // UART1 - RFID reader port
//static BufferedSerial QR_port(PA_2, PA_3); // UART2 - QR reader port
// UART3 - 485
char RXbufferUSB[MAXIMUM_RX_BUFFER_SIZE] = {0}; // buffry pro zpravy
char TXbufferUSB[MAXIMUM_RX_BUFFER_SIZE] = {0};
char RXbufferRFID[MAXIMUM_RX_BUFFER_SIZE] = {0};
char RXbufferQR[MAXIMUM_RX_BUFFER_SIZE] = {0};
char RXbufferIQRF[MAXIMUM_RX_BUFFER_SIZE] = {0};
uint8_t USB_buffer_RX_length = 0;
uint8_t USB_buffer_TX_length = 0; // aktuálnà velikost buffru zprav
uint8_t RFID_buffer_length = 0;
uint8_t QR_buffer_length = 0;
uint8_t IQRF_buffer_RX_length = 0;
bool USB_RX_flag = 0; // priznaky prichozich zprav
bool RFID_RX_flag = 0;
bool QR_RX_flag = 0;
bool IQRF_RX_flag = 0;
bool flag_every_500ms = 0; // timer - nahrada za attach
bool flag_every_1s = 0;
bool flag_every_60s = 0;
int Times500ms = 0;
uint8_t Times1s = 0;
uint8_t Times60s = 0;
// vstupy a vystupy
// wiznet QRF PA_7, PA_6, PA_5, PA_4, PA_1
DigitalOut MCU_LEDG(PB_13); // OK zelena LED
DigitalOut MCU_LEDR(PB_12); // OK cervena LED
DigitalOut Rele(PB_5); // OK rele (posun oproti MCU-P)
DigitalOut Beep(PA_15); // OK pipak
DigitalOut RGB_Red(PC_2); // RGB ledky
DigitalOut RGB_Green(PC_3);
DigitalOut RGB_Blue(PA_8);
DigitalIn Button(PB_14); // OK tlacitko
DigitalOut MODBUS_EN(PC_12); // MODBUS
DigitalIn W_INT(PB_0);
DigitalIn QR_INT(PA_0);
void USB_SendSystemMessage();
bool networking_init(EthernetInterface &wiz);
bool mqtt_init(MQTTNetwork &mqttNet, MQTT::Client<MQTTNetwork, Countdown> &client);
void message_handler(MQTT::MessageData& md);
int publish(MQTT::Client<MQTTNetwork, Countdown> &client, const char* msg_type, const char* point, const char* payload, size_t payload_len, bool retain, MQTT::QoS qos);
int publish_value(MQTT::Client<MQTTNetwork, Countdown> &client, const char *topic, const char *buf, bool retain);
void publish_QRFinfo(MQTT::Client<MQTTNetwork, Countdown> &client);
void publish_QRFdata(MQTT::Client<MQTTNetwork, Countdown> &client);
void Rx_USB_Interrupt();
void Beeper();
void OpenGate();
void MCU_LEDR_Blink();
int main(void)
{
wd.start(WATCHDOG_TIMEOUT_MS);
MCU_LEDR = 0;
MCU_LEDG = 0;
RGB_Red = 0;
RGB_Green = 0;
RGB_Blue = 0;
Rele = 0;
Beep = 0;
RGB_Red = 1; // test signalizacnich LED
wait_us(3000000);
RGB_Red = 0;
RGB_Green = 1;
wait_us(3000000);
RGB_Green = 0;
RGB_Blue = 1;
wait_us(3000000);
RGB_Blue = 0;
sprintf(systemUSBmessage, "Devive: %s\n", DEVICE_NAME); USB_SendSystemMessage();
sprintf(systemUSBmessage, "Device ver.: %s\n\n", DEVICE_VERSION); USB_SendSystemMessage();
EthernetInterface wiz(PA_7, PA_6, PA_5, PA_4, PA_1);
MQTTNetwork mqttNetwork(&wiz);
MQTT::Client<MQTTNetwork, Countdown> client(mqttNetwork, NET_TIMEOUT_MS);
USB_port.set_blocking(false);
//IQRF_port.set_baud(19200); // IQRF
//IQRF_port.set_format(8,SerialBase::None,1); // byte, parita, stop bit
//IQRF_port.attach(&Rx_IQRF_Interrupt, SerialBase::RxIrq);
// system clock musi byt 3x - 4096x baudrate,
// pro 80MHz je povoleny baudrate 19531 - 26666666 bds
// test pro unbufered
//RFID_port.attach(&Rx_RFID_Interrupt, SerialBase::RxIrq);
//RFID_port.baud(9600); // RFID reader konfig
//RFID_port.format(8,SerialBase::None,1); // byte, parita, stop bit
//NVIC_SetPriority(USART1_IRQn, 240);
//RFID_port.set_blocking(false);
//test pro buffered
RFID_port.set_baud(9600); // RFID reader konfig
RFID_port.set_format(8,SerialBase::None,1); // byte, parita, stop bit
NVIC_SetPriority(USART1_IRQn, 240);
RFID_port.set_blocking(false);
//QR_port.set_baud(9600); // QR reader konfig
//QR_port.set_format(8,SerialBase::None,1); // byte, parita, stop bit
//QR_port.attach(&Rx_QR_Interrupt, SerialBase::RxIrq);
wd.kick();
while(1)
{
wait_us(10);
Times500ms++; // ticker 500ms, 1s, 60s
if (Times500ms == 50000)
{
flag_every_500ms = 1;
Times500ms = 0;
Times1s++;
if (Times1s == 2)
{
flag_every_1s = 1;
Times1s = 0;
Times60s++;
if (Times60s == 60)
{
flag_every_60s = 1;
Times60s = 0;
}
}
}
if(flag_every_500ms) // every 500ms
{
flag_every_500ms = 0;
if(!connected_net && !connected_mqtt)
{
MCU_LEDG = !MCU_LEDG;
}
}
if(flag_every_1s) // every 1s
{
flag_every_1s = 0;
if(connected_net && !connected_mqtt)
{
MCU_LEDG = !MCU_LEDG;
}
else if(connected_net && connected_mqtt)
{
MCU_LEDG = 1;
}
if (!Block_front_LEDs_flag) // pokud neni blokovano
{
RGB_Blue = !RGB_Blue; // blikam pripravenost na celnim panelu
}
wd.kick();
}
if(flag_every_60s) // every 60s
{
flag_every_60s = 0;
int LAN_link = wiz.link();
sprintf(systemUSBmessage, "Link: %d, LAN: %d, MQTT: %d\n", LAN_link, connected_net, connected_mqtt); USB_SendSystemMessage();
if(LAN_link !=1)
{
connected_net = 0;
connected_mqtt = 0;
}
else if (!connected_net && Enable_Ethernet)
{
connected_net = networking_init(wiz);
}
if (connected_net && !connected_mqtt)
{
connected_mqtt = mqtt_init(mqttNetwork, client);
}
if (connected_net && connected_mqtt) // pravidelny publish test
{
publish_QRFinfo(client);
publish_QRFdata(client);
client.yield(200);
}
//sprintf(systemUSBmessage, "ReInit UART\n"); USB_SendSystemMessage();
//BufferedSerial RFID_port(PA_9, PA_10);
//RFID_port.set_baud(9600); // RFID reader konfig
//RFID_port.set_format(8,SerialBase::None,1); // byte, parita, stop bit
//RFID_port.set_blocking(false);
wd.kick();
}
if ((Button) && (!Button_flag)) // stisk tlacitka
{
Button_flag = 1;
OpenGate();
}
if ((!Button) && (Button_flag)) // pustÄ›nĂ tlaÄŤĂtka
{
Button_flag = 0;
}
if (RFID_port.readable()) // prijem zpravy od RFID
{
wait_us(100000); // spoydeni pro celou zpravu do buffru
while ((RFID_port.readable()) && (RFID_buffer_length < MAXIMUM_RX_BUFFER_SIZE))
{
RFID_port.read(&RXbufferRFID[RFID_buffer_length],1);
++ RFID_buffer_length;
}
RFID_RX_flag = 1;
}
if ((RFID_RX_flag)||(QR_RX_flag)) // pri prijmu zpravy z RFID nebo QR
{
if (connected_USB) // je pripojeno USB? POSILAM
{
MCU_LEDR_Blink();
if (USB_Header_flag) // zprava s headrem?
{
TXbufferUSB[0] = 0xAA; // hlavicka
TXbufferUSB[1] = 0x00;
if (RFID_RX_flag) // je to od RFID?
{
RFID_RX_flag = 0;
TXbufferUSB[2] = 0x01; // RFID
for (int i=0; i<RFID_buffer_length; i++)
{
TXbufferUSB[i+3] = RXbufferRFID[i]; // data z RFID
} // paticka premazava posledni znak 0D
TXbufferUSB[(RFID_buffer_length + 2)] = 0xAA; // paticka
USB_buffer_TX_length = RFID_buffer_length + 3; // pak o jednu mene
RFID_buffer_length = 0;
}
if (QR_RX_flag)
{
QR_RX_flag = 0;
TXbufferUSB[2] = 0x02; //QR
for (int i=0; i<QR_buffer_length; i++)
{
TXbufferUSB[i+3] = RXbufferQR[i]; // data z QR
}
TXbufferUSB[(QR_buffer_length + 3)] = 0xAA; // paticka
USB_buffer_TX_length = QR_buffer_length + 4;
QR_buffer_length = 0;
}
}
else // bez hlavicky a paticky
{
if (RFID_RX_flag)
{
RFID_RX_flag = 0;
for (int i=0; i<(RFID_buffer_length-1); i++) // minus posledni znak 0D
{
TXbufferUSB[i] = RXbufferRFID[i]; // data z RFID
}
USB_buffer_TX_length = RFID_buffer_length;
RFID_buffer_length = 0;
}
else if (QR_RX_flag)
{
QR_RX_flag = 0;
for (int i=0; i<QR_buffer_length; i++)
{
TXbufferUSB[i] = RXbufferQR[i]; // data z QR
}
USB_buffer_TX_length = QR_buffer_length;
QR_buffer_length = 0;
}
}
USB_port.write(&TXbufferUSB, USB_buffer_TX_length); // tady je chyba - stridam buffry
sprintf(systemUSBmessage, " \n"); USB_SendSystemMessage();
}
USB_buffer_TX_length = 0; // az po odeslani vsech zprav
}
//ThisThread::sleep_for(10ms);
}
}
// posila na USB systemove informace
void USB_SendSystemMessage()
{
if (Enable_USBconfigMess)
{
USB_port.write((uint8_t *)systemUSBmessage, strlen(systemUSBmessage));
}
}
// and all others functions and procedures....
Wiznet and MQTT are already working well and without any failures - sending data every minute.
The UART only works fine for the first 60 seconds before the flag_every_60s is called. If data comes in on the UART after that the board crashes immediately and after 20s the watchdog restarts it.
- at first I suspected wiznet and MQTT, but the board crashes when receiving UART message even though the 60s part is completely empty (I don’t call LAN connection at all)
if(flag_every_60s) // every 60s
{} // empty
Similarly, I do the time loop on the 500ms, 1s and 60s flags completely inappropriately in main. If I use Ticker, then it crashes the very first time I receive a message on the UART.
Overall, it looks to me like the individual parts are working, but the problem is maybe somewhere in some Mutex/ISR collision although I don’t see it anywhere.
The problem is that I don’t have a single free serial port to send a crash report to and know more information.
Is there any way to send this information to the HW USB port, which is the only one I have available?
I tried to solve this problem by creating my own Custom Target, promising myself that I could then get messages over the ST-link I use to record. Unfortunately I was unable to create a custom custom target
The last thing is that I’m not at all sure if I have configured correctly the mbed_app.json and all necessary libraries are enabled. I’m using bare-metal profile and the MBED documentation says mutex is enable for example, so I believe it… Is it OK?
{
"requires": ["bare-metal", "events", "drivers-usb"],
"target_overrides": {
"*": {
"target.clock_source": "USE_PLL_HSI",
"target.lse_available": 0,
"target.default_lib": "small",
"target.printf_lib": "minimal-printf",
"platform.minimal-printf-enable-floating-point": true,
"platform.stdio-minimal-console-only": true,
"platform.stdio-baud-rate": 115200,
"platform.stdio-buffered-serial": 1,
"target.console-uart": false,
"target.console-uart-flow-control": null,
"target.device_has_add": ["USBDEVICE"]
}
}
}
I’m even less sure about the other configuration than this one I got from the demo example.
Also, the documentation mentions that: “arm microlib doesn’t support returning from main(); attempting to return from main() causes a bare metal application to crash. Here we show two ways to prevent this…”. It almost looks like my case, but I honestly don’t really understand what exactly is meant by that?
In principle, I don’t necessarily need the smallest possible configuration - I have 256k flash and I certainly won’t use it, so I can easily go to another configuration with more code and it doesn’t have to be bare-metal or microlib, if that solves my problem
P.S. JohnnyK won’t be at Embedded world in Nuremberg next week by any chance?
BR Lukas