6
Sort of ... Here is my latest fun demo -- still playing with tasks and freeRTOS on the Hercules. It's not perfect, so feel free to try it out and see if you can puzzle out why it's not right! First, a summary: You type in a serial terminal (or even dump a file to the serial port, because it uses interrupts/notifications it is fast!), and if the input is uppercase, it encodes it in ROT-13. That is, it sends back the "opposite" letter if the alphabet was on a wheel. It's the simplest bidirectional cipher I know. Here's an example: Now the code, starting with my changes to halcogen's sci.c . If you keep your code inside the USER CODE numbered sections, halcogen does not overwrite it! cool! view plainprint? Note: Text content in the code blocks is automatically word-wrapped 1. /* USER CODE BEGIN (1) */ 2. uint8 g_sci_rx_data = 'r'; 3. uint8 g_sci_tx_data = 't'; 4. /* USER CODE END */ 5. 6. . 7. . 8. . 9.

Hercules Importante Uart

Embed Size (px)

DESCRIPTION

UART Hercules Launchpad TI

Citation preview

Page 1: Hercules Importante Uart

Sort of ... Here is my latest fun demo -- still playing with tasks and freeRTOS on the Hercules.

It's not perfect, so feel free to try it out and see if you can puzzle out why it's not right!   

First, a summary: You type in a serial terminal (or even dump a file to the serial port, because it uses interrupts/notifications it is fast!), and if the input is uppercase, it encodes it in ROT-13. That is, it sends back the "opposite" letter if the alphabet was on a wheel. It's the simplest bidirectional cipher I know. 

Here's an example: 

Now the code, starting with my changes to halcogen's   sci.c . If you keep your code inside the USER CODE numbered sections, halcogen does not overwrite it! cool! view plainprint?Note: Text content in the code blocks is automatically word-wrapped

1. /* USER CODE BEGIN (1) */  2. uint8 g_sci_rx_data = 'r';  3. uint8 g_sci_tx_data = 't';  4. /* USER CODE END */  5.   6. .  7. .  8. .  9.   10. /* USER CODE BEGIN (3) */  11.     g_sciTransfer_t.rx_length = 1U;  12.     g_sciTransfer_t.rx_data = &g_sci_rx_data;  13.     g_sciTransfer_t.tx_length = 1U;  14.     g_sciTransfer_t.tx_data = &g_sci_tx_data;  15. /* USER CODE END */  

Page 2: Hercules Importante Uart

This makes a one-byte buffer for the RX and TX sides of the SCI/LIN (UART) peripheral. If I make the buffer longer, it seems like it doesn't work until it's filled up, so I just keep it at 1. However, it still takes 1 character to fill it up before it seems to work. I am puzzled!! 

And the main   program : view plainprint?Note: Text content in the code blocks is automatically word-wrapped

1. /* Include Files */  2. #include "esm.h"  3. #include "gio.h"  4. #include "het.h"  5. #include "stdlib.h"  6. #include "sci.h"  7. #include "sys_common.h"  8. #include "system.h"  9.   10. /* FreeRTOS includes */  11. #include "FreeRTOS.h"  12. #include "os_task.h"  13. #include "os_semphr.h"  14. #include "os_queue.h"  15.   16. /* Silly Macro definitions keep me smiling */  17. #define EVER (;;)  18.   19. boolean bFast = true;  20. xQueueHandle g_uartQ = 0;  21. xSemaphoreHandle flagEOL = 0;  22.   23. /* Task function prototypes */  24. static void prvTaskHET(void *pvParameters);  25. static void prvTaskGIO(void *pvParameters);  26. static void prvTaskButtonPoll(void *pvParameters);  27. static void prvTaskQROT(void *pvParameters);  28.   29. void main(void)  30. {  31.     _enable_interrupt_();  32.   33.     /* create a queue and semaphore to collect a line and flag the end o

f it */  34.     g_uartQ = xQueueCreate(32, sizeof(char));  35.     vSemaphoreCreateBinary(flagEOL);  36.   37.     /* initialize all TLAs in use */  38.     gioInit();  39.     hetInit();  40.     sciInit();  41.   42.     sciSend(scilinREG, 7, (unsigned char*)"ROT13\r\n");  43.   44.     sciEnableNotification(scilinREG, SCI_RX_INT);  45.   46.     /* Create Task 1 */  47.     if (xTaskCreate(prvTaskHET, (const signed char *)"TaskHET", configMI

NIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL) != pdTRUE)  48.     {  49.         /* Task could not be created */  50.         while(1);  51.     }  52.     /* Create Task 2 */  53.     if (xTaskCreate(prvTaskGIO, (const signed char *)"TaskGIO", configMI

NIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL) != pdTRUE)  54.     {  

Page 3: Hercules Importante Uart

55.         /* Task could not be created */  56.         while(1);  57.     }  58.     /* Create Task 3 */  59.     if (xTaskCreate(prvTaskButtonPoll, (const signed char *

)"ButtonPoll", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL) != pdTRUE)  

