Skip to content

Instantly share code, notes, and snippets.

@lorsi96
Last active May 3, 2021 21:26
Show Gist options
  • Save lorsi96/a57ba420d67c1ec4a93e4df10672d1d7 to your computer and use it in GitHub Desktop.
Save lorsi96/a57ba420d67c1ec4a93e4df10672d1d7 to your computer and use it in GitHub Desktop.
SEOS PONT Example with UART ISR
/*=============================================================================
* Copyright (c) 2021, Lucas Orsi <lorsi@itba.edu.ar>
* All rights reserved.
* License: MIT
* Date: 2021/05/03
* Version: 1.0
*===========================================================================*/
#include "sapi.h"
#include "seos_pont_2014_isr.h"
#include "seos_pont_2014_scheduler.h"
/*********************************************************************/
/* Mini Queue Pseudo-class */
/*********************************************************************/
#define MINI_QUEUE_SIZE (255)
#define T uint8_t
typedef struct {
T data[MINI_QUEUE_SIZE];
uint8_t index;
} MiniQueue;
/**
* @brief Pushes data into the queue.
*
* @param[in] queue to send data to.
* @param[in] data to be sent.
*/
static void MiniQueue_send(MiniQueue* queue, T data) {
queue->data[queue->index] = data;
queue->index = (queue->index + 1) % MINI_QUEUE_SIZE;
}
/**
* @brief Gets the oldest value available in the queue,
* and removes it afterwards.
*
* @param[in] queue to read data from.
* @param[out] data read from the queue.
* @return bool_t
*/
static bool_t MiniQueue_receive(MiniQueue* queue, T* data) {
if(queue->index) {
*data = queue->data[--queue->index];
return true;
} else {
return false;
}
}
/**
* @brief Resets all the data in a queue.
*
* @param queue queue to erase data from.
*/
static void MiniQueue_reset(MiniQueue* queue) {
queue->index = 0;
}
/*********************************************************************/
/* State Definitions */
/*********************************************************************/
/**
* @brief FSM States.
*
*/
typedef enum {
IDLE, /*< Waiting for the start character "<" to be received.*/
RECEIVING /*< Receiving characters until a ">" is captured. */
} msg_state_t;
/*********************************************************************/
/* Private Variables */
/*********************************************************************/
/**
* @brief Queue to store values from the uart interrupt.
*
* This is only relevant if incoming data from UART is faster
* than the main loop can handle.
*/
static MiniQueue uartBufferQueue = {{0}, 0};
/**
* @brief Queue to hold the incoming message to be echoed.
*
*/
static MiniQueue messageQueue = {{0}, 0};
static msg_state_t currentState = IDLE;
/*********************************************************************/
/* Interrupt Handler */
/*********************************************************************/
/**
* @brief Uart interrupt handler.
*
* Reads data and stores it into the #uartBufferQueue.
*
*/
void onRx(void* _) {
MiniQueue_send(&uartBufferQueue, uartRxRead(UART_USB));
}
/*************************************************************************/
/* App Constants */
/*************************************************************************/
/* Time between the reception of an end character and the echo response. */
#define RECEIVED_OK_DELAY_MS 1000
/* Characters to delimit the beginning and end of a message. */
#define BEGIN_CHAR '>'
#define END_CHAR '<'
/*************************************************************************/
/* Tasks Definitions */
/*************************************************************************/
static void ledWitnessTaskOn(void* _) {
gpioWrite(LEDG, true);
}
static void ledWitnessTaskOff(void* _) {
gpioWrite(LEDG, false);
}
void ackEchoTask(void* _) {
uartWriteString(UART_USB, "Recibido: ");
uartWriteString(UART_USB, (char*)messageQueue.data);
uartWriteString(UART_USB, "\n");
MiniQueue_reset(&messageQueue);
}
void uartCheckerTask(void* _) {
uint8_t newChar;
if(MiniQueue_receive(&uartBufferQueue, &newChar)) {
switch (currentState) {
case IDLE:
if(newChar == BEGIN_CHAR) {
schedulerAddTask(ledWitnessTaskOn, NULL, 0, 0);
currentState = RECEIVING;
}
break;
case RECEIVING:
if(newChar == END_CHAR) {
currentState = IDLE;
MiniQueue_send(&messageQueue, '\0');
schedulerAddTask(ledWitnessTaskOff, NULL, 0, 0);
schedulerAddTask(ackEchoTask, NULL, RECEIVED_OK_DELAY_MS, 0);
} else {
MiniQueue_send(&messageQueue, newChar);
}
default:
break;
}
}
}
/*********************************************************************/
/* App Main */
/*********************************************************************/
int main(void) {
boardConfig();
uartConfig(UART_USB, 115200);
uartCallbackSet(UART_USB, UART_RECEIVE, onRx, NULL);
schedulerInit();
uartInterrupt(UART_USB, true);
schedulerAddTask(uartCheckerTask, NULL, 0, 10);
schedulerStart(1);
for(;;) {
schedulerDispatchTasks();
}
return 0; // Should never reach here.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment