For anyone else wondering about how to create a queue to transmit UART packets I've mentioned above.
- I'm using a Nucleo-L432KC for this.
- I've copied some of @AkilaAwantha Drive Mode arrays for this demonstration
- The full project can be found on GitHub
PollingRoutine.c
/*
* PollingRoutine.c
*
* Created on: Dec 17, 2022
* Author: codek
*/
#include "main.h"
#include "PollingRoutine.h"
extern UART_HandleTypeDef huart2;
UART_QueueStruct txMsg = {0};
uint32_t someState;
//Drive Mode
uint8_t EcoON[8] = { 0x5A, 0xA5, 0x05, 0x82, 0x10, 0x55, 0x01, 0xBA };
uint8_t NormalON[8] = { 0x5A, 0xA5, 0x05, 0x82, 0x10, 0x55, 0x01, 0xBC };
uint8_t SportON[8] = { 0x5A, 0xA5, 0x05, 0x82, 0x10, 0x55, 0x01, 0xBE };
uint8_t modeClear[8] = { 0x5A, 0xA5, 0x05, 0x82, 0x10, 0x55, 0x00, 0x00 };
// is called before main while loop
void PollingInit(void)
{
someState = 1; // send EconON
}
// main while loop
void PollingRoutine(void)
{
SomeTask();
UART_SendMessage();
}
// basic example of how to save data to txMsgQueue queue buffer
void SomeTask(void)
{
int status = 0;
switch(someState)
{
case 1:
status= SaveToUART_TxBuffer(EcoON, sizeof(EcoON));
break;
case 2:
status = SaveToUART_TxBuffer(NormalON, sizeof(NormalON));
break;
case 3:
status = SaveToUART_TxBuffer(SportON, sizeof(SportON));
break;
case 4:
status = SaveToUART_TxBuffer(modeClear, sizeof(modeClear));
break;
}
if(status != 0)
{
// buffer is full. Use some notification so user is aware and can increase UART_TX_QUEUE_SIZE
}
someState = 0;
}
int SaveToUART_TxBuffer(uint8_t *data, uint32_t dataSize)
{
if(txMsg.RING_BUFF.ptr.iCnt_OverFlow)
{
return 1; // Overflow. Increase UART_TX_QUEUE_SIZE
}
memcpy(&txMsg.QUEUE.msg[txMsg.RING_BUFF.ptr.iIndexIN].data, data, dataSize);
txMsg.QUEUE.msg[txMsg.RING_BUFF.ptr.iIndexIN].dataSize = dataSize;
DRV_RingBuffPtr__Input(&txMsg.RING_BUFF.ptr, UART_TX_QUEUE_SIZE);
return 0; // no error
}
void UART_SendMessage(void)
{
if(txMsg.RING_BUFF.ptr.iCnt_Handle)
{
if(HAL_UART_Transmit_IT(&huart2, txMsg.QUEUE.msg[txMsg.RING_BUFF.ptr.iIndexOUT].data, txMsg.QUEUE.msg[txMsg.RING_BUFF.ptr.iIndexOUT].dataSize) == HAL_OK)
{
// transmit is good, increment queue pointer to next available message
DRV_RingBuffPtr__Output(&txMsg.RING_BUFF.ptr, UART_TX_QUEUE_SIZE);
}
}
}
PollingRoutine.h
/*
* PollingRoutine.h
*
* Created on: Dec 17, 2022
* Author: codek
*/
#ifndef INC_POLLINGROUTINE_H_
#define INC_POLLINGROUTINE_H_
#define UART_TX_DATA_SIZE 8
#define UART_TX_QUEUE_SIZE 4
typedef struct
{
uint8_t uartPort;
uint8_t data[UART_TX_DATA_SIZE];
uint8_t dataSize;
}UART_Data;
typedef struct
{
struct
{
UART_Data msg[UART_TX_QUEUE_SIZE];
}QUEUE;
struct
{
RING_BUFF_INFO ptr;
}RING_BUFF;
}UART_QueueStruct;
void PollingInit(void);
void PollingRoutine(void);
void SomeTask(void);
int SaveToUART_TxBuffer(uint8_t *data, uint32_t dataSize);
void UART_SendMessage(void);
#endif /* INC_POLLINGROUTINE_H_ */
RingBuff.c
/*
* RingBuff.c
*
* Created on: Sep 18, 2019
* Author: Karl
*
*
*/
#include "main.h"
#include "ringBuff.h"
/*
typedef struct {
uint16_t iIndexIN; // change all these if need more than 16bits.
uint16_t iIndexOUT;
uint16_t iCnt_Handle;
uint16_t iCnt_OverFlow;
}RING_BUFF_INFO;
*/
//==========================================================
// Layer : DRIVER
//==========================================================
void DRV_RingBuffPtr__Clean(RING_BUFF_INFO *ptr) {
ptr->iIndexIN = 0;
ptr->iIndexOUT = 0;
ptr->iCnt_Handle = 0;
ptr->iCnt_OverFlow = 0;
}
void DRV_RingBuffPtr__Input(RING_BUFF_INFO *ptr, unsigned int iBufferSize) {
ptr->iIndexIN++;
if (ptr->iIndexIN >= iBufferSize)
ptr->iIndexIN = 0;
ptr->iCnt_Handle++;
if (ptr->iIndexIN == ptr->iIndexOUT) {
ptr->iCnt_OverFlow++;
if (ptr->iCnt_OverFlow > 50000)
ptr->iCnt_OverFlow = 0;
if (ptr->iIndexIN == 0) {
ptr->iIndexOUT = iBufferSize - 1;
} else {
ptr->iIndexOUT = ptr->iIndexIN - 1;
}
ptr->iCnt_Handle = 1;
}
}
void DRV_RingBuffPtr__Output(RING_BUFF_INFO *ptr, unsigned int iBufferSize) {
if (ptr->iCnt_Handle) {
ptr->iIndexOUT++;
if (ptr->iIndexOUT >= iBufferSize)
ptr->iIndexOUT = 0;
ptr->iCnt_Handle--;
}
}
void DRV_RingBuffPtr__Output_JumpToNew(RING_BUFF_INFO *ptr, unsigned int iBufferSize) {
if (ptr->iCnt_Handle > 1) {
while (ptr->iCnt_Handle > 1) {
ptr->iIndexOUT++;
if (ptr->iIndexOUT >= iBufferSize)
ptr->iIndexOUT = 0;
ptr->iCnt_Handle--;
}
} else {
ptr->iIndexOUT++;
if (ptr->iIndexOUT >= iBufferSize)
ptr->iIndexOUT = 0;
ptr->iCnt_Handle--;
}
}
RingBuff.h
#ifndef RINGBUFF_H
#define RINGBUFF_H
#include "main.h"
#include <stdint.h>
typedef struct {
uint16_t iIndexIN; // change all these if need more than 16bits.
uint16_t iIndexOUT;
uint16_t iCnt_Handle;
uint16_t iCnt_OverFlow;
}RING_BUFF_INFO;
//================================================
// FUNCTION
//================================================
void DRV_RingBuffPtr__Clean(RING_BUFF_INFO *ptr);
void DRV_RingBuffPtr__Input(RING_BUFF_INFO *ptr, unsigned int iBufferSize);
void DRV_RingBuffPtr__Output(RING_BUFF_INFO *ptr, unsigned int iBufferSize);
void DRV_RingBuffPtr__Output_JumpToNew(RING_BUFF_INFO *ptr, unsigned int iBufferSize);
#endif // RINGBUFF_H
main.c
// only showing main function to see how I'm calling PollingInit and PollingRoutine function
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
PollingInit();
while (1)
{
PollingRoutine();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
main.h
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdlib.h"
#include "stdint.h"
#include "stdbool.h"
#include "stdio.h"
#include "string.h"
#include "RingBuff.h"
#include "PollingRoutine.h"
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
#define MCO_Pin GPIO_PIN_0
#define MCO_GPIO_Port GPIOA
#define VCP_TX_Pin GPIO_PIN_2
#define VCP_TX_GPIO_Port GPIOA
#define SWDIO_Pin GPIO_PIN_13
#define SWDIO_GPIO_Port GPIOA
#define SWCLK_Pin GPIO_PIN_14
#define SWCLK_GPIO_Port GPIOA
#define VCP_RX_Pin GPIO_PIN_15
#define VCP_RX_GPIO_Port GPIOA
#define LD3_Pin GPIO_PIN_3
#define LD3_GPIO_Port GPIOB
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */