tmp 1
This commit is contained in:
parent
bc01b1f0e8
commit
3957af107d
235 changed files with 159562 additions and 189150 deletions
79
components/f4ll/src/console_handler.cpp
Normal file
79
components/f4ll/src/console_handler.cpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* ll_consolehandler.cpp
|
||||
*
|
||||
* Created on: Nov 7, 2019
|
||||
* Author: abody
|
||||
*/
|
||||
|
||||
#include <f4ll/console_handler.h>
|
||||
#include <f4ll/str_util.h>
|
||||
|
||||
namespace f4ll {
|
||||
|
||||
console_handler::console_handler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx)
|
||||
: usart_core(usart, dma, streamRx, streamTx)
|
||||
{
|
||||
}
|
||||
|
||||
void console_handler::ReceiverIdle(void) {}
|
||||
|
||||
void console_handler::TransmissionComplete(void) {}
|
||||
|
||||
void console_handler::FramingError(void) {}
|
||||
|
||||
void console_handler::Overrun(void) {}
|
||||
|
||||
void console_handler::RxDmaTransferComplete(void) {}
|
||||
|
||||
void console_handler::RxDmaHalfTransfer(void) {}
|
||||
|
||||
void console_handler::RxDmaError(dma_helper::DmaErrorType reason)
|
||||
{
|
||||
(void)reason;
|
||||
}
|
||||
|
||||
void console_handler::TxDmaTransferComplete(void)
|
||||
{
|
||||
LL_USART_EnableIT_TC(m_usart);
|
||||
LL_DMA_DisableStream(m_txDma.GetDma(), m_txDma.GetStream());
|
||||
}
|
||||
|
||||
void console_handler::TxDmaHalfTransfer(void) {}
|
||||
|
||||
void console_handler::TxDmaError(dma_helper::DmaErrorType reason)
|
||||
{
|
||||
(void)reason;
|
||||
}
|
||||
|
||||
#define ADDINFO(b, s, u) \
|
||||
b += strcpy_ex(b, s); \
|
||||
b += uitodec(b, u);
|
||||
|
||||
void console_handler::PrintStats(uint8_t id, PacketUsart &usart)
|
||||
{
|
||||
char ids[] = " : ";
|
||||
char *buffer = m_buffer;
|
||||
PacketUsart::Stats const &stats(usart.GetStats());
|
||||
|
||||
ids[0] = id + '0';
|
||||
buffer += strcpy_ex(buffer, ids);
|
||||
ADDINFO(buffer, " s: ", stats.sent);
|
||||
ADDINFO(buffer, " r: ", stats.rcvd);
|
||||
ADDINFO(buffer, " sk: ", stats.skiped);
|
||||
ADDINFO(buffer, " or: ", stats.overrun);
|
||||
ADDINFO(buffer, " he: ", stats.hdrError);
|
||||
ADDINFO(buffer, " pe: ", stats.payloadErrror);
|
||||
buffer += strcpy_ex(buffer, ",0x");
|
||||
buffer += uitohex(buffer, stats.pep1, 8);
|
||||
buffer += strcpy_ex(buffer, ",0x");
|
||||
buffer += uitohex(buffer, stats.pep2, 8);
|
||||
ADDINFO(buffer, " rde: ", stats.rxDmaError);
|
||||
ADDINFO(buffer, " tde: ", stats.txDmaError);
|
||||
ADDINFO(buffer, " pmh: ", stats.premature_hdr);
|
||||
ADDINFO(buffer, " pmp: ", stats.premature_payload);
|
||||
buffer += strcpy_ex(buffer, "\r\n");
|
||||
|
||||
SetupTransmit(m_buffer, buffer - m_buffer + 1);
|
||||
}
|
||||
|
||||
} /* namespace f4ll */
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* ll_consolehandler.cpp
|
||||
*
|
||||
* Created on: Nov 7, 2019
|
||||
* Author: abody
|
||||
*/
|
||||
|
||||
#include "f4ll/consolehandler.h"
|
||||
#include "f4ll/strutil.h"
|
||||
|
||||
namespace f4ll {
|
||||
|
||||
ConsoleHandler::ConsoleHandler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx)
|
||||
: UsartCore(usart, dma, streamRx, streamTx)
|
||||
{
|
||||
}
|
||||
|
||||
void ConsoleHandler::ReceiverIdle(void) {}
|
||||
void ConsoleHandler::TransmissionComplete(void) {}
|
||||
void ConsoleHandler::FramingError(void) {}
|
||||
void ConsoleHandler::Overrun(void) {}
|
||||
void ConsoleHandler::RxDmaTransferComplete(void) {}
|
||||
void ConsoleHandler::RxDmaHalfTransfer(void) {}
|
||||
void ConsoleHandler::RxDmaError(DmaHelper::DmaErrorType reason) {}
|
||||
void ConsoleHandler::TxDmaTransferComplete(void)
|
||||
{
|
||||
LL_USART_EnableIT_TC(m_usart);
|
||||
LL_DMA_DisableStream(m_txDma.GetDma(), m_txDma.GetStream());
|
||||
}
|
||||
void ConsoleHandler::TxDmaHalfTransfer(void) {}
|
||||
void ConsoleHandler::TxDmaError(DmaHelper::DmaErrorType reason) {}
|
||||
|
||||
|
||||
#define ADDINFO(b,s,u) \
|
||||
b += strcpy_ex(b,s); \
|
||||
b += uitodec(b,u);
|
||||
|
||||
void ConsoleHandler::PrintStats(uint8_t id, PacketUsart &usart)
|
||||
{
|
||||
char ids[] = " : ";
|
||||
char *buffer = m_buffer;
|
||||
PacketUsart::Stats const &stats(usart.GetStats());
|
||||
|
||||
ids[0] = id + '0';
|
||||
buffer += strcpy_ex(buffer, ids);
|
||||
ADDINFO(buffer, " s: ", stats.sent);
|
||||
ADDINFO(buffer, " r: ", stats.rcvd);
|
||||
ADDINFO(buffer, " sk: ", stats.skiped);
|
||||
ADDINFO(buffer, " or: ", stats.overrun);
|
||||
ADDINFO(buffer, " he: ", stats.hdrError);
|
||||
ADDINFO(buffer, " pe: ", stats.payloadErrror);
|
||||
buffer += strcpy_ex(buffer,",0x");
|
||||
buffer += uitohex(buffer, stats.pep1, 8);
|
||||
buffer += strcpy_ex(buffer,",0x");
|
||||
buffer += uitohex(buffer, stats.pep2, 8);
|
||||
ADDINFO(buffer, " rde: ", stats.rxDmaError);
|
||||
ADDINFO(buffer, " tde: ", stats.txDmaError);
|
||||
ADDINFO(buffer, " pmh: ", stats.premature_hdr);
|
||||
ADDINFO(buffer, " pmp: ", stats.premature_payload);
|
||||
buffer += strcpy_ex(buffer, "\r\n");
|
||||
|
||||
SetupTransmit(m_buffer, buffer - m_buffer + 1);
|
||||
}
|
||||
|
||||
|
||||
} /* namespace f4ll */
|
||||
|
158
components/f4ll/src/crc_handler.cpp
Normal file
158
components/f4ll/src/crc_handler.cpp
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* ll_crchandler.cpp
|
||||
*
|
||||
* Created on: Oct 26, 2019
|
||||
* Author: compi
|
||||
*/
|
||||
#include <f4ll/crc_handler.h>
|
||||
|
||||
namespace f4ll {
|
||||
|
||||
CrcHandler::CrcHandler(DMA_TypeDef *dma, uint32_t stream) : m_dma(dma, stream) {
|
||||
LL_DMA_EnableIT_TC(dma, stream);
|
||||
LL_DMA_EnableIT_TE(dma, stream);
|
||||
LL_DMA_SetM2MDstAddress(dma, stream, (uint32_t)&CRC->DR);
|
||||
}
|
||||
|
||||
void CrcHandler::AttachSlot(SlotBase &slot) {
|
||||
for (unsigned int i = 0; i < slot.m_taskCount; ++i) {
|
||||
auto &task(slot[i]);
|
||||
task.m_address = nullptr;
|
||||
task.m_wordCount = 0;
|
||||
task.m_callback = nullptr;
|
||||
task.m_callbackParam = 0;
|
||||
}
|
||||
uint32_t prim = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
slot.m_next = m_firstSlot;
|
||||
m_firstSlot = &slot;
|
||||
__set_PRIMASK(prim);
|
||||
}
|
||||
|
||||
bool CrcHandler::Enqueue(SlotBase &slot, uint8_t task, void const *address,
|
||||
uint16_t len, ICallback *cb, uintptr_t cbParam) {
|
||||
uint32_t prim = __get_PRIMASK();
|
||||
bool immediate;
|
||||
|
||||
// TODO: do we need sanity check here? (is slot attached, is task in range,
|
||||
// etc...?)
|
||||
|
||||
while (IsActive(slot, task))
|
||||
;
|
||||
__disable_irq();
|
||||
immediate = m_activeSlot == nullptr;
|
||||
slot[task].m_address = (!immediate) ? address : nullptr;
|
||||
slot[task].m_wordCount = (len + 3) / 4;
|
||||
slot[task].m_callback = cb;
|
||||
slot[task].m_callbackParam = cbParam;
|
||||
if (immediate) {
|
||||
m_activeSlot = &slot;
|
||||
m_activeTask = task;
|
||||
}
|
||||
__set_PRIMASK(prim);
|
||||
|
||||
if (immediate) {
|
||||
CRC->CR = 1;
|
||||
LL_DMA_SetM2MSrcAddress(m_dma.GetDma(), m_dma.GetStream(),
|
||||
(uint32_t)address);
|
||||
LL_DMA_SetDataLength(m_dma.GetDma(), m_dma.GetStream(), (len + 3) / 4);
|
||||
LL_DMA_EnableStream(m_dma.GetDma(), m_dma.GetStream());
|
||||
}
|
||||
return immediate;
|
||||
}
|
||||
|
||||
bool CrcHandler::IsActive(SlotBase &slot, uint8_t task) const {
|
||||
return task < slot.m_taskCount && slot[task].m_wordCount != 0;
|
||||
}
|
||||
|
||||
bool CrcHandler::IsQueued(SlotBase &slot, uint8_t task) const {
|
||||
return task < slot.m_taskCount && slot[task].m_address != nullptr;
|
||||
}
|
||||
|
||||
bool CrcHandler::IsRunning(SlotBase &slot, uint8_t task) const {
|
||||
return task < slot.m_taskCount && slot[task].m_wordCount &&
|
||||
!slot[task].m_address;
|
||||
}
|
||||
|
||||
void CrcHandler::DmaTransferCompleted(void) {
|
||||
if (*m_dma.GetIsReg() & m_dma.GetTcMask()) { // DMA transfer complete
|
||||
*m_dma.GetIfcReg() = m_dma.GetTcMask();
|
||||
LL_DMA_DisableStream(m_dma.GetDma(), m_dma.GetStream());
|
||||
if (m_activeSlot) {
|
||||
if ((*m_activeSlot)[m_activeTask].m_callback)
|
||||
(*m_activeSlot)[m_activeTask].m_callback->CrcSucceeded(
|
||||
(*m_activeSlot)[m_activeTask].m_callbackParam, CRC->DR,
|
||||
m_activeTask);
|
||||
else if ((*m_activeSlot)[m_activeTask].m_callbackParam)
|
||||
*reinterpret_cast<uint32_t *>(
|
||||
(*m_activeSlot)[m_activeTask].m_callbackParam) = CRC->DR;
|
||||
}
|
||||
} else if (*m_dma.GetIsReg() & m_dma.GetTeMask()) { // DMA transfer error
|
||||
*m_dma.GetIfcReg() = m_dma.GetTeMask();
|
||||
LL_DMA_DisableStream(m_dma.GetDma(), m_dma.GetStream());
|
||||
if (m_activeSlot) {
|
||||
if ((*m_activeSlot)[m_activeTask].m_callback)
|
||||
(*m_activeSlot)[m_activeTask].m_callback->CrcFailed(
|
||||
(*m_activeSlot)[m_activeTask].m_callbackParam, CRC->DR,
|
||||
m_activeTask);
|
||||
else if ((*m_activeSlot)[m_activeTask].m_callbackParam)
|
||||
*reinterpret_cast<uint32_t *>(
|
||||
(*m_activeSlot)[m_activeTask].m_callbackParam) = -1;
|
||||
}
|
||||
}
|
||||
(*m_activeSlot)[m_activeTask].m_callback = nullptr;
|
||||
(*m_activeSlot)[m_activeTask].m_callbackParam = 0;
|
||||
(*m_activeSlot)[m_activeTask].m_wordCount = 0;
|
||||
StartNextTask();
|
||||
}
|
||||
|
||||
void CrcHandler::StartNextTask(void) {
|
||||
bool moreTasks;
|
||||
uint8_t index = 0;
|
||||
|
||||
do {
|
||||
SlotBase volatile *slot = m_firstSlot;
|
||||
moreTasks = false;
|
||||
while (slot) {
|
||||
if (index < slot->m_taskCount) {
|
||||
if ((*slot)[index].m_address) {
|
||||
m_activeSlot = slot;
|
||||
m_activeTask = index;
|
||||
CRC->CR = 1;
|
||||
LL_DMA_SetM2MSrcAddress(
|
||||
m_dma.GetDma(), m_dma.GetStream(),
|
||||
reinterpret_cast<uint32_t>((*slot)[index].m_address));
|
||||
LL_DMA_SetDataLength(m_dma.GetDma(), m_dma.GetStream(),
|
||||
(*slot)[index].m_wordCount);
|
||||
LL_DMA_EnableStream(m_dma.GetDma(), m_dma.GetStream());
|
||||
(*slot)[index].m_address = nullptr; // marking as started
|
||||
return;
|
||||
}
|
||||
if (index + 1 < slot->m_taskCount)
|
||||
moreTasks = true;
|
||||
}
|
||||
slot = slot->m_next;
|
||||
}
|
||||
++index;
|
||||
} while (moreTasks);
|
||||
m_activeSlot = nullptr;
|
||||
}
|
||||
|
||||
void CrcHandler::WaitResults(SlotBase &slot, uint8_t task) const {
|
||||
while (IsQueued(slot, task))
|
||||
;
|
||||
while (IsActive(slot, task))
|
||||
;
|
||||
}
|
||||
|
||||
uint32_t CrcHandler::Compute(SlotBase &slot, uint8_t task, void const *address,
|
||||
uint16_t len) {
|
||||
uint32_t result;
|
||||
Enqueue(slot, task, address, len, nullptr,
|
||||
reinterpret_cast<uintptr_t>(&result));
|
||||
while (IsActive(slot, task))
|
||||
;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace f4ll
|
|
@ -1,157 +0,0 @@
|
|||
/*
|
||||
* ll_crchandler.cpp
|
||||
*
|
||||
* Created on: Oct 26, 2019
|
||||
* Author: compi
|
||||
*/
|
||||
#include "f4ll/crchandler.h"
|
||||
|
||||
namespace f4ll {
|
||||
|
||||
CrcHandler::CrcHandler(DMA_TypeDef *dma, uint32_t stream)
|
||||
: m_dma(dma, stream)
|
||||
{
|
||||
LL_DMA_EnableIT_TC(dma, stream);
|
||||
LL_DMA_EnableIT_TE(dma, stream);
|
||||
LL_DMA_SetM2MDstAddress(dma, stream, (uint32_t)&CRC->DR);
|
||||
}
|
||||
|
||||
|
||||
void CrcHandler::AttachSlot(SlotBase &slot)
|
||||
{
|
||||
for(unsigned int i = 0; i < slot.m_taskCount; ++i ) {
|
||||
auto &task(slot[i]);
|
||||
task.m_address = nullptr;
|
||||
task.m_wordCount = 0;
|
||||
task.m_callback = nullptr;
|
||||
task.m_callbackParam = 0;
|
||||
}
|
||||
uint32_t prim = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
slot.m_next = m_firstSlot;
|
||||
m_firstSlot = &slot;
|
||||
__set_PRIMASK(prim);
|
||||
}
|
||||
|
||||
|
||||
bool CrcHandler::Enqueue(SlotBase &slot, uint8_t task, void const *address, uint16_t len, ICallback *cb, uintptr_t cbParam)
|
||||
{
|
||||
uint32_t prim = __get_PRIMASK();
|
||||
bool immediate;
|
||||
|
||||
// TODO: do we need sanity check here? (is slot attached, is task in range, etc...?)
|
||||
|
||||
while(IsActive(slot,task));
|
||||
__disable_irq();
|
||||
immediate = m_activeSlot == nullptr;
|
||||
slot[task].m_address = (!immediate) ? address : nullptr;
|
||||
slot[task].m_wordCount = (len+3)/4;
|
||||
slot[task].m_callback = cb;
|
||||
slot[task].m_callbackParam = cbParam;
|
||||
if(immediate) {
|
||||
m_activeSlot = &slot;
|
||||
m_activeTask = task;
|
||||
}
|
||||
__set_PRIMASK(prim);
|
||||
|
||||
if(immediate) {
|
||||
CRC->CR = 1;
|
||||
LL_DMA_SetM2MSrcAddress(m_dma.GetDma(), m_dma.GetStream(), (uint32_t)address);
|
||||
LL_DMA_SetDataLength(m_dma.GetDma(), m_dma.GetStream(), (len+3)/4);
|
||||
LL_DMA_EnableStream(m_dma.GetDma(), m_dma.GetStream());
|
||||
}
|
||||
return immediate;
|
||||
}
|
||||
|
||||
bool CrcHandler::IsActive(SlotBase &slot, uint8_t task) const
|
||||
{
|
||||
return task < slot.m_taskCount && slot[task].m_wordCount != 0;
|
||||
}
|
||||
|
||||
bool CrcHandler::IsQueued(SlotBase &slot, uint8_t task) const
|
||||
{
|
||||
return task < slot.m_taskCount && slot[task].m_address != nullptr;
|
||||
}
|
||||
|
||||
bool CrcHandler::IsRunning(SlotBase &slot, uint8_t task) const
|
||||
{
|
||||
return task < slot.m_taskCount && slot[task].m_wordCount && ! slot[task].m_address;
|
||||
}
|
||||
|
||||
void CrcHandler::DmaTransferCompleted(void)
|
||||
{
|
||||
if(* m_dma.GetIsReg() & m_dma.GetTcMask()) { // DMA transfer complete
|
||||
* m_dma.GetIfcReg() = m_dma.GetTcMask();
|
||||
LL_DMA_DisableStream(m_dma.GetDma(), m_dma.GetStream());
|
||||
if(m_activeSlot) {
|
||||
if((*m_activeSlot)[m_activeTask].m_callback)
|
||||
(*m_activeSlot)[m_activeTask].m_callback->CrcSucceeded((*m_activeSlot)[m_activeTask].m_callbackParam, CRC->DR, m_activeTask);
|
||||
else if((*m_activeSlot)[m_activeTask].m_callbackParam)
|
||||
*reinterpret_cast<uint32_t*>((*m_activeSlot)[m_activeTask].m_callbackParam) = CRC->DR;
|
||||
}
|
||||
}
|
||||
else if(*m_dma.GetIsReg() & m_dma.GetTeMask()) { // DMA transfer error
|
||||
*m_dma.GetIfcReg() = m_dma.GetTeMask();
|
||||
LL_DMA_DisableStream(m_dma.GetDma(), m_dma.GetStream());
|
||||
if(m_activeSlot) {
|
||||
if((*m_activeSlot)[m_activeTask].m_callback)
|
||||
(*m_activeSlot)[m_activeTask].m_callback->CrcFailed((*m_activeSlot)[m_activeTask].m_callbackParam, CRC->DR, m_activeTask);
|
||||
else if((*m_activeSlot)[m_activeTask].m_callbackParam)
|
||||
*reinterpret_cast<uint32_t*>((*m_activeSlot)[m_activeTask].m_callbackParam) = -1;
|
||||
}
|
||||
}
|
||||
(*m_activeSlot)[m_activeTask].m_callback = nullptr;
|
||||
(*m_activeSlot)[m_activeTask].m_callbackParam = 0;
|
||||
(*m_activeSlot)[m_activeTask].m_wordCount = 0;
|
||||
StartNextTask();
|
||||
}
|
||||
|
||||
|
||||
void CrcHandler::StartNextTask(void)
|
||||
{
|
||||
bool moreTasks;
|
||||
uint8_t index = 0;
|
||||
|
||||
do {
|
||||
SlotBase volatile *slot = m_firstSlot;
|
||||
moreTasks = false;
|
||||
while(slot) {
|
||||
if(index < slot->m_taskCount) {
|
||||
if((*slot)[index].m_address) {
|
||||
m_activeSlot = slot;
|
||||
m_activeTask = index;
|
||||
CRC->CR = 1;
|
||||
LL_DMA_SetM2MSrcAddress(m_dma.GetDma(), m_dma.GetStream(), reinterpret_cast<uint32_t>((*slot)[index].m_address));
|
||||
LL_DMA_SetDataLength(m_dma.GetDma(), m_dma.GetStream(), (*slot)[index].m_wordCount);
|
||||
LL_DMA_EnableStream(m_dma.GetDma(), m_dma.GetStream());
|
||||
(*slot)[index].m_address = nullptr; // marking as started
|
||||
return;
|
||||
}
|
||||
if(index + 1 < slot->m_taskCount)
|
||||
moreTasks = true;
|
||||
}
|
||||
slot = slot->m_next;
|
||||
}
|
||||
++index;
|
||||
} while(moreTasks);
|
||||
m_activeSlot = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void CrcHandler::WaitResults(SlotBase &slot, uint8_t task) const
|
||||
{
|
||||
while(IsQueued(slot, task));
|
||||
while(IsActive(slot, task));
|
||||
}
|
||||
|
||||
|
||||
uint32_t CrcHandler::Compute(
|
||||
SlotBase &slot, uint8_t task, void const *address, uint16_t len)
|
||||
{
|
||||
uint32_t result;
|
||||
Enqueue(slot, task, address, len, nullptr, reinterpret_cast<uintptr_t>(&result));
|
||||
while(IsActive(slot, task));
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace f4ll
|
35
components/f4ll/src/dma_helper.cpp
Normal file
35
components/f4ll/src/dma_helper.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
q * ll_dmahelper.cpp
|
||||
*
|
||||
* Created on: Oct 25, 2019
|
||||
* Author: abody
|
||||
*/
|
||||
|
||||
#include <f4ll/dma_helper.h>
|
||||
|
||||
namespace f4ll {
|
||||
|
||||
const uint32_t dma_helper::m_FEMasks[8] = {DMA_LISR_FEIF0, DMA_LISR_FEIF1, DMA_LISR_FEIF2, DMA_LISR_FEIF3,
|
||||
DMA_HISR_FEIF4, DMA_HISR_FEIF5, DMA_HISR_FEIF6, DMA_HISR_FEIF7};
|
||||
const uint32_t dma_helper::m_DMEMasks[8] = {DMA_LISR_DMEIF0, DMA_LISR_DMEIF1, DMA_LISR_DMEIF2, DMA_LISR_DMEIF3,
|
||||
DMA_HISR_DMEIF4, DMA_HISR_DMEIF5, DMA_HISR_DMEIF6, DMA_HISR_DMEIF7};
|
||||
const uint32_t dma_helper::m_TEMasks[8] = {DMA_LISR_TEIF0, DMA_LISR_TEIF1, DMA_LISR_TEIF2, DMA_LISR_TEIF3,
|
||||
DMA_HISR_TEIF4, DMA_HISR_TEIF5, DMA_HISR_TEIF6, DMA_HISR_TEIF7};
|
||||
const uint32_t dma_helper::m_HTMasks[8] = {DMA_LISR_HTIF0, DMA_LISR_HTIF1, DMA_LISR_HTIF2, DMA_LISR_HTIF3,
|
||||
DMA_HISR_HTIF4, DMA_HISR_HTIF5, DMA_HISR_HTIF6, DMA_HISR_HTIF7};
|
||||
const uint32_t dma_helper::m_TCMasks[8] = {DMA_LISR_TCIF0, DMA_LISR_TCIF1, DMA_LISR_TCIF2, DMA_LISR_TCIF3,
|
||||
DMA_HISR_TCIF4, DMA_HISR_TCIF5, DMA_HISR_TCIF6, DMA_HISR_TCIF7};
|
||||
|
||||
dma_helper::dma_helper(DMA_TypeDef *dma, uint32_t stream)
|
||||
: m_dma(dma),
|
||||
m_stream(stream),
|
||||
m_isReg(
|
||||
(dma == DMA1) ? ((m_stream < LL_DMA_STREAM_4) ? &DMA1->LISR : &DMA1->HISR)
|
||||
: ((m_stream < LL_DMA_STREAM_4) ? &DMA2->LISR : &DMA2->HISR)),
|
||||
m_ifcReg(
|
||||
(dma == DMA1) ? ((m_stream < LL_DMA_STREAM_4) ? &DMA1->LIFCR : &DMA1->HIFCR)
|
||||
: ((m_stream < LL_DMA_STREAM_4) ? &DMA2->LIFCR : &DMA2->HIFCR))
|
||||
{
|
||||
}
|
||||
|
||||
} /* namespace f4ll */
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
q * ll_dmahelper.cpp
|
||||
*
|
||||
* Created on: Oct 25, 2019
|
||||
* Author: abody
|
||||
*/
|
||||
|
||||
#include "f4ll/dmahelper.h"
|
||||
|
||||
namespace f4ll {
|
||||
|
||||
const uint32_t DmaHelper::m_FEMasks[8] = {DMA_LISR_FEIF0, DMA_LISR_FEIF1, DMA_LISR_FEIF2, DMA_LISR_FEIF3, DMA_HISR_FEIF4, DMA_HISR_FEIF5, DMA_HISR_FEIF6, DMA_HISR_FEIF7};
|
||||
const uint32_t DmaHelper::m_DMEMasks[8] = {DMA_LISR_DMEIF0, DMA_LISR_DMEIF1, DMA_LISR_DMEIF2, DMA_LISR_DMEIF3, DMA_HISR_DMEIF4, DMA_HISR_DMEIF5, DMA_HISR_DMEIF6, DMA_HISR_DMEIF7};
|
||||
const uint32_t DmaHelper::m_TEMasks[8] = {DMA_LISR_TEIF0, DMA_LISR_TEIF1, DMA_LISR_TEIF2, DMA_LISR_TEIF3, DMA_HISR_TEIF4, DMA_HISR_TEIF5, DMA_HISR_TEIF6, DMA_HISR_TEIF7};
|
||||
const uint32_t DmaHelper::m_HTMasks[8] = {DMA_LISR_HTIF0, DMA_LISR_HTIF1, DMA_LISR_HTIF2, DMA_LISR_HTIF3, DMA_HISR_HTIF4, DMA_HISR_HTIF5, DMA_HISR_HTIF6, DMA_HISR_HTIF7};
|
||||
const uint32_t DmaHelper::m_TCMasks[8] = {DMA_LISR_TCIF0, DMA_LISR_TCIF1, DMA_LISR_TCIF2, DMA_LISR_TCIF3, DMA_HISR_TCIF4, DMA_HISR_TCIF5, DMA_HISR_TCIF6, DMA_HISR_TCIF7};
|
||||
|
||||
DmaHelper::DmaHelper(DMA_TypeDef *dma, uint32_t stream)
|
||||
: m_dma(dma)
|
||||
, m_stream(stream)
|
||||
, m_isReg((dma == DMA1) ? ((m_stream < LL_DMA_STREAM_4) ? &DMA1->LISR : &DMA1->HISR) : ((m_stream < LL_DMA_STREAM_4) ? &DMA2->LISR : &DMA2->HISR))
|
||||
, m_ifcReg((dma == DMA1) ? ((m_stream < LL_DMA_STREAM_4) ? &DMA1->LIFCR : &DMA1->HIFCR) : ((m_stream < LL_DMA_STREAM_4) ? &DMA2->LIFCR : &DMA2->HIFCR))
|
||||
{
|
||||
}
|
||||
|
||||
} /* namespace f4ll */
|
|
@ -7,9 +7,9 @@
|
|||
*/
|
||||
#include <inttypes.h>
|
||||
//#include <core_cm4.h>
|
||||
#include "stm32f4xx.h"
|
||||
#include "f4ll/strutil.h"
|
||||
#include "f4ll/fault.h"
|
||||
#include <f4ll/fault.h>
|
||||
#include <f4ll/str_util.h>
|
||||
#include <stm32f4xx.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -43,6 +43,7 @@ fault_context_t g_faultContext;
|
|||
|
||||
void __attribute__((weak)) app_fault_callback(uint32_t reason)
|
||||
{
|
||||
(void)reason;
|
||||
}
|
||||
|
||||
void SwoSendStr(char const *str, uint8_t len, uint8_t port)
|
||||
|
|
38
components/f4ll/src/memcpy_dma.cpp
Normal file
38
components/f4ll/src/memcpy_dma.cpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* llmemcpydma.cpp
|
||||
*
|
||||
* Created on: Nov 4, 2019
|
||||
* Author: abody
|
||||
*/
|
||||
|
||||
#include <f4ll/memcpy_dma.h>
|
||||
|
||||
namespace f4ll {
|
||||
|
||||
MemcpyDma::MemcpyDma(DMA_TypeDef *dma, uint32_t stream)
|
||||
: dma_helper(dma, stream)
|
||||
{
|
||||
LL_DMA_EnableIT_TC(dma, stream);
|
||||
}
|
||||
|
||||
void *MemcpyDma::Copy(void *dst, void const *src, uint16_t length)
|
||||
{
|
||||
LL_DMA_SetM2MSrcAddress(GetDma(), GetStream(), (uint32_t)src);
|
||||
LL_DMA_SetM2MDstAddress(GetDma(), GetStream(), (uint32_t)dst);
|
||||
LL_DMA_SetDataLength(GetDma(), GetStream(), (length + 3) / 4);
|
||||
m_busy = 1;
|
||||
LL_DMA_EnableStream(GetDma(), GetStream());
|
||||
while (m_busy)
|
||||
;
|
||||
return dst;
|
||||
}
|
||||
|
||||
void MemcpyDma::DmaTransferCompleted()
|
||||
{
|
||||
if (*GetIsReg() & GetTcMask()) { // DMA transfer complete
|
||||
*GetIfcReg() = GetTcMask();
|
||||
LL_DMA_DisableStream(GetDma(), GetStream());
|
||||
m_busy = 0;
|
||||
}
|
||||
}
|
||||
} /* namespace f4ll */
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* llmemcpydma.cpp
|
||||
*
|
||||
* Created on: Nov 4, 2019
|
||||
* Author: abody
|
||||
*/
|
||||
|
||||
#include "f4ll/memcpydma.h"
|
||||
|
||||
namespace f4ll {
|
||||
|
||||
MemcpyDma::MemcpyDma(DMA_TypeDef *dma, uint32_t stream)
|
||||
: DmaHelper(dma, stream)
|
||||
{
|
||||
LL_DMA_EnableIT_TC(dma, stream);
|
||||
}
|
||||
|
||||
void* MemcpyDma::Copy(void *dst, void const *src, uint16_t length)
|
||||
{
|
||||
LL_DMA_SetM2MSrcAddress(GetDma(), GetStream(), (uint32_t)src);
|
||||
LL_DMA_SetM2MDstAddress(GetDma(), GetStream(), (uint32_t)dst);
|
||||
LL_DMA_SetDataLength(GetDma(), GetStream(), (length+3)/4 );
|
||||
m_busy = 1;
|
||||
LL_DMA_EnableStream(GetDma(), GetStream());
|
||||
while(m_busy);
|
||||
return dst;
|
||||
}
|
||||
|
||||
void MemcpyDma::DmaTransferCompleted()
|
||||
{
|
||||
if(*GetIsReg() & GetTcMask()) { // DMA transfer complete
|
||||
*GetIfcReg() = GetTcMask();
|
||||
LL_DMA_DisableStream(GetDma(), GetStream());
|
||||
m_busy = 0;
|
||||
}
|
||||
}
|
||||
} /* namespace f4ll */
|
211
components/f4ll/src/packet_usart.cpp
Normal file
211
components/f4ll/src/packet_usart.cpp
Normal file
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* ll_hsusart_impl.h
|
||||
*
|
||||
* Created on: Oct 29, 2019
|
||||
* Author: abody
|
||||
*/
|
||||
#include <f4ll/packet_usart.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace f4ll {
|
||||
|
||||
template <typename T> static inline T RoundUpTo4(T input)
|
||||
{
|
||||
return (input + 3) & (((T)-1) - 3);
|
||||
}
|
||||
|
||||
PacketUsart::PacketUsart(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx)
|
||||
: usart_core(usart, dma, streamRx, streamTx)
|
||||
{
|
||||
CrcHandler::instance().AttachSlot(m_crcSlot);
|
||||
LL_USART_EnableIT_IDLE(usart);
|
||||
LL_USART_EnableIT_ERROR(usart);
|
||||
}
|
||||
|
||||
void PacketUsart::RxProcessed(bool second)
|
||||
{
|
||||
m_rxBuffers[second].busy = false;
|
||||
m_rxBuffers[second].error = false;
|
||||
}
|
||||
|
||||
void PacketUsart::SetCallback(IHsUsartCallback *callback, uintptr_t callbackParam)
|
||||
{
|
||||
m_userCallback = callback;
|
||||
m_userCallbackParam = callbackParam;
|
||||
}
|
||||
|
||||
void PacketUsart::PostPacket(uint8_t const *payload, uint8_t length, bool waitForCrcQueue)
|
||||
{
|
||||
uint16_t payloadLength = RoundUpTo4((uint16_t)length);
|
||||
|
||||
BuildHeader(m_txBuffer.packet, m_txSerialNo++, length);
|
||||
if (payload) {
|
||||
memcpy(m_txBuffer.packet.payload, payload, length);
|
||||
}
|
||||
m_txBuffer.requestedLength = sizeof(m_txBuffer.packet.header) + payloadLength + sizeof(uint32_t);
|
||||
m_txBuffer.busy = true;
|
||||
m_txBuffer.error = false;
|
||||
|
||||
CrcHandler::instance().Enqueue(
|
||||
m_crcSlot, 0, &m_txBuffer.packet, sizeof(PacketHeader) + payloadLength, nullptr,
|
||||
reinterpret_cast<uintptr_t>(m_txBuffer.packet.payload + payloadLength));
|
||||
|
||||
while (waitForCrcQueue && CrcHandler::instance().IsQueued(m_crcSlot, 0))
|
||||
;
|
||||
|
||||
SetupTransmit(&m_txBuffer.packet, m_txBuffer.requestedLength);
|
||||
|
||||
++m_stats.sent;
|
||||
}
|
||||
|
||||
void PacketUsart::SetupReceive()
|
||||
{
|
||||
m_rxBuffers[m_rxBufferSelector].requestedLength = sizeof(m_rxBuffers[m_rxBufferSelector].packet);
|
||||
usart_core::SetupReceive(&m_rxBuffers[m_rxBufferSelector], sizeof(m_rxBuffers[m_rxBufferSelector].packet));
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// UsartCore pure virtual functions //
|
||||
//////////////////////////////////////
|
||||
|
||||
void PacketUsart::ReceiverIdle(void)
|
||||
{
|
||||
uint16_t rcvdLen = m_rxBuffers[m_rxBufferSelector].requestedLength - LL_DMA_GetDataLength(m_rxDma.GetDma(), m_rxDma.GetStream());
|
||||
|
||||
if (rcvdLen >= sizeof(PacketHeader)) {
|
||||
if (CheckHeader(m_rxBuffers[m_rxBufferSelector].packet.header)) {
|
||||
if (rcvdLen >= sizeof(PacketHeader) + RoundUpTo4((uint16_t)m_rxBuffers[m_rxBufferSelector].packet.header.payloadLength) +
|
||||
sizeof(uint32_t)) {
|
||||
LL_DMA_DisableStream(m_rxDma.GetDma(), m_rxDma.GetStream());
|
||||
} else {
|
||||
++m_stats.premature_payload;
|
||||
}
|
||||
} else {
|
||||
m_rxBuffers[m_rxBufferSelector].error = 1;
|
||||
LL_DMA_DisableStream(m_rxDma.GetDma(), m_rxDma.GetStream());
|
||||
}
|
||||
} else {
|
||||
++m_stats.premature_hdr;
|
||||
}
|
||||
}
|
||||
|
||||
void PacketUsart::TransmissionComplete(void)
|
||||
{
|
||||
LL_USART_DisableDirectionTx(m_usart); // enforcing an idle frame
|
||||
LL_USART_EnableDirectionTx(m_usart);
|
||||
m_txBuffer.busy = 0;
|
||||
}
|
||||
|
||||
void PacketUsart::FramingError(void) {}
|
||||
|
||||
void PacketUsart::Overrun(void) {}
|
||||
|
||||
void PacketUsart::RxDmaTransferComplete(void)
|
||||
{
|
||||
if (CheckHeader(m_rxBuffers[m_rxBufferSelector].packet.header)) {
|
||||
CrcHandler::instance().Enqueue(
|
||||
m_crcSlot, 1, &m_rxBuffers[m_rxBufferSelector].packet,
|
||||
sizeof(PacketHeader) + RoundUpTo4((uint16_t)m_rxBuffers[m_rxBufferSelector].packet.header.payloadLength), this,
|
||||
m_rxBufferSelector);
|
||||
} else {
|
||||
++m_stats.hdrError;
|
||||
m_rxBuffers[m_rxBufferSelector].error = true;
|
||||
}
|
||||
SwitchRxBuffers();
|
||||
}
|
||||
|
||||
void PacketUsart::RxDmaHalfTransfer(void) {}
|
||||
|
||||
void PacketUsart::RxDmaError(dma_helper::DmaErrorType reason)
|
||||
{
|
||||
(void)reason;
|
||||
|
||||
m_rxBuffers[m_rxBufferSelector].error = 1;
|
||||
++m_stats.rxDmaError;
|
||||
SwitchRxBuffers();
|
||||
}
|
||||
|
||||
void PacketUsart::TxDmaTransferComplete(void)
|
||||
{
|
||||
LL_USART_EnableIT_TC(m_usart);
|
||||
LL_DMA_DisableStream(m_txDma.GetDma(), m_txDma.GetStream());
|
||||
}
|
||||
|
||||
void PacketUsart::TxDmaHalfTransfer(void) {}
|
||||
|
||||
void PacketUsart::TxDmaError(dma_helper::DmaErrorType reason)
|
||||
{
|
||||
(void)reason;
|
||||
|
||||
m_txBuffer.error = 1;
|
||||
++m_stats.txDmaError;
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
// Private functions //
|
||||
///////////////////////
|
||||
|
||||
void PacketUsart::BuildHeader(Packet &packet, uint8_t serialNo, uint8_t length)
|
||||
{
|
||||
uint8_t hash = STARTMARKER;
|
||||
|
||||
packet.header.startByte = STARTMARKER;
|
||||
packet.header.serial = serialNo;
|
||||
hash ^= serialNo;
|
||||
packet.header.payloadLength = length;
|
||||
hash ^= length;
|
||||
packet.header.hash = hash;
|
||||
}
|
||||
|
||||
bool PacketUsart::CheckHeader(PacketHeader &header)
|
||||
{
|
||||
return header.startByte == STARTMARKER && (header.startByte ^ header.serial ^ header.payloadLength) == header.hash;
|
||||
}
|
||||
|
||||
void PacketUsart::SwitchRxBuffers(void)
|
||||
{
|
||||
++m_stats.rcvd;
|
||||
m_rxBufferSelector = !m_rxBufferSelector;
|
||||
|
||||
if (m_rxBuffers[m_rxBufferSelector].busy) {
|
||||
++m_stats.overrun;
|
||||
}
|
||||
SetupReceive();
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
// CrcHandler::ICallback //
|
||||
///////////////////////////
|
||||
|
||||
void PacketUsart::CrcSucceeded(uintptr_t callbackParam, uint32_t crc, uint8_t task)
|
||||
{
|
||||
(void)task;
|
||||
|
||||
Buffer &buf(m_rxBuffers[static_cast<int>(callbackParam)]);
|
||||
|
||||
buf.busy = 1;
|
||||
if (*(uint32_t *)(buf.packet.payload + RoundUpTo4((uint16_t)buf.packet.header.payloadLength)) != crc) {
|
||||
buf.error = 1;
|
||||
buf.errorInfo = crc;
|
||||
++m_stats.payloadErrror;
|
||||
}
|
||||
if (m_userCallback) {
|
||||
buf.busy = !m_userCallback->PacketReceived(this, m_userCallbackParam, buf.packet);
|
||||
}
|
||||
}
|
||||
|
||||
void PacketUsart::CrcFailed(uintptr_t callbackParam, uint32_t crc, uint8_t task)
|
||||
{
|
||||
(void)crc;
|
||||
(void)task;
|
||||
|
||||
Buffer &buf(m_rxBuffers[static_cast<int>(callbackParam)]);
|
||||
buf.busy = buf.error = true;
|
||||
buf.errorInfo = 0;
|
||||
++m_stats.payloadErrror;
|
||||
if (m_userCallback) {
|
||||
buf.busy = !m_userCallback->PacketReceived(this, m_userCallbackParam, buf.packet);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace f4ll
|
|
@ -1,217 +0,0 @@
|
|||
/*
|
||||
* ll_hsusart_impl.h
|
||||
*
|
||||
* Created on: Oct 29, 2019
|
||||
* Author: abody
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "f4ll/packetusart.h"
|
||||
|
||||
namespace f4ll {
|
||||
|
||||
template<typename T> static inline T RoundUpTo4(T input)
|
||||
{
|
||||
return (input + 3) & (((T)-1) - 3);
|
||||
}
|
||||
|
||||
|
||||
PacketUsart::PacketUsart(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx)
|
||||
: UsartCore(usart, dma, streamRx, streamTx)
|
||||
{
|
||||
CrcHandler::Instance().AttachSlot(m_crcSlot);
|
||||
LL_USART_EnableIT_IDLE(usart);
|
||||
LL_USART_EnableIT_ERROR(usart);
|
||||
}
|
||||
|
||||
|
||||
void PacketUsart::RxProcessed(bool second)
|
||||
{
|
||||
m_rxBuffers[second].busy = false;
|
||||
m_rxBuffers[second].error = false;
|
||||
}
|
||||
|
||||
|
||||
void PacketUsart::SetCallback(IHsUsartCallback *callback, uintptr_t callbackParam)
|
||||
{
|
||||
m_userCallback = callback;
|
||||
m_userCallbackParam = callbackParam;
|
||||
}
|
||||
|
||||
|
||||
void PacketUsart::PostPacket(uint8_t const *payload, uint8_t length, bool waitForCrcQueue)
|
||||
{
|
||||
uint16_t payloadLength = RoundUpTo4((uint16_t)length);
|
||||
|
||||
BuildHeader(m_txBuffer.packet, m_txSerialNo++, length);
|
||||
if(payload)
|
||||
memcpy(m_txBuffer.packet.payload, payload, length);
|
||||
m_txBuffer.requestedLength = sizeof(m_txBuffer.packet.header) + payloadLength + sizeof(uint32_t);
|
||||
m_txBuffer.busy = true;
|
||||
m_txBuffer.error = false;
|
||||
|
||||
CrcHandler::Instance().Enqueue(m_crcSlot, 0, &m_txBuffer.packet, sizeof(PacketHeader) + payloadLength,
|
||||
nullptr, reinterpret_cast<uintptr_t>(m_txBuffer.packet.payload + payloadLength));
|
||||
|
||||
while(waitForCrcQueue && CrcHandler::Instance().IsQueued(m_crcSlot, 0));
|
||||
|
||||
SetupTransmit(&m_txBuffer.packet, m_txBuffer.requestedLength);
|
||||
|
||||
++m_stats.sent;
|
||||
}
|
||||
|
||||
|
||||
void PacketUsart::SetupReceive()
|
||||
{
|
||||
m_rxBuffers[m_rxBufferSelector].requestedLength = sizeof(m_rxBuffers[m_rxBufferSelector].packet);
|
||||
UsartCore::SetupReceive(&m_rxBuffers[m_rxBufferSelector], sizeof(m_rxBuffers[m_rxBufferSelector].packet));
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
// UsartCore pure virtual functions //
|
||||
//////////////////////////////////////
|
||||
|
||||
void PacketUsart::ReceiverIdle(void)
|
||||
{
|
||||
uint16_t rcvdLen = m_rxBuffers[m_rxBufferSelector].requestedLength - LL_DMA_GetDataLength(m_rxDma.GetDma(), m_rxDma.GetStream());
|
||||
|
||||
if(rcvdLen >= sizeof(PacketHeader)) {
|
||||
if(CheckHeader(m_rxBuffers[m_rxBufferSelector].packet.header)) {
|
||||
if(rcvdLen >= sizeof(PacketHeader) +
|
||||
RoundUpTo4((uint16_t)m_rxBuffers[m_rxBufferSelector].packet.header.payloadLength)
|
||||
+ sizeof(uint32_t))
|
||||
LL_DMA_DisableStream(m_rxDma.GetDma(), m_rxDma.GetStream());
|
||||
else
|
||||
++m_stats.premature_payload;
|
||||
} else {
|
||||
m_rxBuffers[m_rxBufferSelector].error = 1;
|
||||
LL_DMA_DisableStream(m_rxDma.GetDma(), m_rxDma.GetStream());
|
||||
}
|
||||
} else
|
||||
++m_stats.premature_hdr;
|
||||
}
|
||||
|
||||
|
||||
void PacketUsart::TransmissionComplete(void)
|
||||
{
|
||||
LL_USART_DisableDirectionTx(m_usart); // enforcing an idle frame
|
||||
LL_USART_EnableDirectionTx(m_usart);
|
||||
m_txBuffer.busy = 0;
|
||||
}
|
||||
|
||||
|
||||
void PacketUsart::FramingError(void) {}
|
||||
|
||||
|
||||
void PacketUsart::Overrun(void) {}
|
||||
|
||||
|
||||
void PacketUsart::RxDmaTransferComplete(void)
|
||||
{
|
||||
if(CheckHeader(m_rxBuffers[m_rxBufferSelector].packet.header))
|
||||
CrcHandler::Instance().Enqueue(m_crcSlot, 1,
|
||||
&m_rxBuffers[m_rxBufferSelector].packet,
|
||||
sizeof(PacketHeader) + RoundUpTo4((uint16_t)m_rxBuffers[m_rxBufferSelector].packet.header.payloadLength),
|
||||
this, m_rxBufferSelector);
|
||||
else {
|
||||
++m_stats.hdrError;
|
||||
m_rxBuffers[m_rxBufferSelector].error = true;
|
||||
}
|
||||
SwitchRxBuffers();
|
||||
}
|
||||
|
||||
void PacketUsart::RxDmaHalfTransfer(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void PacketUsart::RxDmaError(DmaHelper::DmaErrorType reason)
|
||||
{
|
||||
m_rxBuffers[m_rxBufferSelector].error = 1;
|
||||
++m_stats.rxDmaError;
|
||||
SwitchRxBuffers();
|
||||
}
|
||||
|
||||
void PacketUsart::TxDmaTransferComplete(void)
|
||||
{
|
||||
LL_USART_EnableIT_TC(m_usart);
|
||||
LL_DMA_DisableStream(m_txDma.GetDma(), m_txDma.GetStream());
|
||||
}
|
||||
|
||||
|
||||
void PacketUsart::TxDmaHalfTransfer(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void PacketUsart::TxDmaError(DmaHelper::DmaErrorType reason)
|
||||
{
|
||||
m_txBuffer.error = 1;
|
||||
++m_stats.txDmaError;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////
|
||||
// Private functions //
|
||||
///////////////////////
|
||||
|
||||
void PacketUsart::BuildHeader(Packet &packet, uint8_t serialNo, uint8_t length)
|
||||
{
|
||||
uint8_t hash = STARTMARKER;
|
||||
|
||||
packet.header.startByte = STARTMARKER;
|
||||
packet.header.serial = serialNo;
|
||||
hash ^= serialNo;
|
||||
packet.header.payloadLength = length;
|
||||
hash ^= length;
|
||||
packet.header.hash = hash;
|
||||
}
|
||||
|
||||
|
||||
bool PacketUsart::CheckHeader(PacketHeader &header)
|
||||
{
|
||||
return header.startByte == STARTMARKER && (header.startByte ^ header.serial ^ header.payloadLength) == header.hash;
|
||||
}
|
||||
|
||||
|
||||
void PacketUsart::SwitchRxBuffers(void)
|
||||
{
|
||||
++m_stats.rcvd;
|
||||
m_rxBufferSelector = !m_rxBufferSelector;
|
||||
|
||||
if(m_rxBuffers[m_rxBufferSelector].busy)
|
||||
++m_stats.overrun;
|
||||
SetupReceive();
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
// CrcHandler::ICallback //
|
||||
///////////////////////////
|
||||
|
||||
void PacketUsart::CrcSucceeded(uintptr_t callbackParam, uint32_t crc, uint8_t task)
|
||||
{
|
||||
Buffer &buf(m_rxBuffers[static_cast<int>(callbackParam)]);
|
||||
|
||||
buf.busy = 1;
|
||||
if(*(uint32_t*) (buf.packet.payload + RoundUpTo4((uint16_t)buf.packet.header.payloadLength)) != crc) {
|
||||
buf.error = 1;
|
||||
buf.errorInfo = crc;
|
||||
++m_stats.payloadErrror;
|
||||
}
|
||||
if(m_userCallback)
|
||||
buf.busy = !m_userCallback->PacketReceived(this, m_userCallbackParam, buf.packet);
|
||||
}
|
||||
|
||||
|
||||
void PacketUsart::CrcFailed(uintptr_t callbackParam, uint32_t crc, uint8_t task)
|
||||
{
|
||||
Buffer &buf(m_rxBuffers[static_cast<int>(callbackParam)]);
|
||||
buf.busy = buf.error = true;
|
||||
buf.errorInfo = 0;
|
||||
++m_stats.payloadErrror;
|
||||
if(m_userCallback)
|
||||
buf.busy = !m_userCallback->PacketReceived(this, m_userCallbackParam, buf.packet);
|
||||
}
|
||||
|
||||
|
||||
} // namespace f4ll
|
105
components/f4ll/src/str_util.cpp
Normal file
105
components/f4ll/src/str_util.cpp
Normal file
|
@ -0,0 +1,105 @@
|
|||
#include <f4ll/str_util.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
size_t strcpy_ex(char *dst, char const *src)
|
||||
{
|
||||
size_t ret = 0;
|
||||
do {
|
||||
*dst++ = *src;
|
||||
++ret;
|
||||
} while (*src++);
|
||||
return ret - 1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void strrev(char *first, char *last)
|
||||
{
|
||||
char tmp;
|
||||
while (last > first) {
|
||||
tmp = *first;
|
||||
*first++ = *last;
|
||||
*last-- = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
char tochr(const uint8_t in, const uint8_t upper)
|
||||
{
|
||||
return in + ((in < 10) ? '0' : (upper ? 'A' : 'a') - 10);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
size_t uitodec(char *buffer, uint32_t data)
|
||||
{
|
||||
char *b2 = buffer;
|
||||
if (!data) {
|
||||
*b2++ = '0';
|
||||
*b2 = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (data) {
|
||||
*b2++ = (data % 10) + '0';
|
||||
data /= 10;
|
||||
}
|
||||
size_t ret = b2 - buffer;
|
||||
|
||||
*b2-- = 0;
|
||||
|
||||
strrev(buffer, b2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
size_t uitohex(char *buffer, uint32_t data, uint8_t chars)
|
||||
{
|
||||
char *b2 = buffer;
|
||||
size_t ret = 0;
|
||||
|
||||
if (chars == 0xff || !chars) {
|
||||
if (!data) {
|
||||
*b2++ = '0';
|
||||
*b2 = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (data) {
|
||||
uint8_t curval = data & 0x0f;
|
||||
*b2++ = tochr(curval, 1);
|
||||
data >>= 4;
|
||||
}
|
||||
ret = b2 - buffer;
|
||||
|
||||
} else {
|
||||
ret = chars;
|
||||
for (uint8_t pos = 0; pos < (uint8_t)ret; ++pos) {
|
||||
*b2++ = tochr(data & 0x0f, 1);
|
||||
data >>= 4;
|
||||
}
|
||||
}
|
||||
*b2-- = 0;
|
||||
strrev(buffer, b2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
size_t itodec(char *buffer, int data)
|
||||
{
|
||||
if (data < 0) {
|
||||
*buffer++ = '-';
|
||||
return uitodec(buffer, -data) + 1;
|
||||
}
|
||||
|
||||
return uitodec(buffer, data);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
size_t itohex(char *buffer, int data)
|
||||
{
|
||||
if (data < 0) {
|
||||
*buffer++ = '-';
|
||||
return uitohex(buffer, -data, 0) + 1;
|
||||
}
|
||||
return uitohex(buffer, data, 0);
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
#include <stdint.h>
|
||||
#include "f4ll/strutil.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
size_t strcpy_ex(char *dst, char const *src)
|
||||
{
|
||||
size_t ret = 0;
|
||||
do {
|
||||
*dst++ = *src;
|
||||
++ret;
|
||||
} while(*src++);
|
||||
return ret - 1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void strrev(char *first, char *last)
|
||||
{
|
||||
char tmp;
|
||||
while(last > first) {
|
||||
tmp = *first;
|
||||
*first++ = *last;
|
||||
*last-- = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
char tochr(const uint8_t in, const uint8_t upper)
|
||||
{
|
||||
return in + ((in < 10) ? '0' : (upper ? 'A' : 'a') - 10);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
size_t uitodec(char* buffer, uint32_t data)
|
||||
{
|
||||
char *b2 = buffer;
|
||||
if(!data) {
|
||||
*b2++ = '0';
|
||||
*b2 = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
while(data) {
|
||||
*b2++ = (data % 10) + '0';
|
||||
data /= 10;
|
||||
}
|
||||
size_t ret = b2 - buffer;
|
||||
|
||||
*b2-- = 0;
|
||||
|
||||
strrev(buffer, b2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
size_t uitohex(char* buffer, uint32_t data, uint8_t chars)
|
||||
{
|
||||
char *b2 = buffer;
|
||||
size_t ret = 0;
|
||||
|
||||
if(chars == 0xff || !chars)
|
||||
{
|
||||
if(!data) {
|
||||
*b2++ = '0';
|
||||
*b2 = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
while(data) {
|
||||
uint8_t curval = data & 0x0f;
|
||||
*b2++ = tochr(curval, 1);
|
||||
data >>= 4;
|
||||
}
|
||||
ret = b2 - buffer;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = chars;
|
||||
for(uint8_t pos = 0; pos < (uint8_t)ret; ++pos) {
|
||||
*b2++ = tochr(data & 0x0f, 1);
|
||||
data >>= 4;
|
||||
}
|
||||
|
||||
}
|
||||
*b2-- = 0;
|
||||
strrev(buffer, b2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
size_t itodec(char* buffer, int data)
|
||||
{
|
||||
if(data < 0) {
|
||||
*buffer++ = '-';
|
||||
return uitodec(buffer, -data) + 1;
|
||||
}
|
||||
|
||||
return uitodec(buffer, data);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
size_t itohex(char* buffer, int data)
|
||||
{
|
||||
if(data < 0) {
|
||||
*buffer++ = '-';
|
||||
return uitohex(buffer, -data, 0) + 1;
|
||||
}
|
||||
return uitohex(buffer, data, 0);
|
||||
}
|
143
components/f4ll/src/usart_core.cpp
Normal file
143
components/f4ll/src/usart_core.cpp
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* ll_dmadrivenusartcore.cpp
|
||||
*
|
||||
* Created on: Nov 4, 2019
|
||||
* Author: abody
|
||||
*/
|
||||
|
||||
#include <f4ll/usart_core.h>
|
||||
|
||||
namespace f4ll {
|
||||
|
||||
usart_core::usart_core(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx)
|
||||
: m_usart(usart),
|
||||
m_rxDma(dma, streamRx),
|
||||
m_txDma(dma, streamTx)
|
||||
{
|
||||
uint32_t status = usart->SR;
|
||||
volatile uint32_t tmpreg = usart->DR; // clearing some of the error/status bits in the USART
|
||||
(void)tmpreg;
|
||||
(void)status;
|
||||
|
||||
*m_txDma.GetIfcReg() = m_txDma.GetTcMask() | m_rxDma.GetHtMask() | m_txDma.GetTeMask() | m_rxDma.GetFeMask() | m_rxDma.GetDmeMask();
|
||||
*m_rxDma.GetIfcReg() = m_rxDma.GetTcMask() | m_rxDma.GetHtMask() | m_rxDma.GetTeMask() | m_rxDma.GetFeMask() | m_rxDma.GetDmeMask();
|
||||
|
||||
LL_DMA_EnableIT_TC(dma, streamRx);
|
||||
LL_DMA_EnableIT_TE(dma, streamRx);
|
||||
LL_DMA_EnableIT_TC(dma, streamTx);
|
||||
LL_DMA_EnableIT_TE(dma, streamTx);
|
||||
}
|
||||
|
||||
void usart_core::UsartIsr()
|
||||
{
|
||||
uint32_t status = m_usart->SR;
|
||||
volatile uint32_t tmpreg = m_usart->DR; // clearing some of the error/status bits in the HW
|
||||
(void)tmpreg;
|
||||
|
||||
if (LL_USART_IsEnabledIT_TC(m_usart) && LL_USART_IsActiveFlag_TC(m_usart)) { // transmission complete
|
||||
LL_USART_DisableIT_TC(m_usart);
|
||||
TransmissionComplete();
|
||||
}
|
||||
if (LL_USART_IsEnabledIT_IDLE(m_usart) && (status & USART_SR_IDLE)) {
|
||||
ReceiverIdle();
|
||||
}
|
||||
if (LL_USART_IsEnabledIT_ERROR(m_usart)) {
|
||||
if (status & USART_SR_FE) {
|
||||
FramingError();
|
||||
}
|
||||
if (status & USART_SR_ORE) {
|
||||
Overrun();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usart_core::RxDmaIsr()
|
||||
{
|
||||
if (*m_rxDma.GetIsReg() & m_rxDma.GetTcMask()) {
|
||||
*m_rxDma.GetIfcReg() = m_rxDma.GetTcMask();
|
||||
if (m_rxDma.IsEnabledIt_TC()) {
|
||||
RxDmaTransferComplete();
|
||||
}
|
||||
}
|
||||
if (*m_rxDma.GetIsReg() & m_rxDma.GetHtMask()) {
|
||||
*m_rxDma.GetIfcReg() = m_rxDma.GetHtMask();
|
||||
if (m_rxDma.IsEnabledIt_HT()) {
|
||||
RxDmaHalfTransfer();
|
||||
}
|
||||
}
|
||||
if (*m_rxDma.GetIsReg() & m_rxDma.GetTeMask()) {
|
||||
*m_rxDma.GetIfcReg() = m_rxDma.GetTeMask();
|
||||
if (m_rxDma.IsEnabledIt_TE()) {
|
||||
RxDmaError(dma_helper::DmaErrorType::Transfer);
|
||||
}
|
||||
}
|
||||
if (*m_rxDma.GetIsReg() & m_rxDma.GetFeMask()) {
|
||||
*m_rxDma.GetIfcReg() = m_rxDma.GetFeMask();
|
||||
if (m_rxDma.IsEnabledIt_FE()) {
|
||||
RxDmaError(dma_helper::DmaErrorType::Fifo);
|
||||
}
|
||||
}
|
||||
if (*m_rxDma.GetIsReg() & m_rxDma.GetDmeMask()) {
|
||||
*m_rxDma.GetIfcReg() = m_rxDma.GetDmeMask();
|
||||
if (m_rxDma.IsEnabledIt_DME()) {
|
||||
RxDmaError(dma_helper::DmaErrorType::DirectMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usart_core::TxDmaIsr()
|
||||
{
|
||||
if (*m_txDma.GetIsReg() & m_txDma.GetTcMask()) { // DMA transfer complete
|
||||
*m_txDma.GetIfcReg() = m_txDma.GetTcMask();
|
||||
if (m_txDma.IsEnabledIt_TC()) {
|
||||
TxDmaTransferComplete();
|
||||
}
|
||||
}
|
||||
if (*m_txDma.GetIsReg() & m_txDma.GetHtMask()) {
|
||||
*m_txDma.GetIfcReg() = m_txDma.GetHtMask();
|
||||
if (m_txDma.IsEnabledIt_HT()) {
|
||||
TxDmaHalfTransfer();
|
||||
}
|
||||
}
|
||||
if (*m_txDma.GetIsReg() & m_txDma.GetTeMask()) {
|
||||
*m_txDma.GetIfcReg() = m_txDma.GetTeMask();
|
||||
if (m_txDma.IsEnabledIt_TE()) {
|
||||
TxDmaError(dma_helper::DmaErrorType::Transfer);
|
||||
}
|
||||
}
|
||||
if (*m_txDma.GetIsReg() & m_txDma.GetFeMask()) {
|
||||
*m_txDma.GetIfcReg() = m_txDma.GetFeMask();
|
||||
if (m_txDma.IsEnabledIt_FE()) {
|
||||
TxDmaError(dma_helper::DmaErrorType::Fifo);
|
||||
}
|
||||
}
|
||||
if (*m_txDma.GetIsReg() & m_txDma.GetDmeMask()) {
|
||||
*m_txDma.GetIfcReg() = m_txDma.GetDmeMask();
|
||||
if (m_txDma.IsEnabledIt_DME()) {
|
||||
TxDmaError(dma_helper::DmaErrorType::DirectMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usart_core::SetupTransmit(void const *buffer, uint16_t length)
|
||||
{
|
||||
LL_DMA_ConfigAddresses(
|
||||
m_txDma.GetDma(), m_txDma.GetStream(), reinterpret_cast<uint32_t>(buffer), LL_USART_DMA_GetRegAddr(m_usart),
|
||||
LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
|
||||
LL_DMA_SetDataLength(m_txDma.GetDma(), m_txDma.GetStream(), length);
|
||||
LL_USART_EnableDMAReq_TX(m_usart);
|
||||
LL_DMA_EnableStream(m_txDma.GetDma(), m_txDma.GetStream());
|
||||
}
|
||||
|
||||
void usart_core::SetupReceive(void *buffer, uint16_t length)
|
||||
{
|
||||
LL_DMA_ConfigAddresses(
|
||||
m_rxDma.GetDma(), m_rxDma.GetStream(), LL_USART_DMA_GetRegAddr(m_usart), reinterpret_cast<uint32_t>(buffer),
|
||||
LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
|
||||
LL_DMA_SetDataLength(m_rxDma.GetDma(), m_rxDma.GetStream(), length);
|
||||
LL_USART_EnableDMAReq_RX(m_usart);
|
||||
LL_USART_ClearFlag_ORE(m_usart);
|
||||
LL_DMA_EnableStream(m_rxDma.GetDma(), m_rxDma.GetStream());
|
||||
}
|
||||
|
||||
} /* namespace f4ll */
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* ll_dmadrivenusartcore.cpp
|
||||
*
|
||||
* Created on: Nov 4, 2019
|
||||
* Author: abody
|
||||
*/
|
||||
|
||||
#include "f4ll/usartcore.h"
|
||||
|
||||
namespace f4ll {
|
||||
|
||||
UsartCore::UsartCore(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t streamRx, uint32_t streamTx)
|
||||
: m_usart(usart)
|
||||
, m_rxDma(dma, streamRx)
|
||||
, m_txDma(dma, streamTx)
|
||||
{
|
||||
uint32_t status = usart->SR;
|
||||
volatile uint32_t tmpreg = usart->DR; // clearing some of the error/status bits in the USART
|
||||
(void) tmpreg;
|
||||
(void) status;
|
||||
|
||||
*m_txDma.GetIfcReg() =
|
||||
m_txDma.GetTcMask() | m_rxDma.GetHtMask() | m_txDma.GetTeMask() | m_rxDma.GetFeMask() | m_rxDma.GetDmeMask();
|
||||
*m_rxDma.GetIfcReg() =
|
||||
m_rxDma.GetTcMask() | m_rxDma.GetHtMask() | m_rxDma.GetTeMask() | m_rxDma.GetFeMask() | m_rxDma.GetDmeMask();
|
||||
|
||||
LL_DMA_EnableIT_TC(dma, streamRx);
|
||||
LL_DMA_EnableIT_TE(dma, streamRx);
|
||||
LL_DMA_EnableIT_TC(dma, streamTx);
|
||||
LL_DMA_EnableIT_TE(dma, streamTx);
|
||||
}
|
||||
|
||||
|
||||
void UsartCore::UsartIsr()
|
||||
{
|
||||
uint32_t status = m_usart->SR;
|
||||
volatile uint32_t tmpreg = m_usart->DR; // clearing some of the error/status bits in the HW
|
||||
(void) tmpreg;
|
||||
|
||||
if(LL_USART_IsEnabledIT_TC(m_usart) && LL_USART_IsActiveFlag_TC(m_usart)) { // transmission complete
|
||||
LL_USART_DisableIT_TC(m_usart);
|
||||
TransmissionComplete();
|
||||
}
|
||||
if(LL_USART_IsEnabledIT_IDLE(m_usart) && (status & USART_SR_IDLE)) {
|
||||
ReceiverIdle();
|
||||
}
|
||||
if(LL_USART_IsEnabledIT_ERROR(m_usart)) {
|
||||
if(status & USART_SR_FE) {
|
||||
FramingError();
|
||||
}
|
||||
if(status & USART_SR_ORE) {
|
||||
Overrun();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UsartCore::RxDmaIsr()
|
||||
{
|
||||
if(*m_rxDma.GetIsReg() & m_rxDma.GetTcMask()) {
|
||||
*m_rxDma.GetIfcReg() = m_rxDma.GetTcMask();
|
||||
if(m_rxDma.IsEnabledIt_TC())
|
||||
RxDmaTransferComplete();
|
||||
}
|
||||
if(*m_rxDma.GetIsReg() & m_rxDma.GetHtMask()) {
|
||||
*m_rxDma.GetIfcReg() = m_rxDma.GetHtMask();
|
||||
if(m_rxDma.IsEnabledIt_HT())
|
||||
RxDmaHalfTransfer();
|
||||
}
|
||||
if(*m_rxDma.GetIsReg() & m_rxDma.GetTeMask()) {
|
||||
*m_rxDma.GetIfcReg() = m_rxDma.GetTeMask();
|
||||
if(m_rxDma.IsEnabledIt_TE())
|
||||
RxDmaError(DmaHelper::DmaErrorType::Transfer);
|
||||
}
|
||||
if(*m_rxDma.GetIsReg() & m_rxDma.GetFeMask()) {
|
||||
*m_rxDma.GetIfcReg() = m_rxDma.GetFeMask();
|
||||
if(m_rxDma.IsEnabledIt_FE())
|
||||
RxDmaError(DmaHelper::DmaErrorType::Fifo);
|
||||
}
|
||||
if(*m_rxDma.GetIsReg() & m_rxDma.GetDmeMask()) {
|
||||
*m_rxDma.GetIfcReg() = m_rxDma.GetDmeMask();
|
||||
if(m_rxDma.IsEnabledIt_DME())
|
||||
RxDmaError(DmaHelper::DmaErrorType::DirectMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UsartCore::TxDmaIsr()
|
||||
{
|
||||
if(*m_txDma.GetIsReg() & m_txDma.GetTcMask()) { // DMA transfer complete
|
||||
*m_txDma.GetIfcReg() = m_txDma.GetTcMask();
|
||||
if(m_txDma.IsEnabledIt_TC())
|
||||
TxDmaTransferComplete();
|
||||
}
|
||||
if(*m_txDma.GetIsReg() & m_txDma.GetHtMask()) {
|
||||
*m_txDma.GetIfcReg() = m_txDma.GetHtMask();
|
||||
if(m_txDma.IsEnabledIt_HT())
|
||||
TxDmaHalfTransfer();
|
||||
}
|
||||
if(*m_txDma.GetIsReg() & m_txDma.GetTeMask()) {
|
||||
*m_txDma.GetIfcReg() = m_txDma.GetTeMask();
|
||||
if(m_txDma.IsEnabledIt_TE())
|
||||
TxDmaError(DmaHelper::DmaErrorType::Transfer);
|
||||
}
|
||||
if(*m_txDma.GetIsReg() & m_txDma.GetFeMask()) {
|
||||
*m_txDma.GetIfcReg() = m_txDma.GetFeMask();
|
||||
if(m_txDma.IsEnabledIt_FE())
|
||||
TxDmaError(DmaHelper::DmaErrorType::Fifo);
|
||||
}
|
||||
if(*m_txDma.GetIsReg() & m_txDma.GetDmeMask()) {
|
||||
*m_txDma.GetIfcReg() = m_txDma.GetDmeMask();
|
||||
if(m_txDma.IsEnabledIt_DME())
|
||||
TxDmaError(DmaHelper::DmaErrorType::DirectMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UsartCore::SetupTransmit(void const *buffer, uint16_t length)
|
||||
{
|
||||
LL_DMA_ConfigAddresses(m_txDma.GetDma(), m_txDma.GetStream(), reinterpret_cast<uint32_t>(buffer),
|
||||
LL_USART_DMA_GetRegAddr(m_usart), LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
|
||||
LL_DMA_SetDataLength(m_txDma.GetDma(), m_txDma.GetStream(), length);
|
||||
LL_USART_EnableDMAReq_TX(m_usart);
|
||||
LL_DMA_EnableStream(m_txDma.GetDma(), m_txDma.GetStream());
|
||||
}
|
||||
|
||||
|
||||
void UsartCore::SetupReceive(void *buffer, uint16_t length)
|
||||
{
|
||||
LL_DMA_ConfigAddresses(m_rxDma.GetDma(), m_rxDma.GetStream(), LL_USART_DMA_GetRegAddr(m_usart),
|
||||
reinterpret_cast<uint32_t>(buffer), LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
|
||||
LL_DMA_SetDataLength(m_rxDma.GetDma(), m_rxDma.GetStream(), length);
|
||||
LL_USART_EnableDMAReq_RX(m_usart);
|
||||
LL_USART_ClearFlag_ORE(m_usart);
|
||||
LL_DMA_EnableStream(m_rxDma.GetDma(), m_rxDma.GetStream());
|
||||
}
|
||||
|
||||
} /* namespace f4ll */
|
Loading…
Add table
Add a link
Reference in a new issue