Since it is possible to send data with different QoS using a single bulk endpoint, you might want to prioritize the transfers by their QoS latency (medium latency transfers processed before high latency transfers, for instance). This kind of prioritization is implemented inside PHDC µC/OS-II and µC/OS-III RTOS layer. Table - QoS Based Scheduler Priority Values shows the priority value associated with each QoS latency (the lowest priority value will be treated first).
QoS latency | QoS based scheduler associated priority |
---|---|
Very high latency | 3 |
High latency | 2 |
Medium latency | 1 |
For instance, let’s say that your application has 3 tasks. Task A has an OS priority of 1, task B has an OS priority of 2 and task C has an OS priority of 3. Note that a low priority number indicates a high priority task. Now say that all 3 tasks want to write PHDC data of different QoS latency. Task A wants to write data that can have very high latency, task B wants to write data that can have medium latency, and finally, task C wants to write data that can have high latency. Table - QoS-Based Scheduling Example shows a summary of the tasks involved in this example.
Task | QoS latency of data to write | OS priority | QoS priority of data to write |
---|---|---|---|
A | Very high | 1 | 3 |
B | Medium | 2 | 1 |
C | High | 3 | 2 |
If no QoS based priority management is implemented, the OS will then resume the tasks in the order of their OS priority. In this example, the task that has the higher OS priority, A, will be resumed first. However, that task wants to write data that can have very high latency (QoS priority of 3). A better choice would be to resume task B first, which wants to send data that can have medium latency (QoS priority of 1). Figure - Task Execution Order, Without QoS Based Scheduling and Figure - Task Execution Order, with QoS Based Scheduling represent this example without and with a QoS-based scheduler, respectively.
(1)
(2)
(3) A task currently holds the lock on the write bulk endpoint, task A, B and C are added to the wait list until the lock is released.
(4) The lock has been released. The QoS based scheduler’s task is resumed, and finds the task that should be resumed first (according to the QoS of the data it wants to send). Task B is resumed.
(5) Task B completes its execution and releases the lock on the pipe. This resumes the scheduler’s task.
(6) Again, the QoS based scheduler finds the next task that should be resumed. Task C is resumed.
(7) Task C has completed its execution and releases the lock. Scheduler task is resumed and determines that task A is the next one to be resumed.
The QoS-based scheduler is implemented in the RTOS layer. Three functions are involved in the execution of the scheduler.
Function name | Called by | Operation |
---|---|---|
USBD_PHDC_OS_WrBulkLock() | USBD_PHDC_Wr() or USBD_PHDC_PreambleWr() , depending if preambles are enabled or not. | Locks write bulk pipe. |
USBD_PHDC_OS_WrBulkUnlock() | USBD_PHDC_Wr() . | Unlocks write bulk pipe. |
USBD_PHDC_OS_WrBulkSchedTask() | N/A. | Determines next task to resume. |
The pseudocode for these three functions is shown in the three following listings.
void USBD_PHDC_OS_WrBulkLock (CPU_INT08U class_nbr, CPU_INT08U prio, CPU_INT16U timeout_ms, USBD_ERR *p_err) { Increment transfer count of given priority (QoS); Post scheduler lock semaphore; Pend on priority specific semaphore; Decrement transfer count of given priority (QoS); }
void USBD_PHDC_OS_WrBulkUnlock (CPU_INT08U class_nbr) { Post scheduler release semaphore; }
static void USBD_PHDC_OS_WrBulkSchedTask (void *p_arg) { Pend on scheduler lock semaphore; Get next highest QoS ready; PostSem(SemList[QoS]); Pend on scheduler release semaphore; }