Subversion Repositories svn.mios32

Rev

Rev 1165 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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