Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdarg.h>
- #include "mss_pdma.h"
- #include "FreeRTOS.h"
- #include "FreeRTOSConfig.h"
- #include "queue.h"
- #include "task.h"
- #include "portmacro.h"
- #include "semphr.h"
- #include "printf.h"
- #define SPRINTF_BUF_SIZE 512
- #define BUF_DEPTH (10u)
- #define BUF_SIZE (1u << BUF_DEPTH)
- #define BUF_MASK (BUF_SIZE - 1)
- #define MAX_DMA_CHUNK (128u) /* for smoother increase of available DMA buffer space */
- static QueueHandle_t queue = 0;
- static SemaphoreHandle_t mutex = 0;
- static volatile TaskHandle_t taskToNotify = NULL;
- static char sprintfBuf[SPRINTF_BUF_SIZE];
- typedef enum {
- InterruptEvent, PrintEvent
- } EventType;
- typedef struct {
- EventType type;
- const char * msg;
- } QueueEvent;
- static void lock() {
- /* take mutex */
- configASSERT(
- xSemaphoreTake(mutex, portMAX_DELAY));
- /* save task handle */
- taskToNotify = xTaskGetCurrentTaskHandle();
- }
- static void release() {
- /* get task notification */
- ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
- /* release mutex */
- configASSERT(
- xSemaphoreGive(mutex));
- }
- void print(const char * msg) {
- QueueEvent event = { PrintEvent, msg };
- lock();
- /* write to task event queue */
- configASSERT(
- xQueueSendToBack(queue, &event, portMAX_DELAY));
- release();
- }
- void printf(const char * fmt, ...) {
- va_list va;
- QueueEvent event;
- lock();
- va_start(va, fmt);
- vsprintf(sprintfBuf, fmt, va);
- va_end(va);
- event.type = PrintEvent;
- event.msg = sprintfBuf;
- /* write to task event queue */
- configASSERT(
- xQueueSendToBack(queue, &event, portMAX_DELAY));
- release();
- }
- static void pdmaChannel0IsrHandler() {
- BaseType_t higherPriorityTaskWoken = pdFALSE;
- QueueEvent event = { InterruptEvent, 0 };
- /* GPIO->GPIO_OUT ^= MSS_GPIO_29_MASK; */
- configASSERT(
- xQueueSendToBackFromISR(queue, &event, &higherPriorityTaskWoken));
- PDMA_disable_irq(PDMA_CHANNEL_0); /* Important! */
- /*if (higherPriorityTaskWoken)
- portYIELD_FROM_ISR(pdTRUE); */
- portYIELD_FROM_ISR(higherPriorityTaskWoken);
- /* FIXME is it okay from handler callback */
- }
- void initLoggerTask() {
- mutex = xSemaphoreCreateMutex();
- configASSERT(mutex);
- queue = xQueueCreate(2, sizeof(QueueEvent));
- configASSERT(queue);
- PDMA_configure(
- PDMA_CHANNEL_0,
- PDMA_TO_UART_0,
- PDMA_LOW_PRIORITY | PDMA_BYTE_TRANSFER | PDMA_INC_SRC_ONE_BYTE,
- PDMA_DEFAULT_WRITE_ADJ
- );
- PDMA_set_irq_handler(PDMA_CHANNEL_0, pdmaChannel0IsrHandler);
- }
- static char dmaBuffer[BUF_SIZE];
- static uint16_t
- bufRdIdx = 0,
- bufWrIdx = 0,
- bufFree = BUF_SIZE;
- static uint16_t writeDmaBuffer(const char * msg, uint32_t startIdx) {
- char ch;
- uint16_t wrote = 0;
- while (bufFree) {
- ch = msg[startIdx++];
- if (!ch)
- break;
- --bufFree;
- dmaBuffer[bufWrIdx++] = ch;
- bufWrIdx &= BUF_MASK;
- ++wrote;
- }
- return wrote;
- }
- static void releaseDmaBufferBytes(uint16_t bytes) {
- configASSERT((BUF_SIZE - bufFree) >= bytes);
- bufRdIdx += bytes;
- bufRdIdx &= BUF_MASK;
- bufFree += bytes;
- }
- static uint16_t getDmaBufferBytesToSend() {
- uint16_t bytes = BUF_SIZE - bufFree;
- uint16_t bytesTillEnd = BUF_SIZE - bufRdIdx;
- uint16_t toSend = bytes < bytesTillEnd ? bytes : bytesTillEnd;
- return toSend > 2 * MAX_DMA_CHUNK ? MAX_DMA_CHUNK : toSend;
- }
- void taskLogger(void * params) {
- const char * msg = NULL;
- uint32_t msgIdx;
- uint16_t sentBytes = 0;
- QueueEvent event;
- uint8_t transmitting = 0;
- if (!queue) initLoggerTask();
- while (1) {
- /* get queue event */
- configASSERT(
- xQueueReceive(queue, &event, portMAX_DELAY));
- if (event.type == PrintEvent) {
- /* assert no message left */
- configASSERT(msg == NULL);
- /* write message to buffer */
- msgIdx = writeDmaBuffer(event.msg, 0u);
- if (!event.msg[msgIdx]) { /* no message left */
- /* send task notification */
- configASSERT(
- xTaskNotifyGive(taskToNotify));
- /* msg remains NULL */
- } else {
- msg = event.msg;
- }
- } else /* interrupt event */ {
- transmitting = 0;
- /* free up sent bytes from buffer */
- releaseDmaBufferBytes(sentBytes);
- sentBytes = 0;
- if (msg) { /* message left */
- configASSERT(msg[msgIdx]); /* TODO remove */
- /* write message to buffer */
- msgIdx += writeDmaBuffer(msg, msgIdx);
- if (!msg[msgIdx]) { /* no message left */
- /* send task notification */
- configASSERT(
- xTaskNotifyGive(taskToNotify));
- msg = NULL;
- }
- }
- }
- if (!transmitting) { /* not transmitting and has buffer data */
- uint16_t bytesToSend = getDmaBufferBytesToSend();
- if (bytesToSend) {
- /* start DMA transfer */
- PDMA_start(
- PDMA_CHANNEL_0,
- (uint32_t)&dmaBuffer[bufRdIdx], /* Important! Source must be in RAM not eNVM !!! */
- PDMA_UART0_TX_REGISTER,
- bytesToSend
- );
- PDMA_enable_irq(PDMA_CHANNEL_0);
- sentBytes = bytesToSend;
- transmitting = 1;
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement