added penguinbuffers submodule

stable
Penguin 3 years ago
parent 9f0877c746
commit 1ee7e71711

3
.gitmodules vendored

@ -0,0 +1,3 @@
[submodule "PenguinBuffer"]
path = PenguinBuffer
url = git@git.epenguin.net:penguin/PenguinBuffer.git

@ -60,7 +60,6 @@ Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c \
Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c \ Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c \
Core/Src/system_stm32l4xx.c \ Core/Src/system_stm32l4xx.c \
shared/util/putil.c \ shared/util/putil.c \
shared/util/PCircularBuffer.c \
shared/drivers/p_serial_mgr.c \ shared/drivers/p_serial_mgr.c \
shared/devices/motor_controller.c shared/devices/motor_controller.c

@ -0,0 +1 @@
Subproject commit 9804c4b906262b873e7f72e3aab3bf899db34b64

@ -1,16 +1,28 @@
#MicroXplorer Configuration settings - do not modify #MicroXplorer Configuration settings - do not modify
Dma.Request0=USART1_RX
Dma.RequestsNb=1
Dma.USART1_RX.0.Direction=DMA_PERIPH_TO_MEMORY
Dma.USART1_RX.0.Instance=DMA1_Channel5
Dma.USART1_RX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.USART1_RX.0.MemInc=DMA_MINC_ENABLE
Dma.USART1_RX.0.Mode=DMA_NORMAL
Dma.USART1_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.USART1_RX.0.PeriphInc=DMA_PINC_DISABLE
Dma.USART1_RX.0.Priority=DMA_PRIORITY_LOW
Dma.USART1_RX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority
File.Version=6 File.Version=6
KeepUserPlacement=false KeepUserPlacement=false
Mcu.CPN=STM32L432KCU3 Mcu.CPN=STM32L432KCU3
Mcu.Family=STM32L4 Mcu.Family=STM32L4
Mcu.IP0=NVIC Mcu.IP0=DMA
Mcu.IP1=RCC Mcu.IP1=NVIC
Mcu.IP2=SYS Mcu.IP2=RCC
Mcu.IP3=TIM2 Mcu.IP3=SYS
Mcu.IP4=TIM6 Mcu.IP4=TIM2
Mcu.IP5=USART1 Mcu.IP5=TIM6
Mcu.IP6=USART2 Mcu.IP6=USART1
Mcu.IPNb=7 Mcu.IP7=USART2
Mcu.IPNb=8
Mcu.Name=STM32L432K(B-C)Ux Mcu.Name=STM32L432K(B-C)Ux
Mcu.Package=UFQFPN32 Mcu.Package=UFQFPN32
Mcu.Pin0=PC14-OSC32_IN (PC14) Mcu.Pin0=PC14-OSC32_IN (PC14)
@ -36,6 +48,7 @@ Mcu.UserName=STM32L432KCUx
MxCube.Version=6.5.0 MxCube.Version=6.5.0
MxDb.Version=DB.6.0.50 MxDb.Version=DB.6.0.50
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true
NVIC.DMA1_Channel5_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true
NVIC.ForceEnableDMAVector=true NVIC.ForceEnableDMAVector=true
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true
@ -129,7 +142,7 @@ ProjectManager.StackSize=0x400
ProjectManager.TargetToolchain=Makefile ProjectManager.TargetToolchain=Makefile
ProjectManager.ToolChainLocation= ProjectManager.ToolChainLocation=
ProjectManager.UnderRoot=false ProjectManager.UnderRoot=false
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_TIM2_Init-TIM2-false-HAL-true,4-MX_USART2_UART_Init-USART2-false-HAL-true,5-MX_TIM6_Init-TIM6-false-HAL-true,6-MX_USART1_UART_Init-USART1-false-HAL-true ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,4-MX_TIM2_Init-TIM2-false-HAL-true,5-MX_USART2_UART_Init-USART2-false-HAL-true,6-MX_DMA_Init-DMA-false-HAL-true,7-MX_USART1_UART_Init-USART1-false-HAL-true
RCC.48CLKFreq_Value=24000000 RCC.48CLKFreq_Value=24000000
RCC.AHBFreq_Value=32000000 RCC.AHBFreq_Value=32000000
RCC.APB1Freq_Value=32000000 RCC.APB1Freq_Value=32000000

