git subrepo pull components/f4ll_c

subrepo:
  subdir:   "components/f4ll_c"
  merged:   "5d26fdc"
upstream:
  origin:   "git@git.pcmuhely.hu:compi/f4ll_c.git"
  branch:   "master"
  commit:   "5d26fdc"
git-subrepo:
  version:  "0.4.0"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "5d6aba9"
This commit is contained in:
Attila Body 2019-12-06 14:32:53 +01:00
parent 357b30b344
commit b9114f049a
10 changed files with 243 additions and 189 deletions

View file

@ -6,7 +6,7 @@
[subrepo] [subrepo]
remote = git@git.pcmuhely.hu:compi/f4ll_c.git remote = git@git.pcmuhely.hu:compi/f4ll_c.git
branch = master branch = master
commit = 4754b650418bd9e053db80827700d3a527d41823 commit = 5d26fdc64d86cdbf16d6796c3c51cef3ef05a8dc
parent = 6f89e70a2a208d77d8d9ae1e20dbece8f0214c59 parent = 357b30b34479b3f45b97b60068d7d0fcaa4d98eb
method = merge method = merge
cmdver = 0.4.0 cmdver = 0.4.0

View file

@ -62,5 +62,5 @@ void Con_PrintStats(char *buffer, uint8_t id, struct usart_stats *stats, USART_
ADDINFO(buffer, " pmp: ", stats->premature_payload); ADDINFO(buffer, " pmp: ", stats->premature_payload);
buffer += strcpy_ex(buffer, "\r\n"); buffer += strcpy_ex(buffer, "\r\n");
Pku_SetupTransmit(usart, dmaInfo->dma, dmaInfo->stream, bs, buffer - bs + 1); Pu_SetupTransmit(usart, dmaInfo->dma, dmaInfo->stream, bs, buffer - bs + 1);
} }

View file