60.     {  61.         /* Loop if task could not be created */  62.         while(1);  63.     }  64.     /* Create Task 4 */  65.     if (xTaskCreate(prvTaskQROT, (const signed char *

)"ROT13QueueProcessor", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL) !=  pdTRUE)  

66.     {  67.         while(1);  68.     }  69.   70.     vTaskStartScheduler();  71.   72.     while(1);  73. }  74.   75.   76. /* toggle a HET pin */  77. static void prvTaskHET(void *pvParameters)  78. {  79.     for EVER  80.     {  81.         gioToggleBit(hetPORT1, 8);  82.         vTaskDelay((200/(bFast?1:2))/portTICK_RATE_MS);  83.     }  84. }  85.   86.   87. /* toggle a GIO pin */  88. static void prvTaskGIO(void *pvParameters)  89. {  90.     for EVER  91.     {  92.         gioToggleBit(gioPORTA, 2);  93.         vTaskDelay((300/(bFast?1:2))/portTICK_RATE_MS);  94.     }  95. }  96.   97.   98. /* periodically read a button state - avoids debouncing */  99. static void prvTaskButtonPoll(void *pvParameters)  100. {  101.     unsigned char ucLastState = pdFALSE;  102.     unsigned char ucState = pdFALSE;  103.   104.     for EVER  105.     {  106.         /* get button state */  107.         ucState = gioGetBit(gioPORTA, 7);  108.   109.         /* check for button press */  110.         if ( ucState != 0 )  111.         {  112.             ucState = pdTRUE;  113.         }  114.   115.         /* check for state change */  116.         if( ucState != ucLastState )  

Page 4: Hercules Importante Uart

117.         {  118.             ucLastState = ucState;  119.             if (ucState)  120.             {  121.                 bFast = !bFast;  122.             }  123.         }  124.         vTaskDelay(10/portTICK_RATE_MS);  125.     }  126. }  127.   128.   129. /* Wait for a semaphore signalling a full line of input, then enc

ode it! */  130. static void prvTaskQROT(void *pvParameters)  131. {  132.     static unsigned char c, e;  133.     const char ROT = 13;  134.     // default state of semaphore should be unavailable (taken)  135.     xSemaphoreTake(flagEOL, 100);  136.   137.     for EVER  138.     {  139.         if (xSemaphoreTake(flagEOL, portMAX_DELAY))  140.         {  141.             c = 0;  142.             sciSend(scilinREG, 5, (unsigned char*)"-OK\r\n");  143.             while (c != '\r')  144.             {  145.                 if (xQueueReceive(g_uartQ, &c, 1))  146.                 {  147.                     //encode the capital letters with ROT13.  148.                     if (c >= 'A' && c <= 'Z')  149.                     {  150.                        e = c + ROT;  151.                        if (e > 'Z')  152.                        {  153.                            e = c - ROT;  154.                        }  155.                        sciSend(scilinREG, 1, (unsigned char*)&e); 

 156.                     }  157.                     else  158.                     {  159.                        sciSend(scilinREG, 1, (unsigned char*)&c); 

 160.                     }  161.                 }  162.             }  163.             sciSend(scilinREG, 5, (unsigned char*)" :)\r\n");  164.   165.             // Take the semaphore again! If the queue was filled 

up, the program breaks if its only taken once...  166.             xSemaphoreTake(flagEOL, 0);  167.         }  168.     }  169. }  170.   171.   172. /* UART Interrupt handler */  173. void sciNotification(sciBASE_t *sci, uint32 flags)  174. {  175.     static uint8 c;  176.     //gioToggleBit(gioPORTA, 2);  177.   178.     // get the byte out of the interrupt register  

Page 5: Hercules Importante Uart

179.     sciReceive(sci, 1, &c);  180.   181.     //put the byte in a queue  182.     if (xQueueSendFromISR(g_uartQ, &c, 0))  183.     {  184.         //success  185.     }  186.     else  187.     {  188.         //queue send fail: probably full  189.     }  190.   191.     //flag the End of the Line  192.     if (c == '\r')  193.     {  194.         xSemaphoreGiveFromISR(flagEOL, NULL);  195.     }  196.     else  197.     {  198.         sciSend(sci, 1, &c);  199.     }  200.   201.     return;  202. }  

As you see, it uses a queue to accumulate characters from the interrupt, so that's neat. Also in the interrupt, it checks for the End-of-line character, '\r'. I couldn't get it working with '\n', maybe because my keyboard seems to only send '\r' when I press enter. Maybe my keyboard sends '\r\n' and I can't see it because of the one-byte buffer (but I don't think so). Anyway, if it finds '\r' it gives the semaphore, "flagEOL". This unblocks the task that will encode and display the message in ROT13. If you type a long message, the queue fills up and the program breaks a little bit -- I hacked around it by taking the semaphore twice, but another solution would be to make the queue longer. I'm not sure which approach is more practical. If you always expect your lines to be short, it's okay to just increase the queue length beyond that, but I'd prefer to make this work with much longer lines, I just haven't thought of a good way to implement it. 

Anyway, I spend too much time having fun, sending FRPERG ZRFFNTRF!!