I have some experience with Atmel AVR family and decided it's time to learn a RTOS. It's my first experience with both, ARM and ChibiOS.
I'm trying to write a library to exchange data between a STM32 and an ESP8266 module using ChibiOS Serial Driver. I started the project and while it does work I'm not sure I'm doing things in the proper way.
What I have done so far:
- Serial communication between STM32 and ESP8266 working;
- Serial communication between STM32 and PC working (debug purposes);
- Thread for sending messages to wifi module. I'm using messages to send data to this thread, I'm not sure it's the best solution or if it's implemented as it should be but it's working fine;
- Thread for receiving data from wifi module, actually it's just dumping this data on debug port.
How should I pass received data from wifi module to the function that is sending an AT command? When sending synchronous messages I'm using a pointer to a thread. How to proced when a thread have to send a message to a function?
Here is my code so far:
Code: Select all
/*
* esp8266.c
*
* Created on: 22/05/2017
* Author: Dolence
*/
#include "ch.h"
#include "hal.h"
#include "chprintf.h"
#include "esp8266.h"
#define READ_TIMEOUT 1000 // uart read timeout on 1000 ticks
#define WRITE_TIMEOUT 1000 // uart write timeout on 1000 ticks
static BaseSequentialStream * espStream = NULL;
static BaseSequentialStream * dbgStream = NULL;
binary_semaphore_t uart_bsem;
static thread_t *tWifiRx;
static thread_t *tWifiTx;
static const SerialConfig esp8266cfg = {
115200, //9600, // baud rate
0,
0,
0,
};
static const SerialConfig debugcfg = {
115200, //9600, // baud rate
0,
0,
0,
};
static THD_WORKING_AREA(waWifiRx, 128);
static THD_FUNCTION(WifiRx, arg) {
(void)arg;
event_listener_t elWifidata;
eventflags_t flags;
chEvtRegisterMask((event_source_t *)chnGetEventSource((SerialDriver *) espStream), &elWifidata, EVENT_MASK(1));
while (true) {
chEvtWaitOneTimeout(EVENT_MASK(1), MS2ST(10));
chSysLock();
flags = chEvtGetAndClearFlags(&elWifidata);
chSysUnlock();
if (flags & CHN_INPUT_AVAILABLE) {
msg_t charbuf;
do {
charbuf = chnGetTimeout((SerialDriver *) espStream, TIME_IMMEDIATE);
if (charbuf != Q_TIMEOUT) {
chSequentialStreamPut(dbgStream, charbuf);
}
}
while (charbuf != Q_TIMEOUT);
}
}
//return 0;
}
static THD_WORKING_AREA(waWifiTx, 128);
static THD_FUNCTION(WifiTx, arg) {
(void)arg;
while (true) {
thread_t *tp = chMsgWait();
msg_t msg = chMsgGet(tp);
chprintf(espStream, "%s", msg);
chMsgRelease(tp, MSG_OK);
}
}
int esp8266Init(SerialDriver * espDriver, SerialDriver * dbgDriver, int mode)
{
espStream = (BaseSequentialStream *) espDriver;
dbgStream = (BaseSequentialStream *) dbgDriver;
sdStart((SerialDriver *) espStream, &debugcfg);
sdStart((SerialDriver *) dbgStream, &esp8266cfg);
//cria o thread de recebimento
tWifiRx = chThdCreateStatic(waWifiRx, sizeof(waWifiRx), NORMALPRIO, WifiRx, NULL);
tWifiTx = chThdCreateStatic(waWifiTx, sizeof(waWifiTx), NORMALPRIO, WifiTx, NULL);
esp8266Cmd("AT+RST\r\n", "teste", 1000);
return 0;
}
bool esp8266Cmd(const char * cmd, const char * rsp, int cmddelay)
{
char buffer[200];
chsnprintf(buffer, sizeof(buffer), "%s", cmd);
chMsgSend(tWifiTx, (msg_t)buffer);
if (cmddelay > 0) chThdSleepMilliseconds(cmddelay);
//return esp8266ReadUntil(rsp, READ_TIMEOUT);
return 0;
}
bool esp8266ReadUntil(const char * resp, int timeout)
{
//to be implemented
thread_t *tp = chMsgWait();
//do while response doesn't arrive or timeout occurs
msg_t msg = chMsgGet(tp);
//
// ...
//
chMsgRelease(tp, MSG_OK);
}
And a pastebin for better readability: https://pastebin.com/G5VBU4ya
Any help, suggestions, tips would be much appreciated. Thanks!