Advertisement
ebak32

LoggerTask.c

Apr 9th, 2015
287
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.80 KB | None | 0 0
  1. #include <stdarg.h>
  2.  
  3. #include "mss_pdma.h"
  4.  
  5. #include "FreeRTOS.h"
  6. #include "FreeRTOSConfig.h"
  7. #include "queue.h"
  8. #include "task.h"
  9. #include "portmacro.h"
  10. #include "semphr.h"
  11.  
  12. #include "printf.h"
  13.  
  14. #define SPRINTF_BUF_SIZE    512
  15.  
  16. #define BUF_DEPTH   (10u)
  17. #define BUF_SIZE    (1u << BUF_DEPTH)
  18. #define BUF_MASK    (BUF_SIZE - 1)
  19. #define MAX_DMA_CHUNK   (128u)  /* for smoother increase of available DMA buffer space */
  20.  
  21. static QueueHandle_t queue = 0;
  22. static SemaphoreHandle_t mutex = 0;
  23. static volatile TaskHandle_t taskToNotify = NULL;
  24.  
  25. static char sprintfBuf[SPRINTF_BUF_SIZE];
  26.  
  27. typedef enum {
  28.     InterruptEvent, PrintEvent
  29. } EventType;
  30.  
  31. typedef struct {
  32.     EventType type;
  33.     const char * msg;
  34. } QueueEvent;
  35.  
  36.  
  37. static void lock() {
  38.     /* take mutex */
  39.     configASSERT(
  40.         xSemaphoreTake(mutex, portMAX_DELAY));
  41.     /* save task handle */
  42.     taskToNotify = xTaskGetCurrentTaskHandle();
  43. }
  44.  
  45. static void release() {
  46.     /* get task notification */
  47.     ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
  48.     /* release mutex */
  49.     configASSERT(
  50.         xSemaphoreGive(mutex));
  51. }
  52.  
  53. void print(const char * msg) {
  54.     QueueEvent event = { PrintEvent, msg };
  55.     lock();
  56.     /* write to task event queue */
  57.     configASSERT(
  58.         xQueueSendToBack(queue, &event, portMAX_DELAY));
  59.     release();
  60. }
  61.  
  62. void printf(const char * fmt, ...) {
  63.     va_list va;
  64.     QueueEvent event;
  65.     lock();
  66.     va_start(va, fmt);
  67.     vsprintf(sprintfBuf, fmt, va);
  68.     va_end(va);
  69.     event.type = PrintEvent;
  70.     event.msg = sprintfBuf;
  71.     /* write to task event queue */
  72.     configASSERT(
  73.         xQueueSendToBack(queue, &event, portMAX_DELAY));
  74.     release();
  75. }
  76.  
  77. static void pdmaChannel0IsrHandler() {
  78.     BaseType_t higherPriorityTaskWoken = pdFALSE;
  79.     QueueEvent event = { InterruptEvent, 0 };
  80.     /* GPIO->GPIO_OUT ^= MSS_GPIO_29_MASK; */
  81.     configASSERT(
  82.         xQueueSendToBackFromISR(queue, &event, &higherPriorityTaskWoken));
  83.     PDMA_disable_irq(PDMA_CHANNEL_0);   /* Important! */
  84.     /*if (higherPriorityTaskWoken)
  85.         portYIELD_FROM_ISR(pdTRUE); */
  86.     portYIELD_FROM_ISR(higherPriorityTaskWoken);
  87.     /* FIXME is it okay from handler callback */
  88. }
  89.  
  90. void initLoggerTask() {
  91.     mutex = xSemaphoreCreateMutex();
  92.     configASSERT(mutex);
  93.     queue = xQueueCreate(2, sizeof(QueueEvent));
  94.     configASSERT(queue);
  95.     PDMA_configure(
  96.         PDMA_CHANNEL_0,
  97.         PDMA_TO_UART_0,
  98.         PDMA_LOW_PRIORITY | PDMA_BYTE_TRANSFER | PDMA_INC_SRC_ONE_BYTE,
  99.         PDMA_DEFAULT_WRITE_ADJ
  100.     );
  101.     PDMA_set_irq_handler(PDMA_CHANNEL_0, pdmaChannel0IsrHandler);
  102. }
  103.  
  104. static char dmaBuffer[BUF_SIZE];
  105. static uint16_t
  106.     bufRdIdx = 0,
  107.     bufWrIdx = 0,
  108.     bufFree = BUF_SIZE;
  109.  
  110. static uint16_t writeDmaBuffer(const char * msg, uint32_t startIdx) {
  111.     char ch;
  112.     uint16_t wrote = 0;
  113.     while (bufFree) {
  114.         ch = msg[startIdx++];
  115.         if (!ch)
  116.             break;
  117.         --bufFree;
  118.         dmaBuffer[bufWrIdx++] = ch;
  119.         bufWrIdx &= BUF_MASK;
  120.         ++wrote;
  121.     }
  122.     return wrote;
  123. }
  124.  
  125. static void releaseDmaBufferBytes(uint16_t bytes) {
  126.     configASSERT((BUF_SIZE - bufFree) >= bytes);
  127.     bufRdIdx += bytes;
  128.     bufRdIdx &= BUF_MASK;
  129.     bufFree += bytes;
  130. }
  131.  
  132. static uint16_t getDmaBufferBytesToSend() {
  133.     uint16_t bytes = BUF_SIZE - bufFree;
  134.     uint16_t bytesTillEnd = BUF_SIZE - bufRdIdx;
  135.     uint16_t toSend =  bytes < bytesTillEnd ? bytes : bytesTillEnd;
  136.     return toSend > 2 * MAX_DMA_CHUNK ? MAX_DMA_CHUNK : toSend;
  137. }
  138.  
  139. void taskLogger(void * params) {
  140.     const char * msg = NULL;
  141.     uint32_t msgIdx;
  142.     uint16_t sentBytes = 0;
  143.     QueueEvent event;
  144.     uint8_t transmitting = 0;
  145.     if (!queue) initLoggerTask();
  146.     while (1) {
  147.         /* get queue event */
  148.         configASSERT(
  149.             xQueueReceive(queue, &event, portMAX_DELAY));
  150.         if (event.type == PrintEvent) {
  151.             /* assert no message left */
  152.             configASSERT(msg == NULL);
  153.             /* write message to buffer */
  154.             msgIdx = writeDmaBuffer(event.msg, 0u);
  155.             if (!event.msg[msgIdx]) { /* no message left */
  156.                 /* send task notification */
  157.                 configASSERT(
  158.                     xTaskNotifyGive(taskToNotify));
  159.                 /* msg remains NULL */
  160.             } else {
  161.                 msg = event.msg;
  162.             }
  163.         } else /* interrupt event */ {
  164.             transmitting = 0;
  165.             /* free up sent bytes from buffer */
  166.             releaseDmaBufferBytes(sentBytes);
  167.             sentBytes = 0;
  168.             if (msg) { /* message left */
  169.                 configASSERT(msg[msgIdx]);  /* TODO remove */
  170.                 /* write message to buffer */
  171.                 msgIdx += writeDmaBuffer(msg, msgIdx);
  172.                 if (!msg[msgIdx]) { /* no message left */
  173.                     /* send task notification */
  174.                     configASSERT(
  175.                         xTaskNotifyGive(taskToNotify));
  176.                     msg = NULL;
  177.                 }
  178.             }
  179.         }
  180.         if (!transmitting) {    /* not transmitting and has buffer data */
  181.             uint16_t bytesToSend = getDmaBufferBytesToSend();
  182.             if (bytesToSend) {
  183.                 /* start DMA transfer */
  184.                 PDMA_start(
  185.                     PDMA_CHANNEL_0,
  186.                     (uint32_t)&dmaBuffer[bufRdIdx], /* Important! Source must be in RAM not eNVM !!! */
  187.                     PDMA_UART0_TX_REGISTER,
  188.                     bytesToSend
  189.                 );
  190.                 PDMA_enable_irq(PDMA_CHANNEL_0);
  191.                 sentBytes = bytesToSend;
  192.                 transmitting = 1;
  193.             }
  194.         }
  195.     }
  196. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement