]> begriffs open source - cmsis-freertos/blob - Demo/MB96350_Softune_Dice_Kit/DiceTask.c
Update cmsis_os2.c
[cmsis-freertos] / Demo / MB96350_Softune_Dice_Kit / DiceTask.c
1 /*
2     FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
3     All rights reserved
4
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
6
7     This file is part of the FreeRTOS distribution.
8
9     FreeRTOS is free software; you can redistribute it and/or modify it under
10     the terms of the GNU General Public License (version 2) as published by the
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
12
13     ***************************************************************************
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<
16     >>!   obliged to provide the source code for proprietary components     !<<
17     >>!   outside of the FreeRTOS kernel.                                   !<<
18     ***************************************************************************
19
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following
23     link: http://www.freertos.org/a00114.html
24
25     ***************************************************************************
26      *                                                                       *
27      *    FreeRTOS provides completely free yet professionally developed,    *
28      *    robust, strictly quality controlled, supported, and cross          *
29      *    platform software that is more than just the market leader, it     *
30      *    is the industry's de facto standard.                               *
31      *                                                                       *
32      *    Help yourself get started quickly while simultaneously helping     *
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *
34      *    tutorial book, reference manual, or both:                          *
35      *    http://www.FreeRTOS.org/Documentation                              *
36      *                                                                       *
37     ***************************************************************************
38
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
40     the FAQ page "My application does not run, what could be wrong?".  Have you
41     defined configASSERT()?
42
43     http://www.FreeRTOS.org/support - In return for receiving this top quality
44     embedded software for free we request you assist our global community by
45     participating in the support forum.
46
47     http://www.FreeRTOS.org/training - Investing in training allows your team to
48     be as productive as possible as early as possible.  Now you can receive
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
50     Ltd, and the world's leading authority on the world's leading RTOS.
51
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.
55
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
58
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
61     licenses offer ticketed support, indemnification and commercial middleware.
62
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety
64     engineered and independently SIL3 certified version for use in safety and
65     mission critical applications that require provable dependability.
66
67     1 tab == 4 spaces!
68 */
69
70
71 /* 
72  * Defines the 'dice' tasks as described at the top of main.c
73  */
74
75
76 /* Kernel includes. */
77 #include "FreeRTOS.h"
78 #include "task.h"
79 #include "semphr.h"
80
81 /* Delays used within the dice functionality.  All delays are defined in milliseconds. */
82 #define diceDELAY_BETWEEN_RANDOM_NUMBERS_ms             ( 20 / portTICK_PERIOD_MS )
83 #define diceSHAKE_TIME                                                  ( ( 2000 / portTICK_PERIOD_MS ) / diceDELAY_BETWEEN_RANDOM_NUMBERS_ms )
84 #define diceSHORT_PAUSE_BEFORE_SHAKE                    ( 250 / portTICK_PERIOD_MS )
85 #define diceDELAY_WHILE_DISPLAYING_RESULT               ( 5000 / portTICK_PERIOD_MS )
86
87 /* Macro to access the display ports. */
88 #define dice7SEG_Value( x )             ( *( pucDisplayOutput[ x ] ) )
89
90 /* Checks the semaphore use to communicate button push events.  A block time
91 can be specified - this is the time to wait for a button push to occur should
92 one have not already occurred. */
93 #define prvButtonHit( ucIndex, xTicksToWait ) xSemaphoreTake( xSemaphores[ ucIndex ], xTicksToWait )
94
95 /* Defines the outputs required for each digit on the display. */
96 static const char cDisplaySegments[ 2 ][ 11 ] =
97 {
98         { 0x48, 0xeb, 0x8c, 0x89, 0x2b, 0x19, 0x18, 0xcb, 0x08, 0x09, 0xf7 }, /* Left display. */
99         { 0xa0, 0xf3, 0xc4, 0xc1, 0x93, 0x89, 0x88, 0xe3, 0x80, 0x81, 0x7f }  /* Right display. */
100 };
101
102 /* The semaphores used to communicate button push events between the button
103 input interrupt handlers and the dice tasks.  Two dice tasks are created so two
104 semaphores are required. */
105 static SemaphoreHandle_t xSemaphores[ 2 ] = { 0 };
106
107 /* Defines the ports used to write to the display.  This variable is defined in
108 partest.c, which contains the LED set/clear/toggle functions. */
109 extern volatile unsigned char *pucDisplayOutput[ 2 ];
110
111 /*-----------------------------------------------------------*/
112
113 /* 
114  * Defines the 'dice' tasks as described at the top of main.c
115  */
116 void vDiceTask( void *pvParameters )
117 {
118 unsigned char ucDiceValue, ucIndex;
119 unsigned long ulDiceRunTime;
120 extern void vSuspendFlashTasks( unsigned char ucIndex, short sSuspendTasks );
121
122
123
124         /* Two instances of this task are created so the task parameter is used
125         to pass in a constant that indicates whether this task is controlling
126         the left side or right side display.  The constant is used as an index
127         into the arrays defined at file scope within this file. */
128         ucIndex = ( unsigned char ) pvParameters;
129         
130         /* A binary semaphore is used to signal button push events.  Create the
131         semaphore before it is used. */
132         vSemaphoreCreateBinary( xSemaphores[ ucIndex ] );
133
134         /* Make sure the semaphore starts in the wanted state - no button pushes 
135         pending. This call will just clear any button pushes that are latched.
136         Passing in 0 as the block time means the call will not wait for any further
137         button pushes but instead return immediately. */
138         prvButtonHit( ucIndex, 0 );
139
140         /* Seed the random number generator. */
141         srand( ( unsigned char ) diceSHAKE_TIME );
142
143
144
145
146         /* Start the task proper.  A loop will be performed each time a button is
147         pushed.  The task will remain in the blocked state (sleeping) until a 
148         button is pushed. */
149         for( ;; )
150         {
151                 /* Wait for a button push.  This task will enter the Blocked state
152                 (will not run again) until after a button has been pushed. */
153                 prvButtonHit( ucIndex, portMAX_DELAY );
154                 
155                 /* The next line will only execute after a button has been pushed -
156                 initialise the variable used to control the time the dice is shaken
157                 for. */
158                 ulDiceRunTime = diceSHAKE_TIME;                         
159
160                 /* Suspend the flash tasks so this task has exclusive access to the
161                 display. */
162                 vSuspendFlashTasks( ucIndex, pdTRUE );
163
164                 /* Clear the display and pause for a short time, before starting to
165                 shake. */
166                 *pucDisplayOutput[ ucIndex ] = 0xff;
167                 vTaskDelay( diceSHORT_PAUSE_BEFORE_SHAKE );
168
169                 /* Keep generating and displaying random numbers until the shake time
170                 expires. */
171                 while( ulDiceRunTime > 0 )
172                 {
173                         ulDiceRunTime--;
174
175                         /* Generate and display a random number. */
176                         ucDiceValue = rand() % 6 + 1;
177                         dice7SEG_Value( ucIndex ) = ( dice7SEG_Value( ucIndex ) | 0xf7 ) & cDisplaySegments[ ucIndex ][ ucDiceValue ];
178
179                         /* Block/sleep for a very short time before generating the next
180                         random number. */
181                         vTaskDelay( diceDELAY_BETWEEN_RANDOM_NUMBERS_ms );
182                 }
183
184
185
186                 /* Clear any button pushes that are pending because a button bounced, or
187                 was pressed while the dice were shaking.  Again a block time of zero is 
188                 used so the function does not wait for any pushes but instead returns
189                 immediately. */
190                 prvButtonHit( ucIndex, 0 );
191
192                 /* Delay for a short while to display the dice shake result.  Use a queue
193                 peek here instead of a vTaskDelay() allows the delay to be interrupted by
194                 a button push.  If a button is pressed xQueuePeek() will return but the
195                 button push will remain pending to be read again at the top of this for
196                 loop.  It is safe to uses a queue function on a semaphore handle as
197                 semaphores are implemented as macros that uses queues, so the two are 
198                 basically the same thing. */
199                 xQueuePeek( xSemaphores[ ucIndex ], NULL, diceDELAY_WHILE_DISPLAYING_RESULT );
200
201                 /* Clear the display then resume the tasks or co-routines that were using
202                 the segments of the display. */
203                 *pucDisplayOutput[ ucIndex ] = 0xff;
204                 vSuspendFlashTasks( ucIndex, pdFALSE );
205         }
206 }
207 /*-----------------------------------------------------------*/
208
209 /* Handler for the SW2 button push interrupt. */
210 __interrupt void vExternalInt8Handler( void )
211 {
212 short sHigherPriorityTaskWoken = pdFALSE;
213
214         /* Reset the interrupt. */
215         EIRR1_ER8 = 0;
216
217         /* Check the semaphore has been created before attempting to use it. */
218         if( xSemaphores[ configLEFT_DISPLAY ] != NULL )
219         {
220                 /* Send a message via the semaphore to the dice task that controls the
221                 left side display.  This will unblock the task if it is blocked waiting
222                 for a button push. */
223                 xSemaphoreGiveFromISR( xSemaphores[ configLEFT_DISPLAY ], &sHigherPriorityTaskWoken );
224         }
225
226         /* If sending the semaphore unblocked a task, and the unblocked task has a
227         priority that is higher than the currently running task, then force a context
228         switch. */
229         if( sHigherPriorityTaskWoken != pdFALSE )
230         {
231                 portYIELD_FROM_ISR();
232         }
233 }
234 /*-----------------------------------------------------------*/
235
236 /* As per vExternalInt8Handler(), but for SW3 and the right side display. */
237 __interrupt void vExternalInt9Handler( void )
238 {
239 short sHigherPriorityTaskWoken = pdFALSE;
240
241         /* Reset the interrupt. */
242         EIRR1_ER9 = 0;
243
244         if( xSemaphores[ configRIGHT_DISPLAY ] != NULL )
245         {
246                 xSemaphoreGiveFromISR( xSemaphores[ configRIGHT_DISPLAY ], &sHigherPriorityTaskWoken );
247         }
248
249         if( sHigherPriorityTaskWoken != pdFALSE )
250         {
251                 portYIELD_FROM_ISR();
252         }
253 }
254
255
256
257
258
259
260