@ -1,5 +1,4 @@
#include "p_serial_mgr.h" #include "p_serial_mgr.h"
#include "PCircularBuffer.h"
#include "putil.h" #include "putil.h"
#include "stm32l4xx_hal_uart.h" #include "stm32l4xx_hal_uart.h"
@ -9,7 +8,7 @@
// [0]{1} Start delimiter 0x7E // [0]{1} Start delimiter 0x7E
// [1]{1} Source Address // [1]{1} Source Address
// [2]{1} Destination Address // [2]{1} Destination Address
// [3]{1} Length Byte // [3]{1} Length Byte (of non-delimited framebuffer)
// [4-n]{n} frame data // [4-n]{n} frame data
// [n+1]{1} checksum // [n+1]{1} checksum
// Escape bytes are 0x7D, only frame data can be escaped // Escape bytes are 0x7D, only frame data can be escaped
@ -20,36 +19,33 @@ typedef enum serial_state_t
{ {
SS_IDLE = 0, // waiting SS_IDLE = 0, // waiting
SS_START = 1, // get start byte, interrupt after 4 more bytes SS_START = 1, // get start byte, interrupt after 4 more bytes
SS_FRAME = 2, // get byte
SS_ESC = 3, // get byte, dont increment number left
SS_CHECKSUM = 4 // done
} serial_state_t; } serial_state_t;
static UART_HandleTypeDef *_serial_huart_inst = NULL; static UART_HandleTypeDef *_serial_huart_inst = NULL;
static uint8_t rxc = '\0'; static uint8_t rxc = '\0';
static bool b_go = false; static serial_state_t sstate = SS_IDLE;
void UART1_RxCpltCallback(UART_HandleTypeDef *huart) void UART1_RxCpltCallback(UART_HandleTypeDef *huart)
{ {
b_go = true; if (rxc == 0x7E && sstate == SS_IDLE)
{
sstate = SS_START;
} }
}
void p_serial_mgr_init(UART_HandleTypeDef *huart) void p_serial_mgr_init(UART_HandleTypeDef *huart)
{ {
_serial_huart_inst = huart; _serial_huart_inst = huart;
_serial_huart_inst->RxCpltCallback = UART1_RxCpltCallback; _serial_huart_inst->RxCpltCallback = UART1_RxCpltCallback;
b_go = false;
} }
void p_serial_mgr_service(void)
bool p_serial_mgr_service(void)
{ {
// // this will be less garbage when i switch to a queue if (sstate == SS_START)
// for (int ind = 0; ind < serial_pkt_cb.max_len; ind++) {
// { return;
// if (serial_pkt_cb.buffer[ind].b_ready) }
// { else if (sstate = SS_IDLE) {}
// return &serial_pkt_cb.buffer[ind];
// }
// }
return b_go; return b_go;
} }

@ -4,14 +4,28 @@
#include "stm32l4xx_hal.h" #include "stm32l4xx_hal.h"
#include <stdbool.h> #include <stdbool.h>
// start byte
// src_addr {1} +
// dest_addr {1} +
// frame_length {1} +
// checksum {1} +
// frame_data {510} -- making it 510 instead of 511 so it is easily divisible
#define MAX_MESSAGE_LEN (516)
#define MAX_FRAME_DATA_LEN (510)
// motor controller
#define DEVICE_ADDR (0x02)
// pi
#define MASTER_ADDR (0x01)
typedef struct serial_pkt_t typedef struct serial_pkt_t
{ {
uint8_t frame_data[256]; uint8_t *src_addr;
uint8_t src_addr; uint8_t *dest_addr;
uint8_t dest_addr; uint8_t *frame_data_len;
uint8_t checksum; uint8_t *checksum;
uint8_t len; uint8_t *frame_data;
bool b_ready; uint8_t data[MAX_MESSAGE_LEN];
int msg_len;
} serial_pkt_t; } serial_pkt_t;
void p_serial_mgr_init(UART_HandleTypeDef *huart); void p_serial_mgr_init(UART_HandleTypeDef *huart);

@ -1,194 +0,0 @@
#include "putil.h"
#include <PCircularBuffer.h>
// Error handler used for debugging only
#ifdef PB_CB_DEBUG
#include <stdio.h>
static void handle_status(const char *func, PB_CB_STATUS status_code)
{
if (status_code != PB_CB_GOOD)
{
PDEBUG("%s failed: error code: %d\r\n", func, status_code);
}
}
#endif
// Circular Buffer Prototypes -- uint8_t
static PB_CB_STATUS p_cb_u8_push(p_cb_u8 *cbuffer, uint8_t value);
static PB_CB_STATUS p_cb_u8_empty(p_cb_u8 *cbuffer);
// serial_pkt
static PB_CB_STATUS p_cb_serial_pkt_push(p_cb_serial_pkt_t *cbuffer, serial_pkt_t value);
static PB_CB_STATUS p_cb_serial_pkt_empty(p_cb_serial_pkt_t *cbuffer);
// Circular Buffer Definitions -- uint8_t
PB_CB_STATUS p_cb_u8_init(p_cb_u8 *circ_buffer, uint8_t *buff, uint32_t max_length)
{
PB_CB_STATUS ret = PB_CB_GOOD;
do
{
// Make sure the buffer isn't bad (null)
if (!buff)
{
ret = PB_CB_NULL_BUFFER;
break;
}
// Make sure the max buffer is a useable size
if (max_length > PB_CB_MAX_BUFFER_SIZE || max_length <= 0)
{
ret = PB_CB_BAD_BUFFER_SIZE;
break;
}
} while (0);
// Debugging
#ifdef PB_CB_DEBUG
handle_status(__func__, ret);
#endif
return ret;
}
PB_CB_STATUS p_cb_u8_push(p_cb_u8 *cbuffer, uint8_t value)
{
PB_CB_STATUS ret = PB_CB_GOOD;
if (!cbuffer)
{
ret = PB_CB_NULL_CBUFFER;
}
else
{
cbuffer->buffer[cbuffer->head] = value;
cbuffer->head = (cbuffer->head + 1) % cbuffer->max_len;
}
// Debugging
#ifdef PB_CB_DEBUG
handle_status(__func__, ret);
#endif
return ret;
}
PB_CB_STATUS p_cb_u8_empty(p_cb_u8 *cbuffer)
{
PB_CB_STATUS ret = PB_CB_GOOD;
do
{
if (!cbuffer)
{
ret = PB_CB_NULL_CBUFFER;
break;
}
if (!cbuffer->buffer)
{
ret = PB_CB_NULL_BUFFER;
break;
}
memset(cbuffer->buffer, 0, cbuffer->max_len);
cbuffer->head = 0;
cbuffer->b_empty = true;
cbuffer->b_filled = false;
} while (0);
// Debugging
#ifdef PB_CB_DEBUG
handle_status(__func__, ret);
#endif
return ret;
}
// Circular Buffer Definitions -- uint8_t
PB_CB_STATUS p_cb_serial_pkt_init(p_cb_serial_pkt_t *inst, serial_pkt_t *buff, uint32_t max_length)
{
PB_CB_STATUS ret = PB_CB_GOOD;
do
{
if (!buff)
{
ret = PB_CB_NULL_BUFFER;
break;
}
if (max_length > PB_CB_MAX_BUFFER_SIZE || max_length <= 0)
{
ret = PB_CB_BAD_BUFFER_SIZE;
break;
}
for (int ind = 0; ind < max_length; ind++)
{
memset(inst->buffer[ind].frame_data, 0, 256);
}
inst->buffer = buff;
inst->max_len = (uint16_t)max_length;
inst->head = 0;
inst->push = p_cb_serial_pkt_push;
inst->empty = p_cb_serial_pkt_empty;
inst->empty(inst);
} while (0);
// Debugging
#ifdef PB_CB_DEBUG
handle_status(__func__, ret);
#endif
return ret;
}
PB_CB_STATUS p_cb_serial_pkt_push(p_cb_serial_pkt_t *cbuffer, serial_pkt_t value)
{
PB_CB_STATUS ret = PB_CB_GOOD;
if (!cbuffer)
{
ret = PB_CB_NULL_CBUFFER;
}
else
{
cbuffer->buffer[cbuffer->head] = value;
cbuffer->head = (cbuffer->head + 1) % cbuffer->max_len;
}
// Debugging
#ifdef PB_CB_DEBUG
handle_status(__func__, ret);
#endif
return ret;
}
PB_CB_STATUS p_cb_serial_pkt_empty(p_cb_serial_pkt_t *cbuffer)
{
PB_CB_STATUS ret = PB_CB_GOOD;
do
{
if (!cbuffer)
{
ret = PB_CB_NULL_CBUFFER;
break;
}
if (!cbuffer->buffer)
{
ret = PB_CB_NULL_BUFFER;
break;
}
memset(cbuffer->buffer, 0, sizeof(serial_pkt_t) * cbuffer->max_len);
cbuffer->head = 0;
cbuffer->b_empty = true;
cbuffer->b_filled = false;
} while (0);
// Debugging
#ifdef PB_CB_DEBUG
handle_status(__func__, ret);
#endif
return ret;
}

