ringbuffer and tests

This commit is contained in:
Wolfgang Hottgenroth 2020-10-28 19:40:08 +01:00
parent 73239f4436
commit b8e676299a
Signed by: wn
GPG Key ID: 6C1E5E531E0D5D7F
12 changed files with 520 additions and 72 deletions

4
.gitignore vendored
View File

@ -1,2 +1,4 @@
cube/build/
.*.sw?
.*.sw?
*.o
test

View File

@ -1,4 +1,4 @@
# Processed by ../tools/insertMyCode.sh
# Processed by ../tools/insertMyCode.sh
##########################################################################################################################
# File automatically-generated by tool: [projectgenerator] version: [3.10.0-B14] date: [Tue Oct 27 22:02:19 CET 2020]
##########################################################################################################################
@ -36,36 +36,36 @@ BUILD_DIR = build
# source
######################################
# C sources
C_SOURCES = \
User/Src/led.c User/Src/loopCtrl.c User/Src/main2.c hottislib/PontCoopScheduler.c \
Core/Src/main.c \
Core/Src/gpio.c \
Core/Src/adc.c \
Core/Src/spi.c \
Core/Src/usart.c \
Core/Src/stm32f1xx_it.c \
Core/Src/stm32f1xx_hal_msp.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c \
C_SOURCES = \
User/Src/mbusComm.c User/Src/led.c User/Src/loopCtrl.c User/Src/main2.c hottislib/PontCoopScheduler.c \
Core/Src/main.c \
Core/Src/gpio.c \
Core/Src/adc.c \
Core/Src/spi.c \
Core/Src/usart.c \
Core/Src/stm32f1xx_it.c \
Core/Src/stm32f1xx_hal_msp.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c \
Core/Src/system_stm32f1xx.c
# ASM sources
ASM_SOURCES = \
ASM_SOURCES = \
startup_stm32f103xe.s
@ -109,8 +109,8 @@ MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)
AS_DEFS =
# C defines
C_DEFS = \
-DUSE_HAL_DRIVER \
C_DEFS = \
-DUSE_HAL_DRIVER \
-DSTM32F103xE
@ -118,14 +118,14 @@ C_DEFS = \
AS_INCLUDES =
# C includes
C_INCLUDES = \
-Ihottislib \
-IUser/Inc \
-ICore/Inc \
-IDrivers/STM32F1xx_HAL_Driver/Inc \
-IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy \
-IDrivers/CMSIS/Device/ST/STM32F1xx/Include \
-IDrivers/CMSIS/Include \
C_INCLUDES = \
-Ihottislib \
-IUser/Inc \
-ICore/Inc \
-IDrivers/STM32F1xx_HAL_Driver/Inc \
-IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy \
-IDrivers/CMSIS/Device/ST/STM32F1xx/Include \
-IDrivers/CMSIS/Include \
-IDrivers/CMSIS/Include

6
cube/User/Inc/logger.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef _LOGGER_H_
#define _LOGGER_H_
void log(char *msg);
#endif // _LOGGER_H_

8
cube/User/Inc/mbusComm.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef _MBUSCOMM_H_
#define _MBUSCOMM_H_
#include <stdint.h>
void mbusCommRequest(uint8_t cmd, uint8_t addr);
#endif // _MBUSCOMM_H_

View File

@ -0,0 +1,23 @@
#ifndef _RINGBUFFER_H_
#define _RINGBUFFER_H_
#include <stdint.h>
#include <stdbool.h>
typedef struct {
uint32_t bufferReadIdx;
uint32_t bufferWriteIdx;
uint32_t bufferSize;
uint8_t* buffer;
} ringbuffer_t;
void ringbufferInit(ringbuffer_t *handle, uint32_t bufferSize);
void ringbufferFree(ringbuffer_t *handle);
int ringbufferPut(ringbuffer_t *handle, uint8_t *data, uint32_t dataLen);
uint8_t *ringbufferGet(ringbuffer_t *handle, uint32_t dataLen);
bool ringbufferEmpty(ringbuffer_t *handle);
int ringbufferGetOne(ringbuffer_t *handle); // if positive, cast to uint8_t and be happy, if negative error
#endif // _RINGBUFFER_H_

17
cube/User/Src/logger.c Normal file
View File

@ -0,0 +1,17 @@
#include <main.h>
#include <usart.h>
#include <logger.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
void log(char *msg) {
uint16_t len = strlen(msg);
if (HAL_UART_Transmit_IT(&debugUart, msg, len) != HAL_OK) {
if(RingBuffer_Write(&txBuf, msg, len) != RING_BUFFER_OK)
return 0;
}
return 1;
}

View File

@ -9,6 +9,8 @@
#include <led.h>
#include <loopCtrl.h>
#include <mbusComm.h>
void my_setup_1() {
schInit();
@ -18,53 +20,21 @@ void my_errorHandler() {
ledRed(true);
}
void blinkRed(void *handle) {
static bool on = false;
ledRed(on);
on ^= true;
}
void blinkGreen(void *handle) {
static bool on = false;
ledGreen(on);
on ^= true;
}
void helloWorld(void *handle) {
static char hello[] = "Hello World\n\r";
HAL_UART_Transmit_IT(&debugUart, (uint8_t*) hello, strlen(hello));
}
void helloMeterbus(void *handle) {
static char hello[] = "Hello Meterbus\n\r";
if (! loopActive) {
loopEnable();
ledRed(false);
}
HAL_UART_Transmit_IT(&mbusUart, (uint8_t*) hello, strlen(hello));
mbusCommRequest(0x5b, 80);
}
void toggleLoop(void *handle) {
static bool state = false;
if (state) {
loopDisable();
} else {
ledRed(false);
loopEnable();
}
state ^= true;
}
void my_setup_2() {
ledRed(false);
ledGreen(true);
schAdd(helloWorld, NULL, 0, 5000);
// schAdd(toggleLoop, NULL, 0, 10000);
schAdd(helloMeterbus, NULL, 0, 10000);
}

74
cube/User/Src/mbusComm.c Normal file
View File

@ -0,0 +1,74 @@
#include <main.h>
#include <usart.h>
#include <PontCoopScheduler.h>
#include <mbusComm.h>
#include <loopCtrl.h>
#include <led.h>
typedef enum {
IDLE,
SEND,
SEND_CONT
} e_mbusCommState;
typedef struct {
e_mbusCommState state;
uint8_t retryCnt;
uint8_t cmd;
uint8_t addr;
uint8_t sendBuf[5];
} t_mbusCommHandle;
static t_mbusCommHandle mbusCommHandle = { .state = IDLE, .retryCnt = 0, .cmd = 0, .addr = 0 };
static void handleRequestEngine(void *handle) {
t_mbusCommHandle *myHandle = (t_mbusCommHandle*) handle;
switch (myHandle->state) {
case IDLE:
break;
case SEND:
myHandle->sendBuf[0] = 0x10;
myHandle->sendBuf[1] = myHandle->cmd;
myHandle->sendBuf[2] = myHandle->addr;
myHandle->sendBuf[3] = myHandle->cmd + myHandle->addr; // checksum
myHandle->sendBuf[4] = 0x16;
myHandle->state = SEND_CONT;
// no break !!
case SEND_CONT:
ledRed(false);
if (! loopActive) {
myHandle->retryCnt++;
loopEnable();
schAdd(handleRequestEngine, handle, 10, 0);
} else {
// write(fd, sendBuf, 5);
HAL_UART_Transmit_IT(&mbusUart, myHandle->sendBuf, 5);
myHandle->state = IDLE;
}
break;
default:
myHandle->state = IDLE;
break;
}
}
void mbusCommRequest(uint8_t cmd, uint8_t addr) {
if (mbusCommHandle.state == IDLE) {
mbusCommHandle.state = SEND;
mbusCommHandle.retryCnt = 0;
mbusCommHandle.cmd = cmd;
mbusCommHandle.addr = addr;
schAdd(handleRequestEngine, (void*) &mbusCommHandle, 0, 0);
} else {
// busy
}
}

105
cube/User/Src/ringbuffer.c Normal file
View File

@ -0,0 +1,105 @@
#include <stdlib.h>
#include <string.h>
#include <ringbuffer.h>
/*
typedef struct {
uint32_t bufferReadIdx;
uint32_t bufferWriteIdx;
uint32_t bufferSize;
uint8_t* buffer;
} ringbuffer_t;
*/
void ringbufferInit(ringbuffer_t *handle, uint32_t bufferSize) {
handle->bufferSize = bufferSize;
handle->buffer = (uint8_t*) malloc(handle->bufferSize);
memset(handle->buffer, 0, handle->bufferSize);
handle->bufferReadIdx = 0;
handle->bufferWriteIdx = 0;
}
void ringbufferFree(ringbuffer_t *handle) {
free(handle->buffer);
handle->buffer = NULL;
handle->bufferSize = 0;
handle->bufferReadIdx = 0;
handle->bufferWriteIdx = 0;
}
/*
void ringbufferPut(ringbuffer_t *handle, void *f) {
if (handle->bufferWriteIdx == (BUFFER_SIZE - 1)) {
while (handle->bufferReadIdx == BUFFER_SIZE);
} else {
while (handle->bufferReadIdx == (handle->bufferWriteIdx + 1));
}
handle->buffer[handle->bufferWriteIdx] = f;
handle->bufferWriteIdx++;
if (handle->bufferWriteIdx > BUFFER_SIZE) {
handle->bufferWriteIdx = 0;
}
pthread_mutex_lock(&(handle->eventMutex));
pthread_cond_signal(&(handle->eventSignal));
pthread_mutex_unlock(&(handle->eventMutex));
}
*/
int ringbufferPut(ringbuffer_t *handle, uint8_t *data, uint32_t dataLen) {
uint32_t freeSpace = 0;
if (handle->bufferReadIdx == handle->bufferWriteIdx) {
freeSpace = handle->bufferSize;
} else if (handle->bufferReadIdx > handle->bufferWriteIdx) {
freeSpace = handle->bufferReadIdx - handle->bufferWriteIdx;
} else {
freeSpace = (handle->bufferSize - handle->bufferWriteIdx) + handle->bufferReadIdx;
}
if (dataLen > freeSpace) {
return -1;
}
if (dataLen <= (handle->bufferSize - handle->bufferWriteIdx)) {
memcpy(handle->buffer + handle->bufferWriteIdx, data, dataLen);
handle->bufferWriteIdx += dataLen;
if (handle->bufferWriteIdx == handle->bufferSize) {
handle->bufferWriteIdx = 0;
}
} else {
uint32_t remainingToTop = handle->bufferSize - handle->bufferWriteIdx;
memcpy(handle->buffer + handle->bufferWriteIdx, data, remainingToTop);
memcpy(handle->buffer, data + remainingToTop, dataLen - remainingToTop);
handle->bufferWriteIdx = dataLen - remainingToTop;
}
return 0;
}
bool ringbufferEmpty(ringbuffer_t *handle) {
return handle->bufferReadIdx == handle->bufferWriteIdx;
}
uint8_t *ringbufferGet(ringbuffer_t *handle, uint32_t dataLen) {
return NULL;
}
int ringbufferGetOne(ringbuffer_t *handle) {
int res = -1;
if (! ringbufferEmpty(handle)) {
uint8_t r = *(handle->buffer + handle->bufferReadIdx);
handle->bufferReadIdx += 1;
if (handle->bufferReadIdx == handle->bufferSize) {
handle->bufferReadIdx = 0;
}
res = (int) r;
}
return res;
}

View File

@ -0,0 +1,17 @@
CFLAGS=-I../../cube/User/Inc
test: ringbuffer.o test.o
gcc -o $@ -lcunit $^
./test
ringbuffer.o: ../../cube/User/Src/ringbuffer.c
gcc -c -o $@ $(CFLAGS) $^
test.o: test.c
gcc -c -o $@ $(CFLAGS) $^
.PHONY: clean
clean:
-rm *.o test

223
tests/testRingbuffer/test.c Normal file
View File

@ -0,0 +1,223 @@
#include <CUnit/Basic.h>
#include <stdio.h>
#include <stdbool.h>
#include <ringbuffer.h>
// #define DEBUG
ringbuffer_t rb;
void printRingbuffer(ringbuffer_t *rb) {
printf("Ringbuffer:\n");
printf(" Size: %u\n", rb->bufferSize);
printf(" ReadIdx: %u\n", rb->bufferReadIdx);
printf(" WriteIdx: %u\n", rb->bufferWriteIdx);
for (uint32_t i = 0; i < rb->bufferSize; i++) {
printf("%02x ", rb->buffer[i]);
}
printf("\n");
}
int init_suite_ringbuffer(void) {
return 0;
}
int clean_suite_ringbuffer(void) {
return 0;
}
void testRingbuffer0() {
#ifdef DEBUG
printf("Initialize ringbuffer\n");
#endif
ringbufferInit(&rb, 16);
#ifdef DEBUG
printRingbuffer(&rb);
#endif
CU_ASSERT(rb.buffer != NULL);
CU_ASSERT(rb.bufferSize == 16);
CU_ASSERT(rb.bufferWriteIdx == 0);
CU_ASSERT(rb.bufferReadIdx == 0);
}
void testRingbuffer1() {
#ifdef DEBUG
printf("\nPut 5 chars in buffer\n");
#endif
int r = ringbufferPut(&rb, "abcde", 5);
#ifdef DEBUG
printf("r = %d\n", r);
printRingbuffer(&rb);
#endif
CU_ASSERT(r == 0);
CU_ASSERT(rb.buffer != NULL);
CU_ASSERT(rb.bufferSize == 16);
CU_ASSERT(rb.bufferWriteIdx == 5);
CU_ASSERT(rb.bufferReadIdx == 0);
}
void testRingbuffer2() {
#ifdef DEBUG
printf("\nPut 5 chars in buffer\n");
#endif
int r = ringbufferPut(&rb, "fghij", 5);
#ifdef DEBUG
printf("r = %d\n", r);
printRingbuffer(&rb);
#endif
CU_ASSERT(r == 0);
CU_ASSERT(rb.buffer != NULL);
CU_ASSERT(rb.bufferSize == 16);
CU_ASSERT(rb.bufferWriteIdx == 10);
CU_ASSERT(rb.bufferReadIdx == 0);
}
void testRingbuffer3() {
#ifdef DEBUG
printf("\nPut 5 chars in buffer\n");
#endif
int r = ringbufferPut(&rb, "klmno", 5);
#ifdef DEBUG
printf("r = %d\n", r);
printRingbuffer(&rb);
#endif
CU_ASSERT(r == 0);
CU_ASSERT(rb.buffer != NULL);
CU_ASSERT(rb.bufferSize == 16);
CU_ASSERT(rb.bufferWriteIdx == 15);
CU_ASSERT(rb.bufferReadIdx == 0);
}
void testRingbuffer4() {
#ifdef DEBUG
printf("\nPut 5 chars in buffer\n");
#endif
int r = ringbufferPut(&rb, "pqrst", 5);
#ifdef DEBUG
printf("r = %d\n", r);
printRingbuffer(&rb);
#endif
CU_ASSERT(r == -1);
CU_ASSERT(rb.buffer != NULL);
CU_ASSERT(rb.bufferSize == 16);
CU_ASSERT(rb.bufferWriteIdx == 15);
CU_ASSERT(rb.bufferReadIdx == 0);
}
void testRingbuffer5() {
#ifdef DEBUG
printf("\nRead one char from buffer\n");
#endif
int r = ringbufferGetOne(&rb);
#ifdef DEBUG
printRingbuffer(&rb);
#endif
CU_ASSERT(r >= 0);
CU_ASSERT(rb.buffer != NULL);
CU_ASSERT(rb.bufferSize == 16);
CU_ASSERT(rb.bufferWriteIdx == 15);
CU_ASSERT(rb.bufferReadIdx == 1);
uint8_t rr = (uint8_t) r;
CU_ASSERT(rr == 'a');
}
void testRingbuffer6() {
#ifdef DEBUG
printf("\nRead some char from buffer\n");
#endif
int r = ringbufferGetOne(&rb);
#ifdef DEBUG
printRingbuffer(&rb);
#endif
CU_ASSERT(r >= 0);
CU_ASSERT(rb.buffer != NULL);
CU_ASSERT(rb.bufferSize == 16);
CU_ASSERT(rb.bufferWriteIdx == 15);
CU_ASSERT(rb.bufferReadIdx == 2);
uint8_t rr = (uint8_t) r;
CU_ASSERT(rr == 'b');
r = ringbufferGetOne(&rb);
#ifdef DEBUG
printRingbuffer(&rb);
#endif
CU_ASSERT(r >= 0);
CU_ASSERT(rb.buffer != NULL);
CU_ASSERT(rb.bufferSize == 16);
CU_ASSERT(rb.bufferWriteIdx == 15);
CU_ASSERT(rb.bufferReadIdx == 3);
rr = (uint8_t) r;
CU_ASSERT(rr == 'c');
r = ringbufferGetOne(&rb);
#ifdef DEBUG
printRingbuffer(&rb);
#endif
CU_ASSERT(r >= 0);
CU_ASSERT(rb.buffer != NULL);
CU_ASSERT(rb.bufferSize == 16);
CU_ASSERT(rb.bufferWriteIdx == 15);
CU_ASSERT(rb.bufferReadIdx == 4);
rr = (uint8_t) r;
CU_ASSERT(rr == 'd');
}
void testRingbuffer99() {
#ifdef DEBUG
printf("De-Initialize ringbuffer\n");
#endif
ringbufferFree(&rb);
#ifdef DEBUG
printRingbuffer(&rb);
#endif
CU_ASSERT(rb.buffer == NULL);
CU_ASSERT(rb.bufferSize == 0);
CU_ASSERT(rb.bufferWriteIdx == 0);
CU_ASSERT(rb.bufferReadIdx == 0);
}
int main() {
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
CU_pSuite ringbufferSuite = CU_add_suite("Suite_Ringbuffer", init_suite_ringbuffer, clean_suite_ringbuffer);
if (NULL == ringbufferSuite) {
CU_cleanup_registry();
return CU_get_error();
}
if ((NULL == CU_add_test(ringbufferSuite, "test 0 of ringbuffer, init", testRingbuffer0)) ||
(NULL == CU_add_test(ringbufferSuite, "test 1 of ringbuffer", testRingbuffer1)) ||
(NULL == CU_add_test(ringbufferSuite, "test 2 of ringbuffer", testRingbuffer2)) ||
(NULL == CU_add_test(ringbufferSuite, "test 3 of ringbuffer", testRingbuffer3)) ||
(NULL == CU_add_test(ringbufferSuite, "test 4 of ringbuffer", testRingbuffer4)) ||
(NULL == CU_add_test(ringbufferSuite, "test 5 of ringbuffer", testRingbuffer5)) ||
(NULL == CU_add_test(ringbufferSuite, "test 6 of ringbuffer", testRingbuffer6)) ||
(NULL == CU_add_test(ringbufferSuite, "test 99 of ringbuffer, free", testRingbuffer99)) ||
0 ) {
CU_cleanup_registry();
return CU_get_error();
}
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
CU_cleanup_registry();
return CU_get_error();
}

3
tools/startTestEnv.sh Normal file
View File

@ -0,0 +1,3 @@
#!/bin/bash
docker run -it --rm -u ${UID} -v ${PWD}:/mnt wollud1969/build-env-c:1.1.1 bash