@ -27,13 +27,14 @@
# define DIAG_INTERRUPT_OUT() # define DIAG_INTERRUPT_OUT()
#endif #endif
#ifdef UNITTEST #ifndef MOCKABLE
#define STATIC_MOCKME #define MOCKABLE(x) x
#else
#define STATIC_MOCKME static
#endif #endif
void Crc_InitStatus(struct crcstatus_t *st, CRC_TypeDef *crcUnit, DMA_TypeDef *dma, uint32_t stream) void Crc_StartNextTask(struct crcstatus_t *status);
void MOCKABLE(Crc_InitStatus)(struct crcstatus_t *st, CRC_TypeDef *crcUnit, DMA_TypeDef *dma, uint32_t stream)
{ {
st->crcUnit = crcUnit; st->crcUnit = crcUnit;
Dma_Init(&st->dmaInfo, dma, stream); Dma_Init(&st->dmaInfo, dma, stream);
@ -44,7 +45,8 @@ void Crc_InitStatus(struct crcstatus_t *st, CRC_TypeDef *crcUnit, DMA_TypeDef *d
st->firstSlot = NULL; st->firstSlot = NULL;
} }
void Crc_AttachTask(struct crcstatus_t *status, struct crcslotlistitem_t *slot, struct crcslottask_t *tasks, uint8_t taskCount)
void MOCKABLE(Crc_AttachTask)(struct crcstatus_t *status, struct crcslotlistitem_t *slot, struct crcslottask_t *tasks, uint8_t taskCount)
{ {
slot->count = taskCount; slot->count = taskCount;
slot->tasks = tasks; slot->tasks = tasks;
@ -57,7 +59,8 @@ void Crc_AttachTask(struct crcstatus_t *status, struct crcslotlistitem_t *slot,
__set_PRIMASK(prim); __set_PRIMASK(prim);
} }
uint8_t Crc_GetActiveTask(struct crcslotlistitem_t **slot_out, struct crcstatus_t volatile *status)
uint8_t MOCKABLE(Crc_GetActiveTask)(struct crcslotlistitem_t **slot_out, struct crcstatus_t volatile *status)
{ {
uint8_t ret; uint8_t ret;
@ -72,8 +75,24 @@ uint8_t Crc_GetActiveTask(struct crcslotlistitem_t **slot_out, struct crcstatus_
} }
uint8_t Crc_Enqueue(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, uint8_t MOCKABLE(Crc_IsSlotQueued)(struct crcslotlistitem_t *slot, uint8_t task) {
uint8_t *address, uint16_t len, void (*callback)(void*, uint32_t, uint8_t), void* callbackParam) return ((struct crcslottask_t volatile)slot->tasks[task]).address != NULL;
}
uint8_t MOCKABLE(Crc_IsSlotBusy)(struct crcslotlistitem_t *slot, uint8_t task) {
struct crcslottask_t volatile *taskPtr = &slot->tasks[task];
return taskPtr->callback != NULL || taskPtr->callbackParam != NULL;
}
void MOCKABLE(Crc_WaitResults)(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task) {
while(Crc_IsSlotBusy(slot, task));
}
uint8_t MOCKABLE(Crc_Enqueue)(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task,
void *address, uint16_t len, void (*callback)(void*, uint32_t, uint8_t), void* callbackParam)
{ {
uint32_t prim = __get_PRIMASK(); uint32_t prim = __get_PRIMASK();
uint16_t need_start; uint16_t need_start;
@ -93,6 +112,7 @@ uint8_t Crc_Enqueue(struct crcstatus_t *status, struct crcslotlistitem_t *slot,
__set_PRIMASK(prim); __set_PRIMASK(prim);
if(need_start) { if(need_start) {
DIAG_CRC_CALC_START();
status->crcUnit->CR = 1; status->crcUnit->CR = 1;
LL_DMA_SetM2MSrcAddress(status->dmaInfo.dma, status->dmaInfo.stream, (uint32_t)address); LL_DMA_SetM2MSrcAddress(status->dmaInfo.dma, status->dmaInfo.stream, (uint32_t)address);
LL_DMA_SetDataLength(status->dmaInfo.dma, status->dmaInfo.stream, (len+3)/4); LL_DMA_SetDataLength(status->dmaInfo.dma, status->dmaInfo.stream, (len+3)/4);
@ -102,7 +122,8 @@ uint8_t Crc_Enqueue(struct crcstatus_t *status, struct crcslotlistitem_t *slot,
return need_start; return need_start;
} }
uint32_t Crc_Compute(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, uint8_t *address, uint16_t len)
uint32_t MOCKABLE(Crc_Compute)(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, void *address, uint16_t len)
{ {
uint32_t result; uint32_t result;
Crc_Enqueue(status, slot, task, address, len, NULL, &result); Crc_Enqueue(status, slot, task, address, len, NULL, &result);
@ -110,8 +131,9 @@ uint32_t Crc_Compute(struct crcstatus_t *status, struct crcslotlistitem_t *slot,
return result; return result;
} }
// only called from ISR context // only called from ISR context
STATIC_MOCKME void Crc_StartNextTask(struct crcstatus_t *status) void MOCKABLE(Crc_StartNextTask)(struct crcstatus_t *status)
{ {
char moreTasks; char moreTasks;
uint8_t index = 0; uint8_t index = 0;
@ -122,6 +144,7 @@ STATIC_MOCKME void Crc_StartNextTask(struct crcstatus_t *status)
while(slot) { while(slot) {
if(index < slot->count) { if(index < slot->count) {
if(slot->tasks[index].address) { if(slot->tasks[index].address) {
DIAG_CRC_CALC_START();
status->activeSlot = slot; status->activeSlot = slot;
status->activeTask = index; status->activeTask = index;
status->crcUnit->CR = 1; status->crcUnit->CR = 1;
@ -141,8 +164,9 @@ STATIC_MOCKME void Crc_StartNextTask(struct crcstatus_t *status)
status->activeSlot = NULL; status->activeSlot = NULL;
} }
// !!!PORTABILITY WARNING!!! using registers and bits directly. should be reviewed extremely t
void Crc_HandleDmaIrq(struct crcstatus_t *status) // !!!PORTABILITY WARNING!!! using registers and bits directly. should be reviewed extremely when porting to a different MCU
void MOCKABLE(Crc_HandleDmaIrq)(struct crcstatus_t *status)
{ {
uint8_t success = 1; uint8_t success = 1;

View file

@ -46,29 +46,36 @@ void Crc_InitStatus(struct crcstatus_t *status, CRC_TypeDef *crcUnit, DMA_TypeDe
uint8_t Crc_GetActiveTask(struct crcslotlistitem_t **slot_out, struct crcstatus_t volatile *status); uint8_t Crc_GetActiveTask(struct crcslotlistitem_t **slot_out, struct crcstatus_t volatile *status);
static inline uint8_t Crc_IsSlotQueued(struct crcslotlistitem_t *slot, uint8_t task) { uint8_t Crc_IsSlotQueued(struct crcslotlistitem_t *slot, uint8_t task);
return ((struct crcslottask_t volatile)slot->tasks[task]).address != NULL;
}
static inline uint8_t Crc_IsSlotBusy(struct crcslotlistitem_t *slot, uint8_t task) { uint8_t Crc_IsSlotBusy(struct crcslotlistitem_t *slot, uint8_t task);
struct crcslottask_t volatile *taskPtr = &slot->tasks[task];
return taskPtr->callback != NULL || taskPtr->callbackParam != NULL;
}
static inline void Crc_WaitResults(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task) { void Crc_WaitResults(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task);
while(Crc_IsSlotBusy(slot, task));
}
void Crc_AttachTask(struct crcstatus_t *status, struct crcslotlistitem_t *slot, struct crcslottask_t *tasks, uint8_t taskCount); void Crc_AttachTask(struct crcstatus_t *status, struct crcslotlistitem_t *slot, struct crcslottask_t *tasks, uint8_t taskCount);
uint8_t Crc_Enqueue(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, uint8_t Crc_Enqueue(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task,
uint8_t *address, uint16_t len, void (*callback)(void*, uint32_t, uint8_t), void* callbackParam); void *address, uint16_t len, void (*callback)(void*, uint32_t, uint8_t), void* callbackParam);
uint32_t Crc_Compute(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, uint8_t *address, uint16_t len); uint32_t Crc_Compute(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, void *address, uint16_t len);
void Crc_ComputeAsync(struct crcstatus_t *status, uint8_t slot,
uint8_t *address, uint16_t len,
void (*callback)(void*, uint32_t, uint8_t), void* callbackParam);
void Crc_HandleDmaIrq(struct crcstatus_t *status); void Crc_HandleDmaIrq(struct crcstatus_t *status);
// !!!PRIVATE!!! exposed only to make mocking possible
void Crc_StartNextTask(struct crcstatus_t *status);
#ifdef UNITTEST
DECLARE_MOCK(Crc_InitStatus);
DECLARE_MOCK(Crc_GetActiveTask);
DECLARE_MOCK(Crc_IsSlotQueued);
DECLARE_MOCK(Crc_IsSlotBusy);
DECLARE_MOCK(Crc_WaitResults);
DECLARE_MOCK(Crc_AttachTask);
DECLARE_MOCK(Crc_Enqueue);
DECLARE_MOCK(Crc_Compute);
DECLARE_MOCK(Crc_HandleDmaIrq);
DECLARE_MOCK(Crc_StartNextTask);
#endif // UNITTEST
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -5,22 +5,10 @@
* Author: abody * Author: abody
*/ */
#include <f4ll_c/dmahelper.h> #include <f4ll_c/dmahelper.h>
#ifndef MOCKABLE
#ifndef DEFINE_MOCKPTR #define MOCKABLE(x) x
#define DEFINE_MOCKPTR(...)
#endif #endif
#ifdef UNITTEST
DEFINE_MOCKPTR(volatile uint32_t*, Dma_GetIsReg, DMA_TypeDef*, uint32_t)
DEFINE_MOCKPTR(volatile uint32_t*, Dma_GetIfcReg, DMA_TypeDef*, uint32_t)
DEFINE_MOCKPTR(uint32_t, Dma_GetDmeMask, uint32_t)
DEFINE_MOCKPTR(uint32_t, Dma_GetTeMask, uint32_t)
DEFINE_MOCKPTR(uint32_t, Dma_GetHtMask, uint32_t)
DEFINE_MOCKPTR(uint32_t, Dma_GetTcMask, uint32_t)
DEFINE_MOCKPTR(uint32_t, Dma_GetFeMask, uint32_t)
DEFINE_MOCKPTR(void, Dma_Init, struct dmainfo_t*, DMA_TypeDef*, uint32_t)
#endif // UNITTEST
volatile uint32_t* MOCKABLE(Dma_GetIsReg)(DMA_TypeDef *dma, uint32_t stream) volatile uint32_t* MOCKABLE(Dma_GetIsReg)(DMA_TypeDef *dma, uint32_t stream)
{ {
if(dma == DMA1) if(dma == DMA1)
@ -29,6 +17,7 @@ volatile uint32_t* MOCKABLE(Dma_GetIsReg)(DMA_TypeDef *dma, uint32_t stream)
return (stream < LL_DMA_STREAM_4) ? &DMA2->LISR : &DMA2->HISR; return (stream < LL_DMA_STREAM_4) ? &DMA2->LISR : &DMA2->HISR;
} }
volatile uint32_t* MOCKABLE(Dma_GetIfcReg)(DMA_TypeDef *dma, uint32_t stream) volatile uint32_t* MOCKABLE(Dma_GetIfcReg)(DMA_TypeDef *dma, uint32_t stream)
{ {
if(dma == DMA1) if(dma == DMA1)

View file

@ -10,11 +10,8 @@
#include <inttypes.h> #include <inttypes.h>
#include <platform/dma_ll.h> #include <platform/dma_ll.h>
#ifndef DECLARE_MOCKPTR #ifndef DECLARE_MOCK
#define DECLARE_MOCKPTR(...) #define DECLARE_MOCK(x)
#endif
#ifndef MOCKABLE
#define MOCKABLE(x) x
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
@ -33,25 +30,25 @@ struct dmainfo_t {
uint32_t tcMask; uint32_t tcMask;
}; };
#ifdef UNITTEST volatile uint32_t* Dma_GetIsReg(DMA_TypeDef *dma, uint32_t stream);
DECLARE_MOCKPTR(volatile uint32_t*, Dma_GetIsReg, DMA_TypeDef*, uint32_t) volatile uint32_t* Dma_GetIfcReg(DMA_TypeDef *dma, uint32_t stream);
DECLARE_MOCKPTR(volatile uint32_t*, Dma_GetIfcReg, DMA_TypeDef*, uint32_t) uint32_t Dma_GetDmeMask(uint32_t stream);
DECLARE_MOCKPTR(uint32_t, Dma_GetDmeMask, uint32_t) uint32_t Dma_GetTeMask(uint32_t stream);
DECLARE_MOCKPTR(uint32_t, Dma_GetTeMask, uint32_t) uint32_t Dma_GetHtMask(uint32_t stream);
DECLARE_MOCKPTR(uint32_t, Dma_GetHtMask, uint32_t) uint32_t Dma_GetTcMask(uint32_t stream);
DECLARE_MOCKPTR(uint32_t, Dma_GetTcMask, uint32_t) uint32_t Dma_GetFeMask(uint32_t stream);
DECLARE_MOCKPTR(uint32_t, Dma_GetFeMask, uint32_t) void Dma_Init(struct dmainfo_t *info, DMA_TypeDef *dma, uint32_t stream);
DECLARE_MOCKPTR(void, Dma_Init, struct dmainfo_t*, DMA_TypeDef*, uint32_t)
#endif // UNITTEST
volatile uint32_t* MOCKABLE(Dma_GetIsReg)(DMA_TypeDef *dma, uint32_t stream); #ifdef UNITTEST
volatile uint32_t* MOCKABLE(Dma_GetIfcReg)(DMA_TypeDef *dma, uint32_t stream); DECLARE_MOCK(Dma_GetIsReg);
uint32_t MOCKABLE(Dma_GetDmeMask)(uint32_t stream); DECLARE_MOCK(Dma_GetIfcReg);
uint32_t MOCKABLE(Dma_GetTeMask)(uint32_t stream); DECLARE_MOCK(Dma_GetDmeMask);
uint32_t MOCKABLE(Dma_GetHtMask)(uint32_t stream); DECLARE_MOCK(Dma_GetTeMask);
uint32_t MOCKABLE(Dma_GetTcMask)(uint32_t stream); DECLARE_MOCK(Dma_GetHtMask);
uint32_t MOCKABLE(Dma_GetFeMask)(uint32_t stream); DECLARE_MOCK(Dma_GetTcMask);
void MOCKABLE(Dma_Init)(struct dmainfo_t *info, DMA_TypeDef *dma, uint32_t stream); DECLARE_MOCK(Dma_GetFeMask);
DECLARE_MOCK(Dma_Init);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -15,17 +15,21 @@
# define DIAG_INTERRUPT_OUT() # define DIAG_INTERRUPT_OUT()
#endif #endif
#ifndef MOCKABLE
#define MOCKABLE(x) x
#endif // MOCKABLE
volatile uint8_t g_memcpyDmaBusy = 0; volatile uint8_t g_memcpyDmaBusy = 0;
static struct dmainfo_t g_memcpyDmaInfo; static struct dmainfo_t g_memcpyDmaInfo;
void Mcd_Init(DMA_TypeDef *dma, uint32_t stream) void MOCKABLE(Mcd_Init)(DMA_TypeDef *dma, uint32_t stream)
{ {
Dma_Init(&g_memcpyDmaInfo, dma, stream); Dma_Init(&g_memcpyDmaInfo, dma, stream);
LL_DMA_EnableIT_TC(dma, stream); LL_DMA_EnableIT_TC(dma, stream);
} }
void * Mcd_Copy(void *dst, void const *src, size_t length) void * MOCKABLE(Mcd_Copy)(void *dst, void const *src, size_t length)
{ {
LL_DMA_SetM2MSrcAddress(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream, (uint32_t)src); LL_DMA_SetM2MSrcAddress(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream, (uint32_t)src);
LL_DMA_SetM2MDstAddress(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream, (uint32_t)dst); LL_DMA_SetM2MDstAddress(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream, (uint32_t)dst);
@ -36,7 +40,7 @@ void * Mcd_Copy(void *dst, void const *src, size_t length)
return dst; return dst;
} }
void Mcd_HandleDmaIrq() void MOCKABLE(Mcd_HandleDmaIrq)(void)
{ {
DIAG_INTERRUPT_IN(); DIAG_INTERRUPT_IN();
if(*g_memcpyDmaInfo.isReg & g_memcpyDmaInfo.tcMask) { // DMA transfer complete if(*g_memcpyDmaInfo.isReg & g_memcpyDmaInfo.tcMask) { // DMA transfer complete

View file

@ -17,7 +17,13 @@ extern "C" {
void Mcd_Init(DMA_TypeDef *dma, uint32_t stream); void Mcd_Init(DMA_TypeDef *dma, uint32_t stream);
void * Mcd_Copy(void *dst, void const *src, size_t length); void * Mcd_Copy(void *dst, void const *src, size_t length);
void Mcd_HandleDmaIrq(); void Mcd_HandleDmaIrq(void);
#ifdef UNITTEST
DECLARE_MOCK(Mcd_Init);
DECLARE_MOCK(Mcd_Copy);
DECLARE_MOCK(Mcd_HandleDmaIrq);
#endif // UNITTEST
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -15,6 +15,10 @@
#include "f4ll_c/dmahelper.h" #include "f4ll_c/dmahelper.h"
#include "f4ll_c/crcscheduler.h" #include "f4ll_c/crcscheduler.h"
#ifndef MOCKABLE
#define MOCKABLE(x) x
#endif
#ifndef DIAG_RX_BUFFER_SWITCH #ifndef DIAG_RX_BUFFER_SWITCH
# define DIAG_RX_BUFFER_SWITCH(x) # define DIAG_RX_BUFFER_SWITCH(x)
#endif #endif
@ -32,7 +36,51 @@ static inline uint32_t RoundUpTo4(uint32_t inp)
return (inp + 3) & 0xfffc; return (inp + 3) & 0xfffc;
} }
void Pku_Init( #ifndef USART_STATS_DISABLED
static inline void StatsIncOverrun(struct usart_stats *s) {
++s->overrun;
}
static inline void StatsIncHdrError(struct usart_stats *s, uint32_t hdr) {
++s->hdrError;
s->lastErrHdr = hdr;
}
static inline void StatsIncPayloadError(struct usart_stats *s, uint32_t pep1, uint32_t pep2) {
++s->payloadErrror;
s->pep1 = pep1;
s->pep2 = pep2;
}
static inline void StatsIncDmaError(struct usart_stats *s) {
++s->dmaError;
}
static inline void StatsIncRcvd(struct usart_stats *s) {
++s->rcvd;
}
static inline void StatsIncPremature_hdr(struct usart_stats *s) {
++s->premature_hdr;
}
static inline void StatsIncPremature_payload(struct usart_stats *s) {
++s->premature_payload;
}
static inline void StatsIncSent(struct usart_stats *s) {
++s->sent;
}
static inline void StatsAddSkiped(struct usart_stats *s, uint8_t cnt) {
s->skiped += s->rcvd > 2 ? cnt : 0;
}
#else // USART_STATS_DISABLED
#define StatsIncOverrun(x)
#define StatsIncHdrError(x,y)
#define StatsIncPayloadError(x,y,z)
#define StatsIncDmaError(x)
#define StatsIncRcvd(x)
#define StatsIncPremature_hdr(x)
#define StatsIncPremature_payload(x)
#define StatsIncSent(x)
#define StatsAddSkiped(x)
#endif // USART_STATS_DISABLED
void MOCKABLE(Pu_Init)(
struct usartstatus_t *st, USART_TypeDef *usart, DMA_TypeDef *dma, struct usartstatus_t *st, USART_TypeDef *usart, DMA_TypeDef *dma,
uint32_t stream_rx, uint32_t stream_tx, uint32_t stream_rx, uint32_t stream_tx,
struct crcstatus_t *crcStatus, struct crcstatus_t *crcStatus,
@ -49,17 +97,17 @@ void Pku_Init(
st->txBuffer.busy = 0; st->txBuffer.busy = 0;
st->txBuffer.error = 0; st->txBuffer.error = 0;
st->txBuffer.requestedLength = 0; st->txBuffer.requestedLength = 0;
st->txBuffer.usartStatus = st;
st->rxBuffers[0].busy = 0; st->rxBuffers[0].busy = 0;
st->rxBuffers[1].busy = 0; st->rxBuffers[1].busy = 0;
st->rxBuffers[0].error = 0; st->rxBuffers[0].error = 0;
st->rxBuffers[1].error = 0; st->rxBuffers[1].error = 0;
st->rxBuffers[0].requestedLength = 0; st->rxBuffers[0].requestedLength = 0;
st->rxBuffers[1].requestedLength = 0; st->rxBuffers[1].requestedLength = 0;
st->txBuffer.usartStatus = st;
st->rxBuffers[0].usartStatus = st; st->rxBuffers[0].usartStatus = st;
st->rxBuffers[1].usartStatus = st; st->rxBuffers[1].usartStatus = st;
st->packetReceivedCallback = packetReceivedCallback; st->packetReceivedCallback = packetReceivedCallback;
st->packetReceivedCallbacParam = packetReceivedCallbackParam; st->packetReceivedCallbackParam = packetReceivedCallbackParam;
st->rxSerial = -1; st->rxSerial = -1;
st->txSerial = 0; st->txSerial = 0;
st->activeRxBuf = 0; st->activeRxBuf = 0;
@ -82,52 +130,46 @@ void Pku_Init(
} }
uint8_t* Pku_GetTxBuffer(struct usartstatus_t *status) uint8_t* MOCKABLE(Pu_GetTxBuffer)(struct usartstatus_t *status)
{ {
return status->txBuffer.packet.payload; return status->txBuffer.packet.payload;
} }
static inline void BuildHeader(struct usart_buffer_t *buffer, uint8_t serial, uint8_t length) uint8_t MOCKABLE(Pu_CheckHeader)(struct usartpacket_t *packet)
{
uint8_t hash = STARTMARKER;
buffer->packet.header.startByte = STARTMARKER;
buffer->packet.header.serial = serial;
hash ^= serial;
buffer->packet.header.payloadLength = length - 1;
hash ^= length - 1;
buffer->packet.header.hash = hash;
}
static inline uint8_t CheckHeader(struct usartpacket_t *packet)
{ {
return packet->header.startByte == STARTMARKER && (packet->header.startByte ^ packet->header.serial ^ packet->header.payloadLength) == packet->header.hash; return packet->header.startByte == STARTMARKER && (packet->header.startByte ^ packet->header.serial ^ packet->header.payloadLength) == packet->header.hash;
} }
uint8_t Pku_Post(struct usartstatus_t *status, uint8_t const *payload, uint16_t length, struct crcstatus_t *crcStatus, uint8_t waitForCrcQueue) uint8_t MOCKABLE(Pu_Post)(struct usartstatus_t *status, uint8_t const *payload, uint8_t length, struct crcstatus_t *crcStatus, uint8_t waitForCrcQueue)
{ {
if(length > 256) struct usart_buffer_t *buffer = &status->txBuffer;
return 1; uint8_t hash = STARTMARKER;
buffer->packet.header.startByte = STARTMARKER;
buffer->packet.header.serial = status->txSerial;
hash ^= status->txSerial++;
buffer->packet.header.payloadLength = length;
hash ^= length;
buffer->packet.header.hash = hash;
BuildHeader(&status->txBuffer, status->txSerial++, length);
uint16_t payloadLength = RoundUpTo4(length); uint16_t payloadLength = RoundUpTo4(length);
if(payload) if(payload)
memcpy(status->txBuffer.packet.payload, payload, length); memcpy(status->txBuffer.packet.payload, payload, length);
status->txBuffer.requestedLength = sizeof(struct usartpacketheader_t) + payloadLength + sizeof(uint32_t); // +4 for the hash status->txBuffer.requestedLength = sizeof(struct usartpacketheader_t) + payloadLength + sizeof(uint32_t); // +4 for the hash
status->txBuffer.busy = 1; status->txBuffer.busy = 1;
status->txBuffer.error = 0; status->txBuffer.error = 0;
Crc_Enqueue(status->crcStatus, &status->crcSlot, 0, status->txBuffer.packet.payload, length, Crc_Enqueue(status->crcStatus, &status->crcSlot, 0, &status->txBuffer.packet, sizeof(status->txBuffer.packet.header) + payloadLength,
NULL, (uint32_t*)(status->txBuffer.packet.payload + payloadLength)); NULL, (uint32_t*)(status->txBuffer.packet.payload + payloadLength));
while(waitForCrcQueue && Crc_IsSlotQueued(&status->crcSlot, 0)); while(waitForCrcQueue && Crc_IsSlotQueued(&status->crcSlot, 0));
Pku_SetupTransmit(status->usart, status->txDmaInfo.dma, status->txDmaInfo.stream, &status->txBuffer.packet, status->txBuffer.requestedLength); Pu_SetupTransmit(status->usart, status->txDmaInfo.dma, status->txDmaInfo.stream, &status->txBuffer.packet, status->txBuffer.requestedLength);
StatsIncSent(&status->stats); StatsIncSent(&status->stats);
return 0; return 0;
} }
void Pku_SetupReceive(struct usartstatus_t *status) void MOCKABLE(Pu_SetupReceive)(struct usartstatus_t *status)
{ {
uint8_t packetIndex = status->activeRxBuf; uint8_t packetIndex = status->activeRxBuf;
@ -141,12 +183,21 @@ void Pku_SetupReceive(struct usartstatus_t *status)
} }
void Pku_ConsumePacket(struct usartstatus_t *status, uint8_t packetIndex) void MOCKABLE(Pu_SetupTransmit)(USART_TypeDef *usart, DMA_TypeDef* dma, uint32_t stream, void *buffer, uint32_t length)
{
LL_DMA_ConfigAddresses(dma, stream, (uint32_t)buffer, LL_USART_DMA_GetRegAddr(usart), LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetDataLength(dma, stream, length);
LL_USART_EnableDMAReq_TX(usart);
LL_DMA_EnableStream(dma, stream);
}
void MOCKABLE(Pu_ConsumePacket)(struct usartstatus_t *status, uint8_t packetIndex)
{ {
struct usart_buffer_t *buffer = &status->rxBuffers[packetIndex]; struct usart_buffer_t *buffer = &status->rxBuffers[packetIndex];
if(buffer->busy) { if(buffer->busy) {
if(buffer->error) if(buffer->error)
StatsIncPayloadError(&status->stats, buffer->errorInfo, *(uint32_t*) (buffer->packet.payload + RoundUpTo4(buffer->packet.header.payloadLength + 1))); StatsIncPayloadError(&status->stats, buffer->errorInfo, *(uint32_t*) (buffer->packet.payload + RoundUpTo4(buffer->packet.header.payloadLength)));
else { else {
uint8_t diff = buffer->packet.header.serial - status->rxSerial; uint8_t diff = buffer->packet.header.serial - status->rxSerial;
if(diff > 1) if(diff > 1)
@ -159,45 +210,24 @@ void Pku_ConsumePacket(struct usartstatus_t *status, uint8_t packetIndex)
} }
void Pku_SetupTransmit(USART_TypeDef *usart, DMA_TypeDef* dma, uint32_t stream, void *buffer, uint32_t length) void MOCKABLE(Pu_HandleRxDmaIrq)(struct usartstatus_t *status)
{
LL_DMA_ConfigAddresses(dma, stream, (uint32_t)buffer, LL_USART_DMA_GetRegAddr(usart), LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetDataLength(dma, stream, length);
LL_USART_EnableDMAReq_TX(usart);
LL_DMA_EnableStream(dma, stream);
}
void RxCrcComputedCallback(void *callbackParm, uint32_t calculatedCrc, uint8_t success)
{
struct usart_buffer_t *ub = (struct usart_buffer_t*) callbackParm;
if(!success)
ub->error = 1;
else if(*(uint32_t*) (ub->packet.payload + RoundUpTo4(ub->packet.header.payloadLength + 1)) == calculatedCrc)
ub->busy = 1;
else {
ub->error = ub->busy = 1;
ub->errorInfo = calculatedCrc;
}
if(ub->usartStatus->packetReceivedCallback)
ub->usartStatus->packetReceivedCallback(ub->usartStatus->packetReceivedCallbacParam, ub);
}
void Pku_HandleRxDmaIrq(struct usartstatus_t *status)
{ {
DIAG_INTERRUPT_IN(); DIAG_INTERRUPT_IN();
StatsIncRcvd(&status->stats); StatsIncRcvd(&status->stats);
if(*status->rxDmaInfo.isReg & status->rxDmaInfo.tcMask) { if(*status->rxDmaInfo.isReg & status->rxDmaInfo.tcMask) {
*status->rxDmaInfo.ifcReg = status->rxDmaInfo.tcMask; *status->rxDmaInfo.ifcReg = status->rxDmaInfo.tcMask;
if(CheckHeader(&status->rxBuffers[status->activeRxBuf].packet)) if(Pu_CheckHeader(&status->rxBuffers[status->activeRxBuf].packet)) {
Crc_Enqueue(status->crcStatus, &status->crcSlot, 1, Crc_Enqueue(status->crcStatus, &status->crcSlot, 1,
status->rxBuffers[status->activeRxBuf].packet.payload, &status->rxBuffers[status->activeRxBuf].packet,
status->rxBuffers[status->activeRxBuf].packet.header.payloadLength +1, RoundUpTo4(status->rxBuffers[status->activeRxBuf].packet.header.payloadLength) + sizeof(struct usartpacketheader_t),
RxCrcComputedCallback, &status->rxBuffers[status->activeRxBuf]); Pu_RxCrcComputedCallback, &status->rxBuffers[status->activeRxBuf]);
else { } else {
StatsIncHdrError(&status->stats, *(uint32_t*)&status->rxBuffers[status->activeRxBuf].packet.header); StatsIncHdrError(&status->stats, *(uint32_t*)&status->rxBuffers[status->activeRxBuf].packet.header);
status->rxBuffers[status->activeRxBuf].error = 1; status->rxBuffers[status->activeRxBuf].error = 1;
} }
} else if(*status->rxDmaInfo.isReg & status->rxDmaInfo.teMask) { }
if(*status->rxDmaInfo.isReg & status->rxDmaInfo.teMask) {
*status->rxDmaInfo.ifcReg = status->rxDmaInfo.teMask; *status->rxDmaInfo.ifcReg = status->rxDmaInfo.teMask;
status->rxBuffers[status->activeRxBuf].error = 1; status->rxBuffers[status->activeRxBuf].error = 1;
} }
@ -207,11 +237,28 @@ void Pku_HandleRxDmaIrq(struct usartstatus_t *status)
DIAG_RX_BUFFER_SWITCH(status->activeRxBuf); DIAG_RX_BUFFER_SWITCH(status->activeRxBuf);
if(status->rxBuffers[status->activeRxBuf].busy) if(status->rxBuffers[status->activeRxBuf].busy)
StatsIncOverrun(&status->stats); StatsIncOverrun(&status->stats);
Pku_SetupReceive(status); Pu_SetupReceive(status);
DIAG_INTERRUPT_OUT(); DIAG_INTERRUPT_OUT();
} }
void Pku_HandleTxDmaIrq(struct usartstatus_t *status)
void MOCKABLE(Pu_RxCrcComputedCallback)(void *callbackParm, uint32_t calculatedCrc, uint8_t success)
{
struct usart_buffer_t *ub = (struct usart_buffer_t*) callbackParm;
if(!success)
ub->error = 1;
else if(*(uint32_t*) (ub->packet.payload + RoundUpTo4(ub->packet.header.payloadLength)) == calculatedCrc)
ub->busy = 1;
else {
ub->error = ub->busy = 1;
ub->errorInfo = calculatedCrc;
}
if(ub->usartStatus->packetReceivedCallback)
ub->usartStatus->packetReceivedCallback(ub->usartStatus->packetReceivedCallbackParam, ub);
}
void MOCKABLE(Pu_HandleTxDmaIrq)(struct usartstatus_t *status)
{ {
DIAG_INTERRUPT_IN(); DIAG_INTERRUPT_IN();
if(*status->txDmaInfo.isReg & status->txDmaInfo.tcMask) { // DMA transfer complete if(*status->txDmaInfo.isReg & status->txDmaInfo.tcMask) { // DMA transfer complete
@ -219,9 +266,11 @@ void Pku_HandleTxDmaIrq(struct usartstatus_t *status)
LL_USART_EnableIT_TC(status->usart); LL_USART_EnableIT_TC(status->usart);
LL_DMA_DisableStream(status->txDmaInfo.dma, status->txDmaInfo.stream); LL_DMA_DisableStream(status->txDmaInfo.dma, status->txDmaInfo.stream);
} }
else if(*status->txDmaInfo.isReg & status->txDmaInfo.teMask) { if(*status->txDmaInfo.isReg & status->txDmaInfo.teMask) {
*status->txDmaInfo.ifcReg = status->txDmaInfo.teMask; *status->txDmaInfo.ifcReg = status->txDmaInfo.teMask;
status->txBuffer.error = 1; status->txBuffer.error = 1;
LL_USART_EnableIT_TC(status->usart);
LL_DMA_DisableStream(status->txDmaInfo.dma, status->txDmaInfo.stream);
StatsIncDmaError(&status->stats); StatsIncDmaError(&status->stats);
} }
if(*status->txDmaInfo.isReg & status->txDmaInfo.feMask) if(*status->txDmaInfo.isReg & status->txDmaInfo.feMask)
@ -233,26 +282,29 @@ void Pku_HandleTxDmaIrq(struct usartstatus_t *status)
DIAG_INTERRUPT_OUT(); DIAG_INTERRUPT_OUT();
} }
void Pku_HandleUsartIrq(struct usartstatus_t *status)
void MOCKABLE(Pu_HandleUsartIrq)(struct usartstatus_t *status)
{ {
DIAG_INTERRUPT_IN(); DIAG_INTERRUPT_IN();
if(LL_USART_IsActiveFlag_IDLE(status->usart) && LL_USART_IsEnabledIT_IDLE(status->usart)) { // receiver idle if(LL_USART_IsActiveFlag_IDLE(status->usart) && LL_USART_IsEnabledIT_IDLE(status->usart)) { // receiver idle
LL_USART_ClearFlag_IDLE(status->usart); LL_USART_ClearFlag_IDLE(status->usart);
uint16_t rcvdLen = status->rxBuffers[status->activeRxBuf].requestedLength - LL_DMA_GetDataLength(status->rxDmaInfo.dma, status->rxDmaInfo.stream); uint16_t rcvdLen = status->rxBuffers[status->activeRxBuf].requestedLength - LL_DMA_GetDataLength(status->rxDmaInfo.dma, status->rxDmaInfo.stream);
if(rcvdLen >= sizeof(struct usartpacketheader_t)) { if(rcvdLen >= sizeof(struct usartpacketheader_t)) {
if(CheckHeader(&status->rxBuffers[status->activeRxBuf].packet)) { if(Pu_CheckHeader(&status->rxBuffers[status->activeRxBuf].packet)) {
if(rcvdLen >= sizeof(struct usartpacketheader_t) + RoundUpTo4(status->rxBuffers[status->activeRxBuf].packet.header.payloadLength + 1) + sizeof(uint32_t)) if(rcvdLen >= sizeof(struct usartpacketheader_t) + RoundUpTo4(status->rxBuffers[status->activeRxBuf].packet.header.payloadLength) + sizeof(uint32_t))
LL_DMA_DisableStream(status->rxDmaInfo.dma, status->rxDmaInfo.stream); LL_DMA_DisableStream(status->rxDmaInfo.dma, status->rxDmaInfo.stream);
else else
StatsIncPremature_payload(&status->stats); StatsIncPremature_payload(&status->stats);
} else { } else {
status->rxBuffers[status->activeRxBuf].error = 1; status->rxBuffers[status->activeRxBuf].error = 1;
status->rxBuffers[status->activeRxBuf].busy = 1;
LL_DMA_DisableStream(status->rxDmaInfo.dma, status->rxDmaInfo.stream); LL_DMA_DisableStream(status->rxDmaInfo.dma, status->rxDmaInfo.stream);
} }
} else } else
StatsIncPremature_hdr(&status->stats); StatsIncPremature_hdr(&status->stats);
} }
else if(LL_USART_IsActiveFlag_TC(status->usart) && LL_USART_IsEnabledIT_TC(status->usart)) { // transmission complete
if(LL_USART_IsActiveFlag_TC(status->usart) && LL_USART_IsEnabledIT_TC(status->usart)) { // transmission complete
LL_USART_DisableIT_TC(status->usart); LL_USART_DisableIT_TC(status->usart);
LL_USART_DisableDirectionTx(status->usart); // enforcing an idle frame LL_USART_DisableDirectionTx(status->usart); // enforcing an idle frame
LL_USART_EnableDirectionTx(status->usart); LL_USART_EnableDirectionTx(status->usart);

View file

@ -7,10 +7,10 @@
#ifndef USART_HANDLER_H_ #ifndef USART_HANDLER_H_
#define USART_HANDLER_H_ #define USART_HANDLER_H_
#include <f4ll_c/crcscheduler.h>
#include <inttypes.h> #include <inttypes.h>
#include <platform/usart_ll.h>
#include "f4ll_c/dmahelper.h" #include "f4ll_c/dmahelper.h"
#include <f4ll_c/crcscheduler.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -18,25 +18,43 @@ extern "C" {
struct usart_buffer_t; struct usart_buffer_t;
struct usartstatus_t; struct usartstatus_t;
struct usartpacket_t;
typedef void (*pku_packetreceivedcallback_t)(void *userParam, struct usart_buffer_t *buffer); typedef void (*pku_packetreceivedcallback_t)(void *userParam, struct usart_buffer_t *buffer);
void Pku_Init( void Pu_Init(
struct usartstatus_t *st, USART_TypeDef *usart, DMA_TypeDef *dma, struct usartstatus_t *st, USART_TypeDef *usart, DMA_TypeDef *dma,
uint32_t stream_rx, uint32_t stream_tx, uint32_t stream_rx, uint32_t stream_tx,
struct crcstatus_t *crcStatus, struct crcstatus_t *crcStatus,
pku_packetreceivedcallback_t packetReceivedCallback, void * packetReceivedCallbackParam); pku_packetreceivedcallback_t packetReceivedCallback, void * packetReceivedCallbackParam);
uint8_t* Pku_GetTxBuffer(struct usartstatus_t *status); uint8_t* Pu_GetTxBuffer(struct usartstatus_t *status);
uint8_t Pku_Post(struct usartstatus_t *status, uint8_t const *payload, uint16_t length, struct crcstatus_t *crcStatus, uint8_t waitForCrcQueue); uint8_t Pu_Post(struct usartstatus_t *status, uint8_t const *payload, uint8_t length, struct crcstatus_t *crcStatus, uint8_t waitForCrcQueue);
void Pku_SetupReceive(struct usartstatus_t *status); void Pu_SetupReceive(struct usartstatus_t *status);
void Pku_SetupTransmit(USART_TypeDef *usart, DMA_TypeDef* dma, uint32_t stream, void *buffer, uint32_t length); void Pu_SetupTransmit(USART_TypeDef *usart, DMA_TypeDef* dma, uint32_t stream, void *buffer, uint32_t length);
void Pku_ConsumePacket(struct usartstatus_t *status, uint8_t packetIndex); void Pu_ConsumePacket(struct usartstatus_t *status, uint8_t packetIndex);
void Pku_HandleRxDmaIrq(struct usartstatus_t *status); void Pu_HandleRxDmaIrq(struct usartstatus_t *status);
void Pku_HandleTxDmaIrq(struct usartstatus_t *status); void Pu_HandleTxDmaIrq(struct usartstatus_t *status);
void Pku_HandleUsartIrq(struct usartstatus_t *status); void Pu_HandleUsartIrq(struct usartstatus_t *status);
// !!!Private!!! exposed only to make unit testing possible
void Pu_RxCrcComputedCallback(void *callbackParm, uint32_t calculatedCrc, uint8_t success);
uint8_t Pu_CheckHeader(struct usartpacket_t *packet);
DECLARE_MOCK(Pu_Init);
DECLARE_MOCK(Pu_GetTxBuffer);
DECLARE_MOCK(Pu_Post);
DECLARE_MOCK(Pu_SetupReceive);
DECLARE_MOCK(Pu_SetupTransmit);
DECLARE_MOCK(Pu_ConsumePacket);
DECLARE_MOCK(Pu_ConsumePacket);
DECLARE_MOCK(Pu_HandleRxDmaIrq);
DECLARE_MOCK(Pu_HandleTxDmaIrq);
DECLARE_MOCK(Pu_HandleUsartIrq);
DECLARE_MOCK(Pu_RxCrcComputedCallback);
DECLARE_MOCK(Pu_CheckHeader);
/****************************************************************************************** /******************************************************************************************
* *
@ -94,54 +112,11 @@ struct usartstatus_t {
struct usart_stats stats; struct usart_stats stats;
uint8_t activeRxBuf; uint8_t activeRxBuf;
pku_packetreceivedcallback_t packetReceivedCallback; pku_packetreceivedcallback_t packetReceivedCallback;
void *packetReceivedCallbacParam; void *packetReceivedCallbackParam;
struct usart_buffer_t txBuffer; struct usart_buffer_t txBuffer;
struct usart_buffer_t rxBuffers[2]; struct usart_buffer_t rxBuffers[2];
}; };
#ifndef USART_STATS_DISABLED
static inline void StatsIncOverrun(struct usart_stats *s) {
++s->overrun;
}
static inline void StatsIncHdrError(struct usart_stats *s, uint32_t hdr) {
++s->hdrError;
s->lastErrHdr = hdr;
}
static inline void StatsIncPayloadError(struct usart_stats *s, uint32_t pep1, uint32_t pep2) {
++s->payloadErrror;
s->pep1 = pep1;
s->pep2 = pep2;
}
static inline void StatsIncDmaError(struct usart_stats *s) {
++s->dmaError;
}
static inline void StatsIncRcvd(struct usart_stats *s) {
++s->rcvd;
}
static inline void StatsIncPremature_hdr(struct usart_stats *s) {
++s->premature_hdr;
}
static inline void StatsIncPremature_payload(struct usart_stats *s) {
++s->premature_payload;
}
static inline void StatsIncSent(struct usart_stats *s) {
++s->sent;
}
static inline void StatsAddSkiped(struct usart_stats *s, uint8_t cnt) {
s->skiped += s->rcvd > 2 ? cnt : 0;
}
#else // USART_STATS_DISABLED
#define StatsIncOverrun(x)
#define StatsIncHdrError(x,y)
#define StatsIncPayloadError(x,y,z)
#define StatsIncDmaError(x)
#define StatsIncRcvd(x)
#define StatsIncPremature_hdr(x)
#define StatsIncPremature_payload(x)
#define StatsIncSent(x)
#define StatsAddSkiped(x)
#endif // USART_STATS_DISABLED
#ifdef __cplusplus #ifdef __cplusplus
} }