1 | #include "board.h"
|
2 | #include "cli.h"
|
3 |
|
4 | #include "FreeRTOS.h"
|
5 | #include "task.h"
|
6 |
|
7 | #include "stdio.h"
|
8 | #include "cdc_vcom.h"
|
9 |
|
10 | extern ErrorCode_t USB_Init(void);
|
11 | extern USBD_API_INIT_PARAM_T usb_param;
|
12 |
|
13 | long ledStackHighWaterMark;
|
14 | long uartStackHighWaterMark;
|
15 |
|
16 | static TaskHandle_t xUARTTaskHandle = NULL;
|
17 |
|
18 | static short rx_byte;
|
19 | static char rx_status;
|
20 |
|
21 | void UART_IRQHandler(void)
|
22 | {
|
23 | BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
24 |
|
25 | uint8_t iirvalue = Chip_UART_ReadIntIDReg(LPC_USART) & UART_IIR_INTID_MASK;
|
26 | if ((iirvalue == UART_IIR_INTID_RLS) || (iirvalue == UART_IIR_INTID_RDA))
|
27 | {
|
28 | rx_status = Chip_UART_ReadLineStatus(LPC_USART) & (UART_LSR_OE | UART_LSR_PE | UART_LSR_BI | UART_LSR_FE | UART_LSR_RXFE);
|
29 | rx_byte = Chip_UART_ReadByte(LPC_USART);
|
30 | }
|
31 | else if (iirvalue == UART_IIR_INTID_CTI) /* Character timeout indicator */
|
32 | {
|
33 | // if (UART_Character_Timeout)
|
34 | // UART_Character_Timeout();
|
35 | }
|
36 | else if (iirvalue == UART_IIR_INTID_THRE) /* THRE, transmit holding register empty */
|
37 | {
|
38 | /* all data transmitted on UART disable UART_IER_THREINT */
|
39 | Chip_UART_IntDisable(LPC_USART, UART_IER_THREINT);
|
40 | }
|
41 |
|
42 | NVIC_ClearPendingIRQ(UART0_IRQn);
|
43 |
|
44 | /* Notify the task that the transmission is complete. */
|
45 | // vTaskNotifyGiveFromISR( xUARTTaskHandle, &xHigherPriorityTaskWoken );
|
46 |
|
47 | /* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch
|
48 | should be performed to ensure the interrupt returns directly to the highest
|
49 | priority task. The macro used for this purpose is dependent on the port in
|
50 | use and may be called portEND_SWITCHING_ISR(). */
|
51 | // portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
52 | }
|
53 |
|
54 | static void vUARTTask(void *pvParameters)
|
55 | {
|
56 | uint32_t ulNotificationValue;
|
57 | const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 1000 );
|
58 |
|
59 | /* Store the handle of the calling task. */
|
60 | xUARTTaskHandle = xTaskGetCurrentTaskHandle();
|
61 |
|
62 | for (;;)
|
63 | {
|
64 | uartStackHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
|
65 |
|
66 | /* Wait for the transmission to complete. */
|
67 | ulNotificationValue = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
|
68 |
|
69 | if( ulNotificationValue >= 1 )
|
70 | {
|
71 | /* The transmission ended as expected. */
|
72 | printf("ISR - ch = 0x%02x\r\n", rx_byte);
|
73 | }
|
74 | else
|
75 | {
|
76 | /* The call to ulTaskNotifyTake() timed out. */
|
77 | printf("TO\r\n");
|
78 | // rx_byte = Chip_UART_ReadByte(LPC_USART);
|
79 | // printf("ch = %x\r\n", rx_byte);
|
80 | }
|
81 | }
|
82 | }
|
83 |
|
84 | /* LED toggle thread */
|
85 | static void vLEDTask(void *pvParameters)
|
86 | {
|
87 | for (;;)
|
88 | {
|
89 | ACT_LED_TOGGLE();
|
90 | vTaskDelay(configTICK_RATE_HZ/2);
|
91 | ledStackHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
|
92 | }
|
93 | }
|
94 |
|
95 | /* STATS thread */
|
96 | static void vStatsTask(void *pvParameters)
|
97 | {
|
98 | for (;;)
|
99 | {
|
100 | vTaskDelay(configTICK_RATE_HZ*10);
|
101 | printf("\r\n");
|
102 | printf("Heap: %d (act) / %d (min) byte free\r\n", xPortGetFreeHeapSize(), xPortGetMinimumEverFreeHeapSize());
|
103 | printf("this stack: %ld entries free\r\n", uxTaskGetStackHighWaterMark( NULL ));
|
104 | printf("UART stack: %ld entries free\r\n", uartStackHighWaterMark);
|
105 | printf("LED stack: %ld entries free\r\n", ledStackHighWaterMark);
|
106 | printf("\r\n");
|
107 | }
|
108 | }
|
109 |
|
110 | uint8_t lower_heap[5*1024];
|
111 |
|
112 | HeapRegion_t xHeapRegions[] = {
|
113 | { (uint8_t*)lower_heap, sizeof(lower_heap) },
|
114 | { NULL, 0 },
|
115 | { NULL, 0 }
|
116 | };
|
117 |
|
118 | /* Main Program */
|
119 | int main (void)
|
120 | {
|
121 | Board_Init();
|
122 | USB_Init();
|
123 | CLI_Init();
|
124 |
|
125 | /* Setup UART for 38.4K8E1 */
|
126 | Chip_UART_Init(LPC_USART);
|
127 | Chip_UART_SetBaud(LPC_USART, 38400);
|
128 | Chip_UART_ConfigData(LPC_USART, (UART_LCR_WLEN8 | UART_LCR_SBS_1BIT | UART_LCR_PARITY_EN | UART_LCR_PARITY_EVEN));
|
129 | Chip_UART_SetupFIFOS(LPC_USART, (UART_FCR_FIFO_EN | UART_FCR_TRG_LEV2));
|
130 | Chip_UART_TXEnable(LPC_USART);
|
131 |
|
132 | /* Enable receive data and line status interrupt */
|
133 | Chip_UART_IntEnable(LPC_USART, (UART_IER_RBRINT | UART_IER_RLSINT));
|
134 |
|
135 | /* prio = 3 */
|
136 | NVIC_SetPriority(UART0_IRQn, (1UL<<__NVIC_PRIO_BITS)-1UL); // only 2 bits used, so prio can be 0,1,2,3 where 0 is highest priority
|
137 | NVIC_EnableIRQ(UART0_IRQn);
|
138 |
|
139 | // use remaining USB RAM for RTOS heap
|
140 | xHeapRegions[1].pucStartAddress = (uint8_t*)usb_param.mem_base;
|
141 | xHeapRegions[1].xSizeInBytes = usb_param.mem_size;
|
142 |
|
143 | vPortDefineHeapRegions(xHeapRegions);
|
144 |
|
145 | /* UART thread */
|
146 | xTaskCreate(vUARTTask, "UART", 80, NULL, configMAX_PRIORITIES - 1, (xTaskHandle *) NULL);
|
147 |
|
148 | /* STATS thread */
|
149 | xTaskCreate(vStatsTask, "Stats", 80, NULL, tskIDLE_PRIORITY, (xTaskHandle *) NULL);
|
150 |
|
151 | /* LED toggle thread */
|
152 | xTaskCreate(vLEDTask, "LED", 32, NULL, tskIDLE_PRIORITY + 1, (xTaskHandle *) NULL);
|
153 |
|
154 | /* Start the scheduler */
|
155 | vTaskStartScheduler();
|
156 |
|
157 | for (;;)
|
158 | {
|
159 | if (rx_byte != -1)
|
160 | {
|
161 | printf("ISR - ch = 0x%02x\r\n", rx_byte);
|
162 | rx_byte = -1;
|
163 | }
|
164 | CLI_Task();
|
165 | }
|
166 | }
|
167 |
|
168 | void vApplicationIdleHook( void )
|
169 | {
|
170 | // must never been delayed by FreeRTOS function...
|
171 | CLI_Task(); // consume all input
|
172 | // __wfi();
|
173 | }
|
174 | /*-----------------------------------------------------------*/
|
175 |
|
176 | void vApplicationMallocFailedHook( void )
|
177 | {
|
178 | ACT_LED_ON();
|
179 | taskDISABLE_INTERRUPTS();
|
180 | for (;;) {;}
|
181 | }
|
182 | /*-----------------------------------------------------------*/
|
183 |
|
184 | void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
|
185 | {
|
186 | ( void ) pcTaskName;
|
187 | ( void ) pxTask;
|
188 |
|
189 | ACT_LED_ON();
|
190 | taskDISABLE_INTERRUPTS();
|
191 | for (;;) {;}
|
192 | }
|