More elegant fsl::Task implementation
This commit is contained in:
parent
7eedbfdf9b
commit
0111f3d210
9 changed files with 301 additions and 19 deletions
|
@ -53,15 +53,15 @@ uint16_t ReadTouch(SPI_TypeDef *spi, bool x)
|
||||||
|
|
||||||
Application::Application()
|
Application::Application()
|
||||||
: GlobalsInitializer(&m_console)
|
: GlobalsInitializer(&m_console)
|
||||||
, Task(3)
|
, Task(3, &Application::Loop)
|
||||||
, m_console(USART1, DMA2, LL_DMA_STREAM_2, LL_DMA_STREAM_7, this, nullptr)
|
, m_console(USART1, DMA2, LL_DMA_STREAM_2, LL_DMA_STREAM_7, this, nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::TaskFn(void *taskObj)
|
//void Application::TaskFn(void *taskObj)
|
||||||
{
|
//{
|
||||||
static_cast<Application*>(reinterpret_cast<fsl::Task<Application, APPLICATION_STACK_SIZE>*>(taskObj))->Loop();
|
// static_cast<Application*>(reinterpret_cast<fsl::Task<Application, APPLICATION_STACK_SIZE>*>(taskObj))->Loop();
|
||||||
}
|
//}
|
||||||
|
|
||||||
void Application::Loop()
|
void Application::Loop()
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,11 +37,10 @@ class Application : public GlobalsInitializer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Application();
|
Application();
|
||||||
void Loop();
|
void Loop();
|
||||||
|
|
||||||
friend class fsl::Task<Application, APPLICATION_STACK_SIZE>;
|
friend class fsl::Task<Application, APPLICATION_STACK_SIZE>;
|
||||||
private:
|
private:
|
||||||
static void TaskFn(void *taskObj);
|
|
||||||
|
|
||||||
virtual void LineReceived(void *userParam, f4ll_cpp::SerialConsole<257>::Buffer *buffer);
|
virtual void LineReceived(void *userParam, f4ll_cpp::SerialConsole<257>::Buffer *buffer);
|
||||||
virtual void TransmissionComplete(void *userParam, f4ll_cpp::SerialConsole<257>::Buffer *buffer);
|
virtual void TransmissionComplete(void *userParam, f4ll_cpp::SerialConsole<257>::Buffer *buffer);
|
||||||
|
|
|
@ -51,6 +51,10 @@
|
||||||
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
|
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
extern uint32_t SystemCoreClock;
|
extern uint32_t SystemCoreClock;
|
||||||
|
/* USER CODE BEGIN 0 */
|
||||||
|
extern void configureTimerForRunTimeStats(void);
|
||||||
|
extern unsigned long getRunTimeCounterValue(void);
|
||||||
|
/* USER CODE END 0 */
|
||||||
#endif
|
#endif
|
||||||
#ifndef CMSIS_device_header
|
#ifndef CMSIS_device_header
|
||||||
#define CMSIS_device_header "stm32f4xx.h"
|
#define CMSIS_device_header "stm32f4xx.h"
|
||||||
|
@ -70,6 +74,7 @@
|
||||||
#define configMINIMAL_STACK_SIZE ((uint16_t)128)
|
#define configMINIMAL_STACK_SIZE ((uint16_t)128)
|
||||||
#define configTOTAL_HEAP_SIZE ((size_t)15360)
|
#define configTOTAL_HEAP_SIZE ((size_t)15360)
|
||||||
#define configMAX_TASK_NAME_LEN ( 16 )
|
#define configMAX_TASK_NAME_LEN ( 16 )
|
||||||
|
#define configGENERATE_RUN_TIME_STATS 1
|
||||||
#define configUSE_TRACE_FACILITY 1
|
#define configUSE_TRACE_FACILITY 1
|
||||||
#define configUSE_16_BIT_TICKS 0
|
#define configUSE_16_BIT_TICKS 0
|
||||||
#define configUSE_MUTEXES 1
|
#define configUSE_MUTEXES 1
|
||||||
|
@ -166,6 +171,12 @@ standard names. */
|
||||||
|
|
||||||
#define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 0
|
#define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 0
|
||||||
|
|
||||||
|
/* USER CODE BEGIN 2 */
|
||||||
|
/* Definitions needed when configGENERATE_RUN_TIME_STATS is on */
|
||||||
|
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS configureTimerForRunTimeStats
|
||||||
|
#define portGET_RUN_TIME_COUNTER_VALUE getRunTimeCounterValue
|
||||||
|
/* USER CODE END 2 */
|
||||||
|
|
||||||
/* USER CODE BEGIN Defines */
|
/* USER CODE BEGIN Defines */
|
||||||
/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */
|
/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */
|
||||||
/* USER CODE END Defines */
|
/* USER CODE END Defines */
|
||||||
|
|
|
@ -65,6 +65,23 @@ void StartDefaultTask(void *argument);
|
||||||
|
|
||||||
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
|
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
|
||||||
|
|
||||||
|
/* Hook prototypes */
|
||||||
|
void configureTimerForRunTimeStats(void);
|
||||||
|
unsigned long getRunTimeCounterValue(void);
|
||||||
|
|
||||||
|
/* USER CODE BEGIN 1 */
|
||||||
|
/* Functions needed when configGENERATE_RUN_TIME_STATS is on */
|
||||||
|
__weak void configureTimerForRunTimeStats(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
__weak unsigned long getRunTimeCounterValue(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* USER CODE END 1 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief FreeRTOS initialization
|
* @brief FreeRTOS initialization
|
||||||
* @param None
|
* @param None
|
||||||
|
|
|
@ -102,7 +102,7 @@ int main(void)
|
||||||
/* USER CODE BEGIN 2 */
|
/* USER CODE BEGIN 2 */
|
||||||
AppInit();
|
AppInit();
|
||||||
|
|
||||||
/* USER CODE END 2 */
|
/* USER CODE END 2 */
|
||||||
|
|
||||||
/* Init scheduler */
|
/* Init scheduler */
|
||||||
osKernelInitialize(); /* Call init function for freertos objects (in freertos.c) */
|
osKernelInitialize(); /* Call init function for freertos objects (in freertos.c) */
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
namespace f4ll_cpp {
|
namespace f4ll_cpp {
|
||||||
|
|
||||||
template<unsigned int bufSize> class SerialConsole : protected UartBase
|
template<size_t bufSize> class SerialConsole : protected UartBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
|
@ -52,7 +52,7 @@ private:
|
||||||
void *m_callbackUserParam;
|
void *m_callbackUserParam;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<unsigned int bufSize> SerialConsole<bufSize>::SerialConsole(
|
template<size_t bufSize> SerialConsole<bufSize>::SerialConsole(
|
||||||
USART_TypeDef *uart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx,
|
USART_TypeDef *uart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx,
|
||||||
ISerialConsoleCallback *callback, void *callbackUserParam
|
ISerialConsoleCallback *callback, void *callbackUserParam
|
||||||
)
|
)
|
||||||
|
@ -63,13 +63,13 @@ template<unsigned int bufSize> SerialConsole<bufSize>::SerialConsole(
|
||||||
SetupReceive(m_rxBuffers[m_activeRxBuffer].buffer, bufSize);
|
SetupReceive(m_rxBuffers[m_activeRxBuffer].buffer, bufSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned int bufSize> void SerialConsole<bufSize>::SetupTransmit(void *buffer, uint16_t length)
|
template<size_t bufSize> void SerialConsole<bufSize>::SetupTransmit(void *buffer, uint16_t length)
|
||||||
{
|
{
|
||||||
m_txBuffer.busy = true;
|
m_txBuffer.busy = true;
|
||||||
UartBase::SetupTransmit(buffer, length);
|
UartBase::SetupTransmit(buffer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned int bufSize> void SerialConsole<bufSize>::HandleRxDmaIrq()
|
template<size_t bufSize> void SerialConsole<bufSize>::HandleRxDmaIrq()
|
||||||
{
|
{
|
||||||
if(*m_rxDma.GetIsReg() & m_rxDma.GetTcMask()) {
|
if(*m_rxDma.GetIsReg() & m_rxDma.GetTcMask()) {
|
||||||
*m_rxDma.GetIfcReg() = m_rxDma.GetTcMask();
|
*m_rxDma.GetIfcReg() = m_rxDma.GetTcMask();
|
||||||
|
@ -87,7 +87,7 @@ template<unsigned int bufSize> void SerialConsole<bufSize>::HandleRxDmaIrq()
|
||||||
SetupReceive(m_rxBuffers[m_activeRxBuffer].buffer, bufSize);
|
SetupReceive(m_rxBuffers[m_activeRxBuffer].buffer, bufSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned int bufSize> void SerialConsole<bufSize>::HandleTxDmaIrq()
|
template<size_t bufSize> void SerialConsole<bufSize>::HandleTxDmaIrq()
|
||||||
{
|
{
|
||||||
if(*m_txDma.GetIsReg() & m_txDma.GetTcMask()) { // DMA transfer complete
|
if(*m_txDma.GetIsReg() & m_txDma.GetTcMask()) { // DMA transfer complete
|
||||||
*m_txDma.GetIfcReg() = m_txDma.GetTcMask();
|
*m_txDma.GetIfcReg() = m_txDma.GetTcMask();
|
||||||
|
@ -102,7 +102,7 @@ template<unsigned int bufSize> void SerialConsole<bufSize>::HandleTxDmaIrq()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned int bufSize> void SerialConsole<bufSize>::HandleUsartIrq()
|
template<size_t bufSize> void SerialConsole<bufSize>::HandleUsartIrq()
|
||||||
{
|
{
|
||||||
if(LL_USART_IsActiveFlag_IDLE(m_uart) && LL_USART_IsEnabledIT_IDLE(m_uart)) { // receiver idle
|
if(LL_USART_IsActiveFlag_IDLE(m_uart) && LL_USART_IsEnabledIT_IDLE(m_uart)) { // receiver idle
|
||||||
// we assume that new line marker will arrive without an idle cycle even if it is CRLF
|
// we assume that new line marker will arrive without an idle cycle even if it is CRLF
|
||||||
|
@ -136,7 +136,7 @@ template<unsigned int bufSize> void SerialConsole<bufSize>::HandleUsartIrq()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned int bufSize> void SerialConsole<bufSize>::Send(char const *buffer, uint8_t length)
|
template<size_t bufSize> void SerialConsole<bufSize>::Send(char const *buffer, uint8_t length)
|
||||||
{
|
{
|
||||||
if(!length) {
|
if(!length) {
|
||||||
auto computedLength = strlen(buffer);
|
auto computedLength = strlen(buffer);
|
||||||
|
@ -150,7 +150,7 @@ template<unsigned int bufSize> void SerialConsole<bufSize>::Send(char const *buf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned int bufSize> void SerialConsole<bufSize>::SendLine(char const *buffer, uint8_t length)
|
template<size_t bufSize> void SerialConsole<bufSize>::SendLine(char const *buffer, uint8_t length)
|
||||||
{
|
{
|
||||||
if(!length) {
|
if(!length) {
|
||||||
auto computedLength = strlen(buffer);
|
auto computedLength = strlen(buffer);
|
||||||
|
|
245
components/fsl/ringbuffer.h
Normal file
245
components/fsl/ringbuffer.h
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
/*
|
||||||
|
* ringbuffer.h
|
||||||
|
*
|
||||||
|
* Created on: Sep 14, 2021
|
||||||
|
* Author: Attila Body
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <semphr.h>
|
||||||
|
#include <task.h>
|
||||||
|
|
||||||
|
namespace fsl {
|
||||||
|
|
||||||
|
template<size_t capacity> class RingBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Initializes the ring buffer internal structure with the corresponding parameters.
|
||||||
|
* Provided only for convenience, the structure also can be initialized locally
|
||||||
|
*/
|
||||||
|
RingBuffer(TaskHandle_t consumerTask,
|
||||||
|
// BaseType_t consumerNotifyIndex,
|
||||||
|
uint32_t consumerNotifyMask,
|
||||||
|
TaskHandle_t producerTask,
|
||||||
|
// BaseType_t producerNotifyIndex,
|
||||||
|
uint32_t producerNotifyMask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copies data to the ring buffer (without committing it) The amount of the committed data in the buffer
|
||||||
|
* should not exceed the size of the buffer.
|
||||||
|
* @param data Pointer to the data to copy
|
||||||
|
* @param len Length of the data to copy
|
||||||
|
*/
|
||||||
|
void Put(uint8_t const *data_buffer, size_t len);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Commits the data already placed into the buffer and notifies the consumer about it's availability
|
||||||
|
*/
|
||||||
|
void Commit();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Waits until all the data from the ring buffer gets consumed.
|
||||||
|
*/
|
||||||
|
void Flush();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets a pointer to the next chunk of committed data in the buffer without administering the consumption
|
||||||
|
* of it. The caller should also call ringbuffer_RepostConsumption using the returned chunk length after
|
||||||
|
* it finished processing the data.
|
||||||
|
* @param[in] len_requested Length of the data requested from the buffer. The length of the actual data provided
|
||||||
|
* might be actually smaller (because either reaching the end of the buffer or not enough data in the buffer).
|
||||||
|
* @param[out] data Receives 1a pointer to the first byte of the available data in the buffer
|
||||||
|
* @param[out] len Receives the length of the chunk available in the buffer. Will not exceed len_requested.
|
||||||
|
* @retval true if the buffer has more available data, false otherwise
|
||||||
|
* @remark The caller should wait for notification from the producer task (using m_producerNotifyIndex
|
||||||
|
* and producer_notify_mask) before calling this function and consume the data
|
||||||
|
* (also registering each consumption cycle) until this function returns false
|
||||||
|
*/
|
||||||
|
bool GetChunk(size_t len_requested, uint8_t *&data, size_t &len);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Marks the chunk returned by ringbuffer_GetChunk as available
|
||||||
|
* @param consumed The length of the chunk as returned by ringbuffer_GetChunk(..., len)
|
||||||
|
*/
|
||||||
|
void ReportConsumption(size_t consumed);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_head; //!< Write position
|
||||||
|
size_t m_headShadow; //!< Shadowed write position for collecting data before committing it
|
||||||
|
size_t m_tail; //!< Read position
|
||||||
|
TaskHandle_t m_consumerTask; //!< Task handle of the consumer (to notify when data is available)
|
||||||
|
BaseType_t m_consumerNotifyIndex; //!< Notification index used for consumer notification
|
||||||
|
uint32_t m_consumerNotifyMask; //!< Notification data for the consumer
|
||||||
|
TaskHandle_t m_producerTask; //!< Task handle of the producer (to notify when available buffer space increased)
|
||||||
|
BaseType_t m_producerNotifyIndex; //!< Notification index used for producer notification
|
||||||
|
uint32_t m_producerNotifyMask; //!< Notification data for the producer
|
||||||
|
|
||||||
|
uint8_t m_buffer[capacity]; //!< Pointer to the phisical memory bufer
|
||||||
|
|
||||||
|
static inline size_t used(size_t s, size_t h, size_t t)
|
||||||
|
{
|
||||||
|
return (((h) >= (t)) ? ((h) - (t)) : ((s) - (t) + (h)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t available(size_t s, size_t h, size_t t)
|
||||||
|
{
|
||||||
|
return ((s) - used(s, h, t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ASSERT(bool pred)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template<size_t capacity> RingBuffer<capacity>::RingBuffer(
|
||||||
|
TaskHandle_t consumerTask,
|
||||||
|
// BaseType_t consumerNotifyIndex,
|
||||||
|
uint32_t consumerNotifyMask,
|
||||||
|
TaskHandle_t producerTask,
|
||||||
|
// BaseType_t producerNotifyIndex,
|
||||||
|
uint32_t producerNotifyMask)
|
||||||
|
: m_consumerTask(consumerTask)
|
||||||
|
// , m_consumerNotifyIndex(consumerNotifyIndex)
|
||||||
|
, m_consumerNotifyMask(consumerNotifyMask)
|
||||||
|
, m_producerTask(producerTask)
|
||||||
|
// , m_producerNotifyIndex(producerNotifyIndex)
|
||||||
|
, m_producerNotifyMask(producerNotifyMask)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
template<size_t capacity> void RingBuffer<capacity>::Put(uint8_t const *data_buffer, size_t len)
|
||||||
|
{
|
||||||
|
uint16_t chunk1 = 0;
|
||||||
|
uint16_t chunk2 = 0;
|
||||||
|
uint16_t uncommitted = 0;
|
||||||
|
uncommitted = used(capacity, m_headShadow, m_head);
|
||||||
|
|
||||||
|
__ASSERT(uncommitted + len + 1 <= capacity);
|
||||||
|
|
||||||
|
if(xPortIsInsideInterrupt()) {
|
||||||
|
if(available(capacity, m_headShadow, m_tail) < len + 1) {
|
||||||
|
__ASSERT(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while(available(capacity, m_headShadow, m_tail) < len + 1) {
|
||||||
|
// xTaskNotifyWaitIndexed(m_producerNotifyIndex, 0, m_producerNotifyMask, NULL, portMAX_DELAY);
|
||||||
|
xTaskNotifyWait(0, m_producerNotifyMask, NULL, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk1 = capacity - m_headShadow;
|
||||||
|
if(chunk1 >= len) {
|
||||||
|
chunk1 = len;
|
||||||
|
} else {
|
||||||
|
chunk2 = len - chunk1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(m_buffer + m_headShadow, data_buffer, chunk1);
|
||||||
|
m_headShadow += chunk1;
|
||||||
|
if(m_headShadow == capacity) {
|
||||||
|
m_headShadow = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chunk2) {
|
||||||
|
memcpy(m_buffer, data_buffer + chunk1, chunk2);
|
||||||
|
m_headShadow += chunk2;
|
||||||
|
if(m_headShadow == capacity) {
|
||||||
|
m_headShadow = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<size_t capacity> void RingBuffer<capacity>::Commit()
|
||||||
|
{
|
||||||
|
uint16_t uncommitted = used(capacity, m_headShadow, m_head);
|
||||||
|
|
||||||
|
if(!uncommitted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_head = m_headShadow;
|
||||||
|
|
||||||
|
if(xPortIsInsideInterrupt()) {
|
||||||
|
BaseType_t woken_up = 0;
|
||||||
|
// xTaskNotifyIndexedFromISR(m_consumerTask, m_consumerNotifyIndex, m_consumerNotifyMask, eSetBits, &woken_up);
|
||||||
|
xTaskNotifyFromISR(m_consumerTask, m_consumerNotifyMask, eSetBits, &woken_up);
|
||||||
|
portYIELD_FROM_ISR(woken_up); // NOLINT(hicpp-no-assembler)
|
||||||
|
} else {
|
||||||
|
// xTaskNotifyIndexed(m_consumerTask, m_consumerNotifyIndex, m_consumerNotifyMask, eSetBits);
|
||||||
|
xTaskNotify(m_consumerTask, m_consumerNotifyMask, eSetBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<size_t capacity> void RingBuffer<capacity>::Flush()
|
||||||
|
{
|
||||||
|
while(m_head != m_tail) {
|
||||||
|
// TODO: Watchdog?
|
||||||
|
// xTaskNotifyWaitIndexed(m_producerNotifyIndex, 0, m_producerNotifyMask, NULL, portMAX_DELAY);
|
||||||
|
xTaskNotifyWait(0, m_producerNotifyMask, NULL, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<size_t capacity> bool RingBuffer<capacity>::GetChunk(size_t len_requested, uint8_t *&data, size_t &len)
|
||||||
|
{
|
||||||
|
size_t head = m_head;
|
||||||
|
size_t tail = m_tail;
|
||||||
|
size_t chunk_size = head >= tail ? head - tail : capacity - tail;
|
||||||
|
if(!chunk_size) {
|
||||||
|
len = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(chunk_size > len_requested) {
|
||||||
|
chunk_size = len_requested;
|
||||||
|
}
|
||||||
|
data = m_buffer + tail;
|
||||||
|
len = chunk_size;
|
||||||
|
|
||||||
|
tail += chunk_size;
|
||||||
|
if(tail == capacity) {
|
||||||
|
tail = 0;
|
||||||
|
}
|
||||||
|
return tail != head;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<size_t capacity> void RingBuffer<capacity>::ReportConsumption(size_t consumed)
|
||||||
|
{
|
||||||
|
if(!consumed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_tail += consumed;
|
||||||
|
if(m_tail == capacity) {
|
||||||
|
m_tail = 0;
|
||||||
|
}
|
||||||
|
if(m_producerTask) {
|
||||||
|
if(xPortIsInsideInterrupt()) {
|
||||||
|
BaseType_t woken_up = 0;
|
||||||
|
// xTaskNotifyIndexedFromISR(m_producerTask, m_producerNotifyIndex, m_producerNotifyMask, eSetBits, &woken_up);
|
||||||
|
xTaskNotifyFromISR(m_producerTask, m_producerNotifyMask, eSetBits, &woken_up);
|
||||||
|
portYIELD_FROM_ISR(woken_up); // NOLINT(hicpp-no-assembler)
|
||||||
|
} else {
|
||||||
|
// xTaskNotifyIndexed(m_producerTask, m_producerNotifyIndex, producerNotifyMask, eSetBits);
|
||||||
|
xTaskNotify(m_producerTask, m_producerNotifyMask, eSetBits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // fsl
|
|
@ -16,17 +16,26 @@ namespace fsl {
|
||||||
|
|
||||||
template<typename T, uint32_t stackSize> class Task {
|
template<typename T, uint32_t stackSize> class Task {
|
||||||
public:
|
public:
|
||||||
Task(UBaseType_t priority) : m_priority(priority) {}
|
Task(UBaseType_t priority, void (T::*fp)()) : m_priority(priority), m_fp(fp) {}
|
||||||
void Start(SemaphoreHandle_t doneSem = nullptr, bool waitForInit = false) {
|
void Start(SemaphoreHandle_t doneSem = nullptr, bool waitForInit = false) {
|
||||||
m_handle = xTaskCreateStatic(T::TaskFn, getName(), sizeof(m_stack)/sizeof(m_stack[0]),
|
m_handle = xTaskCreateStatic(staticBridge, getName(), sizeof(m_stack)/sizeof(m_stack[0]),
|
||||||
this, m_priority, m_stack, &m_tcb);
|
this, m_priority, m_stack, &m_tcb);
|
||||||
}
|
}
|
||||||
virtual ~Task() {};
|
virtual ~Task() {};
|
||||||
virtual char const * getName() = 0;
|
virtual char const * getName() = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void staticBridge(void *taskObj) {
|
||||||
|
reinterpret_cast<Task<T, stackSize>*>(taskObj)->taskBridge();
|
||||||
|
}
|
||||||
|
|
||||||
|
void taskBridge() {
|
||||||
|
(static_cast<T*>(this)->*m_fp)();
|
||||||
|
}
|
||||||
|
|
||||||
TaskHandle_t m_handle;
|
TaskHandle_t m_handle;
|
||||||
UBaseType_t m_priority;
|
UBaseType_t m_priority;
|
||||||
|
void (T::*m_fp)();
|
||||||
StaticTask_t m_tcb;
|
StaticTask_t m_tcb;
|
||||||
StackType_t m_stack[stackSize];
|
StackType_t m_stack[stackSize];
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,8 +37,9 @@ Dma.USART1_TX.2.PeriphInc=DMA_PINC_DISABLE
|
||||||
Dma.USART1_TX.2.Priority=DMA_PRIORITY_LOW
|
Dma.USART1_TX.2.Priority=DMA_PRIORITY_LOW
|
||||||
Dma.USART1_TX.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
|
Dma.USART1_TX.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
|
||||||
FREERTOS.FootprintOK=true
|
FREERTOS.FootprintOK=true
|
||||||
FREERTOS.IPParameters=Tasks01,configMINIMAL_STACK_SIZE,FootprintOK,configUSE_NEWLIB_REENTRANT
|
FREERTOS.IPParameters=Tasks01,configMINIMAL_STACK_SIZE,FootprintOK,configUSE_NEWLIB_REENTRANT,configGENERATE_RUN_TIME_STATS
|
||||||
FREERTOS.Tasks01=defaultTask,24,384,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL
|
FREERTOS.Tasks01=defaultTask,24,384,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL
|
||||||
|
FREERTOS.configGENERATE_RUN_TIME_STATS=1
|
||||||
FREERTOS.configMINIMAL_STACK_SIZE=128
|
FREERTOS.configMINIMAL_STACK_SIZE=128
|
||||||
FREERTOS.configUSE_NEWLIB_REENTRANT=1
|
FREERTOS.configUSE_NEWLIB_REENTRANT=1
|
||||||
FSMC.AddressSetupTime1=1
|
FSMC.AddressSetupTime1=1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue