main.c
Upload User: sz_yanmei
Upload Date: 2013-10-08
Package Size: 4585k
Code Size: 12k
Category:

OS Develop

Development Platform:

C/C++

  1. /*
  2. FreeRTOS.org V4.2.0 - Copyright (C) 2003-2007 Richard Barry.
  3. This file is part of the FreeRTOS.org distribution.
  4. FreeRTOS.org is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. FreeRTOS.org is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with FreeRTOS.org; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15. A special exception to the GPL can be applied should you wish to distribute
  16. a combined work that includes FreeRTOS.org, without being obliged to provide
  17. the source code for any proprietary components.  See the licensing section 
  18. of http://www.FreeRTOS.org for full details of how and when the exception
  19. can be applied.
  20. ***************************************************************************
  21. See http://www.FreeRTOS.org for documentation, latest information, license 
  22. and contact details.  Please ensure to read the configuration and relevant 
  23. port sections of the online documentation.
  24. ***************************************************************************
  25. */
  26. /*
  27.  * This project contains an application demonstrating the use of the 
  28.  * FreeRTOS.org mini real time scheduler on the Luminary Micro LM3S811 Eval
  29.  * board.  See http://www.FreeRTOS.org for more information.
  30.  *
  31.  * main() simply sets up the hardware, creates all the demo application tasks, 
  32.  * then starts the scheduler.  http://www.freertos.org/a00102.html provides
  33.  * more information on the standard demo tasks. 
  34.  *
  35.  * In addition to a subset of the standard demo application tasks, main.c also
  36.  * defines the following tasks: 
  37.  *
  38.  * + A 'Print' task.  The print task is the only task permitted to access the
  39.  * LCD - thus ensuring mutual exclusion and consistent access to the resource.
  40.  * Other tasks do not access the LCD directly, but instead send the text they
  41.  * wish to display to the print task.  The print task spends most of its time
  42.  * blocked - only waking when a message is queued for display.
  43.  *
  44.  * + A 'Button handler' task.  The eval board contains a user push button that
  45.  * is configured to generate interrupts.  The interrupt handler uses a 
  46.  * semaphore to wake the button handler task - demonstrating how the priority 
  47.  * mechanism can be used to defer interrupt processing to the task level.  The
  48.  * button handler task sends a message both to the LCD (via the print task) and
  49.  * the UART where it can be viewed using a dumb terminal (via the UART to USB
  50.  * converter on the eval board).  NOTES:  The dumb terminal must be closed in 
  51.  * order to reflash the microcontroller.  A very basic interrupt driven UART
  52.  * driver is used that does not use the FIFO.  19200 baud is used.
  53.  *
  54.  * + A 'check' task.  The check task only executes every five seconds but has a
  55.  * high priority so is guaranteed to get processor time.  Its function is to
  56.  * check that all the other tasks are still operational and that no errors have
  57.  * been detected at any time.  If no errors have every been detected 'PASS' is
  58.  * written to the display (via the print task) - if an error has ever been
  59.  * detected the message is changed to 'FAIL'.  The position of the message is
  60.  * changed for each write.
  61.  */
  62. /* Environment includes. */
  63. #include "DriverLib.h"
  64. /* Scheduler includes. */
  65. #include "FreeRTOS.h"
  66. #include "task.h"
  67. #include "queue.h"
  68. #include "semphr.h"
  69. /* Demo app includes. */
  70. #include "integer.h"
  71. #include "PollQ.h"
  72. #include "semtest.h"
  73. #include "BlockQ.h"
  74. /* Delay between cycles of the 'check' task. */
  75. #define mainCHECK_DELAY ( ( portTickType ) 5000 / portTICK_RATE_MS )
  76. /* UART configuration - note this does not use the FIFO so is not very 
  77. efficient. */
  78. #define mainBAUD_RATE ( 19200 )
  79. #define mainFIFO_SET ( 0x10 )
  80. /* Demo task priorities. */
  81. #define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 )
  82. #define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
  83. #define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
  84. #define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 )
  85. /* Demo board specifics. */
  86. #define mainPUSH_BUTTON             GPIO_PIN_4
  87. /* Misc. */
  88. #define mainQUEUE_SIZE ( 3 )
  89. #define mainDEBOUNCE_DELAY ( ( portTickType ) 150 / portTICK_RATE_MS )
  90. #define mainNO_DELAY ( ( portTickType ) 0 )
  91. /*
  92.  * Configure the processor and peripherals for this demo. 
  93.  */
  94. static void prvSetupHardware( void );
  95. /*
  96.  * The 'check' task, as described at the top of this file.
  97.  */
  98. static void vCheckTask( void *pvParameters );
  99. /*
  100.  * The task that is woken by the ISR that processes GPIO interrupts originating
  101.  * from the push button.
  102.  */
  103. static void vButtonHandlerTask( void *pvParameters );
  104. /*
  105.  * The task that controls access to the LCD.
  106.  */
  107. static void vPrintTask( void *pvParameter );
  108. /* String that is transmitted on the UART. */
  109. static portCHAR *cMessage = "Task woken by button interrupt! --- ";
  110. static volatile portCHAR *pcNextChar;
  111. /* The semaphore used to wake the button handler task from within the GPIO
  112. interrupt handler. */
  113. xSemaphoreHandle xButtonSemaphore;
  114. /* The queue used to send strings to the print task for display on the LCD. */
  115. xQueueHandle xPrintQueue;
  116. /*-----------------------------------------------------------*/
  117. int main( void )
  118. {
  119. /* Configure the clocks, UART and GPIO. */
  120. prvSetupHardware();
  121. /* Create the semaphore used to wake the button handler task from the GPIO
  122. ISR. */
  123. vSemaphoreCreateBinary( xButtonSemaphore );
  124. xSemaphoreTake( xButtonSemaphore, 0 );
  125. /* Create the queue used to pass message to vPrintTask. */
  126. xPrintQueue = xQueueCreate( mainQUEUE_SIZE, sizeof( portCHAR * ) );
  127. /* Start the standard demo tasks. */
  128. vStartIntegerMathTasks( tskIDLE_PRIORITY );
  129. vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
  130. vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
  131. vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
  132. /* Start the tasks defined within the file. */
  133. xTaskCreate( vCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );
  134. xTaskCreate( vButtonHandlerTask, "Status", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY + 1, NULL );
  135. xTaskCreate( vPrintTask, "Print", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY - 1, NULL );
  136. /* Start the scheduler. */
  137. vTaskStartScheduler();
  138. /* Will only get here if there was insufficient heap to start the 
  139. scheduler. */
  140. return 0;
  141. }
  142. /*-----------------------------------------------------------*/
  143. static void vCheckTask( void *pvParameters )
  144. {
  145. portBASE_TYPE xErrorOccurred = pdFALSE;
  146. portTickType xLastExecutionTime;
  147. const portCHAR *pcPassMessage = "PASS";
  148. const portCHAR *pcFailMessage = "FAIL";
  149. /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil()
  150. works correctly. */
  151. xLastExecutionTime = xTaskGetTickCount();
  152. for( ;; )
  153. {
  154. /* Perform this check every mainCHECK_DELAY milliseconds. */
  155. vTaskDelayUntil( &xLastExecutionTime, mainCHECK_DELAY );
  156. /* Has an error been found in any task? */
  157. if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
  158. {
  159. xErrorOccurred = pdTRUE;
  160. }
  161. if( xArePollingQueuesStillRunning() != pdTRUE )
  162. {
  163. xErrorOccurred = pdTRUE;
  164. }
  165. if( xAreSemaphoreTasksStillRunning() != pdTRUE )
  166. {
  167. xErrorOccurred = pdTRUE;
  168. }
  169. if( xAreBlockingQueuesStillRunning() != pdTRUE )
  170. {
  171. xErrorOccurred = pdTRUE;
  172. }
  173. /* Send either a pass or fail message.  If an error is found it is
  174. never cleared again.  We do not write directly to the LCD, but instead
  175. queue a message for display by the print task. */
  176. if( xErrorOccurred == pdTRUE )
  177. {
  178. xQueueSend( xPrintQueue, &pcFailMessage, portMAX_DELAY );
  179. }
  180. else
  181. {
  182. xQueueSend( xPrintQueue, &pcPassMessage, portMAX_DELAY );
  183. }
  184. }
  185. }
  186. /*-----------------------------------------------------------*/
  187. static void prvSetupHardware( void )
  188. {
  189. /* Setup the PLL. */
  190. SysCtlClockSet( SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_6MHZ );
  191. /* Setup the push button. */
  192. SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
  193.     GPIODirModeSet(GPIO_PORTC_BASE, mainPUSH_BUTTON, GPIO_DIR_MODE_IN);
  194. GPIOIntTypeSet( GPIO_PORTC_BASE, mainPUSH_BUTTON,GPIO_FALLING_EDGE );
  195. GPIOPinIntEnable( GPIO_PORTC_BASE, mainPUSH_BUTTON );
  196. IntEnable( INT_GPIOC );
  197. /* Enable the UART.  */
  198. SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
  199. SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
  200. /* Set GPIO A0 and A1 as peripheral function.  They are used to output the
  201. UART signals. */
  202. GPIODirModeSet( GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1, GPIO_DIR_MODE_HW );
  203. /* Configure the UART for 8-N-1 operation. */
  204. UARTConfigSet( UART0_BASE, mainBAUD_RATE, UART_CONFIG_WLEN_8 | UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE );
  205. /* We don't want to use the fifo.  This is for test purposes to generate
  206. as many interrupts as possible. */
  207. HWREG( UART0_BASE + UART_O_LCR_H ) &= ~mainFIFO_SET;
  208. /* Enable Tx interrupts. */
  209. HWREG( UART0_BASE + UART_O_IM ) |= UART_INT_TX;
  210. IntEnable( INT_UART0 );
  211. /* Initialise the LCD> */
  212.     OSRAMInit( false );
  213.     OSRAMStringDraw("www.FreeRTOS.org", 0, 0);
  214. OSRAMStringDraw("LM3S811 demo", 16, 1);
  215. }
  216. /*-----------------------------------------------------------*/
  217. static void vButtonHandlerTask( void *pvParameters )
  218. {
  219. const portCHAR *pcInterruptMessage = "Int";
  220. for( ;; )
  221. {
  222. /* Wait for a GPIO interrupt to wake this task. */
  223. while( xSemaphoreTake( xButtonSemaphore, portMAX_DELAY ) != pdPASS );
  224. /* Start the Tx of the message on the UART. */
  225. UARTIntDisable( UART0_BASE, UART_INT_TX );
  226. {
  227. pcNextChar = cMessage;
  228. /* Send the first character. */
  229. if( !( HWREG( UART0_BASE + UART_O_FR ) & UART_FR_TXFF ) )
  230. {
  231. HWREG( UART0_BASE + UART_O_DR ) = *pcNextChar;
  232. }
  233. pcNextChar++;
  234. }
  235. UARTIntEnable(UART0_BASE, UART_INT_TX);
  236. /* Queue a message for the print task to display on the LCD. */
  237. xQueueSend( xPrintQueue, &pcInterruptMessage, portMAX_DELAY );
  238. /* Make sure we don't process bounces. */
  239. vTaskDelay( mainDEBOUNCE_DELAY );
  240. xSemaphoreTake( xButtonSemaphore, mainNO_DELAY );
  241. }
  242. }
  243. /*-----------------------------------------------------------*/
  244. void vUART_ISR(void)
  245. {
  246. unsigned portLONG ulStatus;
  247. /* What caused the interrupt. */
  248. ulStatus = UARTIntStatus( UART0_BASE, pdTRUE );
  249. /* Clear the interrupt. */
  250. UARTIntClear( UART0_BASE, ulStatus );
  251. /* Was a Tx interrupt pending? */
  252. if( ulStatus & UART_INT_TX )
  253. {
  254. /* Send the next character in the string.  We are not using the FIFO. */
  255. if( *pcNextChar != NULL )
  256. {
  257. if( !( HWREG( UART0_BASE + UART_O_FR ) & UART_FR_TXFF ) )
  258. {
  259. HWREG( UART0_BASE + UART_O_DR ) = *pcNextChar;
  260. }
  261. pcNextChar++;
  262. }
  263. }
  264. }
  265. /*-----------------------------------------------------------*/
  266. void vGPIO_ISR( void )
  267. {
  268. /* Clear the interrupt. */
  269. GPIOPinIntClear(GPIO_PORTC_BASE, mainPUSH_BUTTON);
  270. /* Wake the button handler task. */
  271. if( xSemaphoreGiveFromISR( xButtonSemaphore, pdFALSE ) )
  272. {
  273. portEND_SWITCHING_ISR( pdTRUE );
  274. }
  275. }
  276. /*-----------------------------------------------------------*/
  277. static void vPrintTask( void *pvParameters )
  278. {
  279. portCHAR *pcMessage;
  280. unsigned portBASE_TYPE uxLine = 0, uxRow = 0;
  281. for( ;; )
  282. {
  283. /* Wait for a message to arrive. */
  284. xQueueReceive( xPrintQueue, &pcMessage, portMAX_DELAY );
  285. /* Write the message to the LCD. */
  286. uxRow++;
  287. uxLine++;
  288. OSRAMClear();
  289. OSRAMStringDraw( pcMessage, uxLine & 0x3f, uxRow & 0x01);
  290. }
  291. }