Beruflich Dokumente
Kultur Dokumente
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
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;
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 */
_enable_interrupt_();
32.
33.
/* create a queue and semaphore to collect a line and flag the end o
f it */
34.
35.
vSemaphoreCreateBinary(flagEOL);
36.
37.
38.
gioInit();
39.
hetInit();
40.
sciInit();
41.
42.
43.
44.
sciEnableNotification(scilinREG, SCI_RX_INT);
45.
46.
47.
48.
/* Create Task 1 */
if (xTaskCreate(prvTaskHET, (const signed char *)"TaskHET", configMI
NIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL) != pdTRUE)
{
49.
50.
while(1);
51.
52.
/* Create Task 2 */
53.
54.
55.
56.
while(1);
57.
58.
/* Create Task 3 */
59.
60.
61.
62.
while(1);
63.
64.
/* Create Task 4 */
65.
66.
67.
68.
while(1);
}
69.
70.
71.
vTaskStartScheduler();
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.
102.
103.
104.
for EVER
105.
106.
107.
108.
109.
110.
if ( ucState != 0 )
111.
112.
ucState = pdTRUE;
113.
114.
115.
116.
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.
131.
132.
133.
134.
135.
xSemaphoreTake(flagEOL, 100);
136.
137.
for EVER
138.
139.
if (xSemaphoreTake(flagEOL, portMAX_DELAY))
140.
141.
c = 0;
142.
143.
while (c != '\r')
144.
145.
146.
147.
148.
149.
150.
e = c + ROT;
151.
if (e > 'Z')
152.
153.
e = c - ROT;
154.
155.
156.
157.
else
158.
159.
160.
161.
162.
163.
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.
173.
174.
175.
static uint8 c;
176.
//gioToggleBit(gioPORTA, 2);
177.
178.
179.
sciReceive(sci, 1, &c);
180.
181.
182.
183.
184.
//success
185.
186.
else
187.
188.
189.
190.
191.
192.
if (c == '\r')
193.
194.
xSemaphoreGiveFromISR(flagEOL, NULL);
195.
196.
else
197.
198.
sciSend(sci, 1, &c);
199.
200.
201.
202.
return;
}
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!!