Rev 1906 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1334 | tk | 1 | // $Id: tasks.c 2425 2016-11-03 00:44:22Z tk $ |
2 | /* |
||
3 | * FreeRTOS Tasks |
||
4 | * only used by MIOS32 build, as a Cocoa based Task handling is used on MacOS |
||
5 | * |
||
6 | * ========================================================================== |
||
7 | * |
||
8 | * Copyright (C) 2008 Thorsten Klose (tk@midibox.org) |
||
9 | * Licensed for personal non-commercial use only. |
||
10 | * All other rights reserved. |
||
11 | * |
||
12 | * ========================================================================== |
||
13 | */ |
||
14 | |||
15 | ///////////////////////////////////////////////////////////////////////////// |
||
16 | // Include files |
||
17 | ///////////////////////////////////////////////////////////////////////////// |
||
18 | |||
19 | #include <mios32.h> |
||
20 | |||
21 | #include "app.h" |
||
22 | #include "tasks.h" |
||
23 | |||
24 | #include <msd.h> |
||
25 | |||
26 | |||
27 | |||
28 | ///////////////////////////////////////////////////////////////////////////// |
||
29 | // Global variables |
||
30 | ///////////////////////////////////////////////////////////////////////////// |
||
31 | |||
32 | // for mutual exclusive SD Card access between different tasks |
||
33 | // The mutex is handled with MUTEX_SDCARD_TAKE and MUTEX_SDCARD_GIVE |
||
34 | // macros inside the application, which contain a different implementation |
||
35 | // for emulation |
||
36 | xSemaphoreHandle xSDCardSemaphore; |
||
37 | |||
38 | // Mutex for MIDI IN/OUT handler |
||
39 | xSemaphoreHandle xMIDIINSemaphore; |
||
40 | xSemaphoreHandle xMIDIOUTSemaphore; |
||
41 | |||
42 | // Mutex for LCD access |
||
43 | xSemaphoreHandle xLCDSemaphore; |
||
44 | |||
45 | |||
46 | ///////////////////////////////////////////////////////////////////////////// |
||
47 | // Local types |
||
48 | ///////////////////////////////////////////////////////////////////////////// |
||
49 | |||
50 | typedef enum { |
||
51 | MSD_DISABLED, |
||
52 | MSD_INIT, |
||
53 | MSD_READY, |
||
54 | MSD_SHUTDOWN |
||
55 | } msd_state_t; |
||
56 | |||
57 | |||
58 | ///////////////////////////////////////////////////////////////////////////// |
||
59 | // Local definitions |
||
60 | ///////////////////////////////////////////////////////////////////////////// |
||
61 | |||
62 | #define PRIORITY_TASK_PERIOD_1mS ( tskIDLE_PRIORITY + 3 ) |
||
63 | #define PRIORITY_TASK_PERIOD_1mS_LP ( tskIDLE_PRIORITY + 2 ) |
||
1905 | tk | 64 | #define PRIORITY_TASK_PERIOD_1mS_LP2 ( tskIDLE_PRIORITY + 1 ) |
1334 | tk | 65 | #define PRIORITY_TASK_PERIOD_1mS_SD ( tskIDLE_PRIORITY + 2 ) |
66 | |||
67 | // local prototype of the task function |
||
68 | static void TASK_Period_1mS(void *pvParameters); |
||
69 | static void TASK_Period_1mS_LP(void *pvParameters); |
||
1905 | tk | 70 | static void TASK_Period_1mS_LP2(void *pvParameters); |
1334 | tk | 71 | static void TASK_Period_1mS_SD(void *pvParameters); |
72 | |||
73 | |||
74 | ///////////////////////////////////////////////////////////////////////////// |
||
75 | // Local variables |
||
76 | ///////////////////////////////////////////////////////////////////////////// |
||
77 | |||
78 | static volatile msd_state_t msd_state; |
||
79 | |||
80 | |||
81 | ///////////////////////////////////////////////////////////////////////////// |
||
82 | // Initialize all tasks |
||
83 | ///////////////////////////////////////////////////////////////////////////// |
||
84 | s32 TASKS_Init(u32 mode) |
||
85 | { |
||
86 | // disable MSD by default (has to be enabled in SID_UI_FILE menu) |
||
87 | msd_state = MSD_DISABLED; |
||
88 | |||
89 | // create semaphores |
||
90 | xSDCardSemaphore = xSemaphoreCreateRecursiveMutex(); |
||
91 | xMIDIINSemaphore = xSemaphoreCreateRecursiveMutex(); |
||
92 | xMIDIOUTSemaphore = xSemaphoreCreateRecursiveMutex(); |
||
1905 | tk | 93 | xLCDSemaphore = xSemaphoreCreateRecursiveMutex(); |
1334 | tk | 94 | |
95 | // start tasks |
||
2425 | tk | 96 | xTaskCreate(TASK_Period_1mS, "1mS", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_PERIOD_1mS, NULL); |
97 | xTaskCreate(TASK_Period_1mS_LP, "1mS_LP", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_PERIOD_1mS_LP, NULL); |
||
98 | xTaskCreate(TASK_Period_1mS_LP2, "1mS_LP2", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_PERIOD_1mS_LP2, NULL); |
||
99 | xTaskCreate(TASK_Period_1mS_SD, "1mS_SD", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_PERIOD_1mS_SD, NULL); |
||
1334 | tk | 100 | |
101 | return 0; // no error |
||
102 | } |
||
103 | |||
104 | |||
105 | ///////////////////////////////////////////////////////////////////////////// |
||
106 | // This task is called periodically each mS |
||
107 | ///////////////////////////////////////////////////////////////////////////// |
||
108 | static void TASK_Period_1mS(void *pvParameters) |
||
109 | { |
||
110 | portTickType xLastExecutionTime; |
||
111 | |||
112 | // Initialise the xLastExecutionTime variable on task entry |
||
113 | xLastExecutionTime = xTaskGetTickCount(); |
||
114 | |||
115 | while( 1 ) { |
||
116 | vTaskDelayUntil(&xLastExecutionTime, 1 / portTICK_RATE_MS); |
||
117 | |||
118 | // skip delay gap if we had to wait for more than 5 ticks to avoid |
||
119 | // unnecessary repeats until xLastExecutionTime reached xTaskGetTickCount() again |
||
120 | portTickType xCurrentTickCount = xTaskGetTickCount(); |
||
121 | if( xLastExecutionTime < (xCurrentTickCount-5) ) |
||
122 | xLastExecutionTime = xCurrentTickCount; |
||
123 | |||
124 | // continue in application hook |
||
125 | APP_TASK_Period_1mS(); |
||
126 | } |
||
127 | } |
||
128 | |||
129 | |||
130 | ///////////////////////////////////////////////////////////////////////////// |
||
131 | // This task handles the SD Card |
||
132 | ///////////////////////////////////////////////////////////////////////////// |
||
133 | static void TASK_Period_1mS_SD(void *pvParameters) |
||
134 | { |
||
135 | u8 lun_available = 0; |
||
136 | |||
137 | while( 1 ) { |
||
138 | vTaskDelay(1 / portTICK_RATE_MS); |
||
139 | |||
140 | if( msd_state == MSD_DISABLED ) { |
||
141 | APP_TASK_Period_1mS_SD(); |
||
142 | } else { |
||
143 | // MSD driver |
||
144 | MUTEX_SDCARD_TAKE; |
||
145 | |||
146 | switch( msd_state ) { |
||
147 | case MSD_SHUTDOWN: |
||
148 | // switch back to USB MIDI |
||
149 | MIOS32_USB_Init(1); |
||
150 | msd_state = MSD_DISABLED; |
||
151 | break; |
||
152 | |||
153 | case MSD_INIT: |
||
154 | // LUN not mounted yet |
||
155 | lun_available = 0; |
||
156 | |||
157 | // enable MSD USB driver |
||
158 | //MUTEX_J16_TAKE; |
||
159 | if( MSD_Init(0) >= 0 ) |
||
160 | msd_state = MSD_READY; |
||
161 | else |
||
162 | msd_state = MSD_SHUTDOWN; |
||
163 | //MUTEX_J16_GIVE; |
||
164 | break; |
||
165 | |||
166 | case MSD_READY: |
||
167 | // service MSD USB driver |
||
168 | MSD_Periodic_mS(); |
||
169 | |||
170 | // this mechanism shuts down the MSD driver if SD card has been unmounted by OS |
||
171 | if( lun_available && !MSD_LUN_AvailableGet(0) ) |
||
172 | msd_state = MSD_SHUTDOWN; |
||
173 | else if( !lun_available && MSD_LUN_AvailableGet(0) ) |
||
174 | lun_available = 1; |
||
175 | break; |
||
176 | } |
||
177 | |||
178 | MUTEX_SDCARD_GIVE; |
||
179 | } |
||
180 | } |
||
181 | } |
||
182 | |||
183 | ///////////////////////////////////////////////////////////////////////////// |
||
184 | // This task is called periodically each mS with low priority |
||
185 | ///////////////////////////////////////////////////////////////////////////// |
||
186 | static void TASK_Period_1mS_LP(void *pvParameters) |
||
187 | { |
||
188 | while( 1 ) { |
||
189 | // using vTaskDelay instead of vTaskDelayUntil, since a periodical execution |
||
190 | // isn't required, and this task could be invoked too often if it was blocked |
||
191 | // for a long time |
||
192 | vTaskDelay(1 / portTICK_RATE_MS); |
||
193 | |||
194 | // continue in application hook |
||
195 | APP_TASK_Period_1mS_LP(); |
||
196 | } |
||
197 | } |
||
198 | |||
199 | |||
200 | ///////////////////////////////////////////////////////////////////////////// |
||
1905 | tk | 201 | // This task is called periodically each mS with very low priority |
202 | ///////////////////////////////////////////////////////////////////////////// |
||
203 | static void TASK_Period_1mS_LP2(void *pvParameters) |
||
204 | { |
||
205 | while( 1 ) { |
||
206 | // using vTaskDelay instead of vTaskDelayUntil, since a periodical execution |
||
207 | // isn't required, and this task could be invoked too often if it was blocked |
||
208 | // for a long time |
||
209 | vTaskDelay(1 / portTICK_RATE_MS); |
||
210 | |||
211 | // continue in application hook |
||
212 | APP_TASK_Period_1mS_LP2(); |
||
213 | } |
||
214 | } |
||
215 | |||
216 | |||
217 | ///////////////////////////////////////////////////////////////////////////// |
||
1334 | tk | 218 | // MSD access functions |
219 | ///////////////////////////////////////////////////////////////////////////// |
||
220 | s32 TASK_MSD_EnableSet(u8 enable) |
||
221 | { |
||
222 | MIOS32_IRQ_Disable(); |
||
223 | if( msd_state == MSD_DISABLED && enable ) { |
||
224 | msd_state = MSD_INIT; |
||
225 | } else if( msd_state == MSD_READY && !enable ) |
||
226 | msd_state = MSD_SHUTDOWN; |
||
227 | MIOS32_IRQ_Enable(); |
||
228 | |||
229 | return 0; // no error |
||
230 | } |
||
231 | |||
232 | s32 TASK_MSD_EnableGet() |
||
233 | { |
||
234 | return (msd_state == MSD_READY) ? 1 : 0; |
||
235 | } |
||
236 | |||
237 | s32 TASK_MSD_FlagStrGet(char str[5]) |
||
238 | { |
||
239 | str[0] = MSD_CheckAvailable() ? 'U' : '-'; |
||
240 | str[1] = MSD_LUN_AvailableGet(0) ? 'M' : '-'; |
||
241 | str[2] = MSD_RdLEDGet(250) ? 'R' : '-'; |
||
242 | str[3] = MSD_WrLEDGet(250) ? 'W' : '-'; |
||
243 | str[4] = 0; |
||
244 | |||
245 | return 0; // no error |
||
246 | } |