@ -1,88 +0,0 @@
// Resource/Inspiration: https://embedjournal.com/implementing-circular-buffer-embedded-c/
/*
Penguin's Circular Buffer -- a simple floating queue designed for low memory usage (mainly for embedded)
This is a ring buffer with limited capabilities. It is meant as a container for moving data.
Normally included features such as checks to see if the buffer is full or empty have been omitted
because this type of buffer is being implemented mainly for sensor data usage. Data is almost never read
individually, and even if it is, it isn't meant to be cleared on read. It is a simple moving buffer that
automatically writes over old data for the purpose of keeping track of the most up to date data.
Notes:
- Initialization is mandatory using p_cb_<type>_init.
- If a circular buffer is not initialized, you will run into a LOT of hard-to-debug problems. Just initialize it.
- By default, all cb types should be defined as disabled. This is to save on size. Enable the ones you want to use.
Behavior:
- Oldest data is overwritten
- popping of data isn't implemented. If this feature is required, use a ring buffer.
Acronyms:
- p: penguin
- pb: penguin buffer
- cb: circular buffer
- uX, where X is bit size: unsigned X bit integer
- iX, where X is bit size: signed X bit integer
Note: I wrote this like 3 years ago or something. I hope it works.
*/
#ifndef _PCIRCULARBUFFER_H_
#define _PCIRCULARBUFFER_H_
#include "p_serial_mgr.h"
#include <stdbool.h>
#include <stdint.h>
#ifdef _DEBUG
#define PC_CB_DEBUG
#endif
// Max size is 65535 (2^16 - 1) so variables can be safely set 16 bits (unsigned)
// If you want to change this, you'll need to change the sizes of all heads and max lengths
#define PB_CB_MAX_BUFFER_SIZE (65535)
typedef enum PB_CB_STATUS
{
PB_CB_GOOD = 0,
PB_CB_BAD = 1,
PB_CB_BAD_BUFFER_SIZE = 2,
PB_CB_NULL_BUFFER = 3,
PB_CB_NULL_CBUFFER = 4
} PB_CB_STATUS;
typedef struct p_cb_u8
{
uint8_t *buffer;
uint16_t head;
uint16_t max_len;
// Signifies the buffer being filled at least once.
// Useful for initializing sensor data
bool b_filled;
// Signifies the buffer being empty
// Useful for knowing if data is being received
bool b_empty;
PB_CB_STATUS (*push)(struct p_cb_u8 *cbuffer, uint8_t value);
PB_CB_STATUS (*empty)(struct p_cb_u8 *cbuffer);
} p_cb_u8;
PB_CB_STATUS p_cb_u8_init(p_cb_u8 *circ_buffer, uint8_t *buff, uint32_t max_length);
typedef struct p_cb_serial_pkt_t
{
serial_pkt_t *buffer;
uint16_t head;
uint16_t max_len;
bool b_filled;
// Signifies the buffer being empty
// Useful for knowing if data is being received
bool b_empty;
PB_CB_STATUS (*push)(struct p_cb_serial_pkt_t *cbuffer, serial_pkt_t value);
PB_CB_STATUS (*empty)(struct p_cb_serial_pkt_t *cbuffer);
} p_cb_serial_pkt_t;
PB_CB_STATUS p_cb_serial_pkt_init(p_cb_serial_pkt_t *inst, serial_pkt_t *buff, uint32_t max_length);
#endif
Loading…
Cancel
Save