]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_LM3S102_Rowley/Demo3/main.c
Update to MIT licensed FreeRTOS V10.0.0 - see https://www.freertos.org/History.txt
[freertos] / FreeRTOS / Demo / CORTEX_LM3S102_Rowley / Demo3 / main.c
1 /*\r
2  * FreeRTOS Kernel V10.0.0\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software. If you wish to use our Amazon\r
14  * FreeRTOS name, please do so in a fair use way that does not cause confusion.\r
15  *\r
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
18  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
19  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
22  *\r
23  * http://www.FreeRTOS.org\r
24  * http://aws.amazon.com/freertos\r
25  *\r
26  * 1 tab == 4 spaces!\r
27  */\r
28 \r
29 \r
30 /*\r
31  * This is a mini co-routine demo for the Rowley CrossFire LM3S102 development\r
32  * board.  It makes use of the boards tri-colour LED and analogue input.\r
33  *\r
34  * Four co-routines are created - an 'I2C' co-routine and three 'flash'\r
35  * co-routines.\r
36  *\r
37  * The I2C co-routine triggers an ADC conversion then blocks on a queue to \r
38  * wait for the conversion result - which it receives on the queue directly\r
39  * from the I2C interrupt service routine.  The conversion result is then\r
40  * scalled to a delay period.  The I2C interrupt then wakes each of the \r
41  * flash co-routines before itself delaying for the calculated period and\r
42  * then repeating the whole process.\r
43  *\r
44  * When woken by the I2C co-routine the flash co-routines each block for \r
45  * a given period, illuminate an LED for a fixed period, then go back to\r
46  * sleep to wait for the next cycle.  The uxIndex parameter of the flash\r
47  * co-routines is used to ensure that each flashes a different LED, and that\r
48  * the delay periods are such that the LED's get flashed in sequence.\r
49  */\r
50 \r
51 \r
52 /* Scheduler include files. */\r
53 #include "FreeRTOS.h"\r
54 #include "task.h"\r
55 #include "queue.h"\r
56 #include "croutine.h"\r
57 \r
58 /* Demo application include files. */\r
59 #include "partest.h"\r
60 \r
61 /* Library include files. */\r
62 #include "DriverLib.h"\r
63 \r
64 /* States of the I2C master interface. */\r
65 #define mainI2C_IDLE       0\r
66 #define mainI2C_READ_1     1\r
67 #define mainI2C_READ_2     2\r
68 #define mainI2C_READ_DONE  3\r
69 \r
70 #define mainZERO_LENGTH 0\r
71 \r
72 /* Address of the A2D IC on the CrossFire board. */\r
73 #define mainI2CAddress  0x4D\r
74 \r
75 /* The queue used to send data from the I2C ISR to the co-routine should never\r
76 contain more than one item as the same co-routine is used to trigger the I2C\r
77 activity. */\r
78 #define mainQUEUE_LENGTH 1\r
79 \r
80 /* The CrossFire board contains a tri-colour LED. */\r
81 #define mainNUM_LEDs    3\r
82 \r
83 /* The I2C co-routine has a higher priority than the flash co-routines.  This\r
84 is not really necessary as when the I2C co-routine is active the other \r
85 co-routines are delaying. */\r
86 #define mainI2c_CO_ROUTINE_PRIORITY 1\r
87 \r
88 \r
89 /* The current state of the I2C master. */\r
90 static volatile unsigned portBASE_TYPE uxState = mainI2C_IDLE;\r
91 \r
92 /* The delay period derived from the A2D value. */\r
93 static volatile portBASE_TYPE uxDelay = 250;\r
94 \r
95 /* The queue used to communicate between the I2C interrupt and the I2C \r
96 co-routine. */\r
97 static QueueHandle_t xADCQueue;\r
98 \r
99 /* The queue used to synchronise the flash co-routines. */\r
100 static QueueHandle_t xDelayQueue;\r
101 \r
102 /*\r
103  * Sets up the PLL, I2C and GPIO used by the demo.\r
104  */\r
105 static void prvSetupHardware( void );\r
106 \r
107 /* The co-routines as described at the top of the file. */\r
108 static void vI2CCoRoutine( CoRoutineHandle_t xHandle, unsigned portBASE_TYPE uxIndex );\r
109 static void vFlashCoRoutine( CoRoutineHandle_t xHandle, unsigned portBASE_TYPE uxIndex );\r
110 \r
111 /*-----------------------------------------------------------*/\r
112 \r
113 int main( void )\r
114 {\r
115 unsigned portBASE_TYPE uxCoRoutine;\r
116 \r
117         /* Setup all the hardware used by this demo. */\r
118         prvSetupHardware();\r
119 \r
120         /* Create the queue used to communicate between the ISR and I2C co-routine.\r
121         This can only ever contain one value. */\r
122         xADCQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( TickType_t ) );\r
123 \r
124         /* Create the queue used to synchronise the flash co-routines.  The queue\r
125         is used to trigger three tasks, but is for synchronisation only and does\r
126         not pass any data.  It therefore has three position each of zero length. */\r
127         xDelayQueue = xQueueCreate( mainNUM_LEDs, mainZERO_LENGTH );\r
128 \r
129         /* Create the co-routine that initiates the i2c. */\r
130         xCoRoutineCreate( vI2CCoRoutine, mainI2c_CO_ROUTINE_PRIORITY, 0 );\r
131 \r
132         /* Create the flash co-routines. */\r
133         for( uxCoRoutine = 0; uxCoRoutine < mainNUM_LEDs; uxCoRoutine++ )\r
134         {\r
135                 xCoRoutineCreate( vFlashCoRoutine, tskIDLE_PRIORITY, uxCoRoutine );        \r
136         }\r
137 \r
138         /* Start the scheduler.  From this point on the co-routines should \r
139         execute. */\r
140         vTaskStartScheduler();\r
141 \r
142         /* Should not get here unless we did not have enough memory to start the\r
143         scheduler. */\r
144         for( ;; );\r
145         return 0;\r
146 }\r
147 /*-----------------------------------------------------------*/\r
148 \r
149 static void prvSetupHardware( void )\r
150 {\r
151         /* Setup the PLL. */\r
152         SysCtlClockSet( SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_6MHZ );\r
153 \r
154         /* Enable the I2C used to read the pot. */\r
155         SysCtlPeripheralEnable( SYSCTL_PERIPH_I2C );\r
156         SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOB );\r
157         GPIOPinTypeI2C( GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3 );\r
158 \r
159         /* Initialize the I2C master. */\r
160         I2CMasterInit( I2C_MASTER_BASE, pdFALSE );\r
161         \r
162         /* Enable the I2C master interrupt. */\r
163         I2CMasterIntEnable( I2C_MASTER_BASE );\r
164     IntEnable( INT_I2C );\r
165 \r
166         /* Initialise the hardware used to talk to the LED's. */\r
167         vParTestInitialise();\r
168 }\r
169 /*-----------------------------------------------------------*/\r
170 \r
171 static void vI2CCoRoutine( CoRoutineHandle_t xHandle, unsigned portBASE_TYPE uxIndex )\r
172 {\r
173 TickType_t xADCResult;\r
174 static portBASE_TYPE xResult = 0, xMilliSecs, xLED;\r
175 \r
176         crSTART( xHandle );\r
177 \r
178         for( ;; )\r
179         {\r
180                 /* Start the I2C off to read the ADC. */\r
181                 uxState = mainI2C_READ_1;\r
182                 I2CMasterSlaveAddrSet( I2C_MASTER_BASE, mainI2CAddress, pdTRUE );               \r
183                 I2CMasterControl( I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START );\r
184 \r
185                 /* Wait to receive the conversion result. */\r
186                 crQUEUE_RECEIVE( xHandle, xADCQueue, &xADCResult, portMAX_DELAY, &xResult );\r
187 \r
188                 /* Scale the result to give a useful range of values for a visual \r
189                 demo. */\r
190                 xADCResult >>= 2;\r
191                 xMilliSecs = xADCResult / portTICK_PERIOD_MS;\r
192 \r
193                 /* The delay is split between the four co-routines so they remain in\r
194                 synch. */\r
195                 uxDelay = xMilliSecs / ( mainNUM_LEDs + 1 );\r
196 \r
197                 /* Trigger each of the flash co-routines. */\r
198                 for( xLED = 0; xLED < mainNUM_LEDs; xLED++ )\r
199                 {\r
200                         crQUEUE_SEND( xHandle, xDelayQueue, &xLED, 0, &xResult );\r
201                 }\r
202 \r
203                 /* Wait for the full delay time then start again.  This delay is long \r
204                 enough to ensure the flash co-routines have done their thing and gone\r
205                 back to sleep. */\r
206                 crDELAY( xHandle, xMilliSecs );\r
207         }\r
208 \r
209         crEND();\r
210 }\r
211 /*-----------------------------------------------------------*/\r
212 \r
213 static void vFlashCoRoutine( CoRoutineHandle_t xHandle, unsigned portBASE_TYPE uxIndex )\r
214 {\r
215 portBASE_TYPE xResult, xNothing;\r
216 \r
217         crSTART( xHandle );\r
218 \r
219         for( ;; )\r
220         {\r
221                 /* Wait for start of next round. */\r
222                 crQUEUE_RECEIVE( xHandle, xDelayQueue, &xNothing, portMAX_DELAY, &xResult );\r
223 \r
224                 /* Wait until it is this co-routines turn to flash. */\r
225                 crDELAY( xHandle, uxDelay * uxIndex );\r
226 \r
227                 /* Turn on the LED for a fixed period. */\r
228                 vParTestSetLED( uxIndex, pdTRUE );\r
229                 crDELAY( xHandle, uxDelay );\r
230                 vParTestSetLED( uxIndex, pdFALSE );\r
231 \r
232                 /* Go back and wait for the next round. */\r
233         }\r
234 \r
235         crEND();\r
236 }\r
237 /*-----------------------------------------------------------*/\r
238 \r
239 void vI2C_ISR(void)\r
240 {\r
241 static TickType_t xReading;\r
242 \r
243         /* Clear the interrupt. */\r
244         I2CMasterIntClear( I2C_MASTER_BASE );\r
245 \r
246         /* Determine what to do based on the current uxState. */\r
247         switch (uxState)\r
248         {\r
249                 case mainI2C_IDLE:              break;\r
250         \r
251                 case mainI2C_READ_1:    /* Read ADC result high byte. */\r
252                                                                 xReading = I2CMasterDataGet( I2C_MASTER_BASE );\r
253                                                                 xReading <<= 8;\r
254                 \r
255                                                                 /* Continue the burst read. */\r
256                                                                 I2CMasterControl( I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT );\r
257                                                                 uxState = mainI2C_READ_2;\r
258                                                                 break;\r
259         \r
260                 case mainI2C_READ_2:    /* Read ADC result low byte. */\r
261                                                                 xReading |= I2CMasterDataGet( I2C_MASTER_BASE );                                                                \r
262                         \r
263                                                                 /* Finish the burst read. */\r
264                                                                 I2CMasterControl( I2C_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH );\r
265                                                                 uxState = mainI2C_READ_DONE;\r
266                                                                 break;\r
267                         \r
268                 case mainI2C_READ_DONE: /* Complete. */\r
269                                                                 I2CMasterDataGet( I2C_MASTER_BASE );\r
270                                                                 uxState = mainI2C_IDLE;\r
271 \r
272                                                                 /* Send the result to the co-routine. */\r
273                                 crQUEUE_SEND_FROM_ISR( xADCQueue, &xReading, pdFALSE );\r
274                                                                 break;\r
275         }\r
276 }\r
277 /*-----------------------------------------------------------*/\r
278 \r
279 void vApplicationIdleHook( void )\r
280 {\r
281         for( ;; )\r
282         {\r
283                 vCoRoutineSchedule();\r
284         }\r
285 }\r
286 \r