SAMPScheduler.c
上传用户:super_houu
上传日期:2008-09-21
资源大小:4099k
文件大小:35k
源码类别:

DVD

开发平台:

Others

  1. #include "Config.h" // Global Configuration - do not remove!
  2. // *****************************************************************************
  3. // * Define debug messages condition
  4. // * has to be define before "SysDefs.h"
  5. // *****************************************************************************
  6. #if D_SUPPORT_SACD // ZKR GLSACD
  7. //#define _DEBUG_SCHEDULER
  8. #ifdef _DEBUG_SCHEDULER
  9. #define _DEBUG_TASK_SWITCH
  10. #endif
  11. #include <embedded.h>
  12. #include "IncludeSysDefs.h"
  13. #include "PlaycoreCoremaincoremain.h"
  14. #include "Playcoretimingtiming.h"
  15. #include "KerneluITRONrtos.h"
  16. #include "KernelKer_API.h"
  17. #include "KernelEventDef.h"
  18. #include "PlaycoreScPadScPadAlloc.h"
  19. #include "CPUtimefunc.h"
  20. #include "Playcorecoremaincoregdef.h"
  21. #include "PlaycoreSAMPschedulerSAMPScheduler.h"
  22. #include "decoderlow_leveldec_ll_reg.h"
  23. extern int SACD_Navigator(HDLR_OP Op, EVENT Event, void *Param);
  24. //JERRYC_2004AUG24
  25. extern UINT32 Ker_GetCoreStackBottom(void);
  26. typedef void (_far *LPSACDTIMERPROC)(void);
  27. #ifdef dbg_printf
  28. #undef dbg_printf
  29. #define dbg_printf(sMsg) printf ## sMsg
  30. #endif
  31. // *****************************************************************************
  32. // * SACD task scheduler
  33. // * Implemented features: TASKSWITCH,SEMAPHORES,MAILBOXES
  34. // *****************************************************************************
  35. // *****************************************************************************
  36. // * Constant definition
  37. // *****************************************************************************
  38. //definition of allocated memory in SDRAM for tasks stack
  39. #define SDRAM_STACK_SIZE 2048ul   //BYTE
  40. #define SDRAM_STACK_BASE (SC_CLIPSDIR1_LIST_ADDRESS << 1)
  41. //staticly allocated resources definition
  42. #define NUMBER_OF_TASKS 6
  43. #define NUMBER_OF_SEMAPHORES 13
  44. #define NUMBER_OF_MAILBOXES 8
  45. //ID of scheduler task
  46. #define TASK_ID_SCHEDULER NUMBER_OF_TASKS
  47. //definition of uninitialized semaphor counter
  48. #define SEMAPHORE_UNINITIALIZED 0xFFFF
  49. // *****************************************************************************
  50. // * External referencies
  51. // *****************************************************************************
  52. extern void SAMP_API_Handler (UINT32 param);
  53. // *****************************************************************************
  54. // * Global variable
  55. // *****************************************************************************
  56. int SchedulerID = -1;
  57. //keeps id of active task
  58. static IDENT currentTask;
  59. #define CUR_TASK currentTask
  60. //initial level of core tasks stack (offset part only)
  61. static UINT16 initialStack;
  62. #define INITIAL_STACK initialStack
  63. #define TASK (gns.sacd.task)
  64. #define SEMA (gns.sacd.semaphore)
  65. #define MB (gns.sacd.mailbox)
  66. // *****************************************************************************
  67. // * Function prototypes
  68. // *****************************************************************************
  69. static IDENT SchedulerGetReadyTask (void);
  70. static SAMP(ErrCode) TaskSwitch (void);
  71. static int SAMP_Scheduler (HDLR_OP Op, EVENT Event, void *Param);
  72. // *****************************************************************************
  73. // * TASKS handling implementation
  74. // *****************************************************************************
  75. // *****************************************************************************
  76. // * Name: OS_TaskCreate
  77. // * Purpose: Create and start a new task
  78. // * Input: Priority  Priority of the task.
  79. // *  Stacksize  Stack size required by the task.
  80. // *  Entry  The function that gets control when the new task starts
  81. // *  execution.
  82. // * Output: *Id  Unique identification number for the created task.
  83. // * Returns: SAMP(ERR_OK)  Operation successful.
  84. // *    ERR_UNKNOWN Unknown internal failure.
  85. // * Description: Create a new task with the given priority and stack size and
  86. // * start it at the entry point. The task Id is returned. There are eight
  87. // * different task priorities required by SA-MP. They are specified by the
  88. // * integer numbers 0, 1, 2, ... 7 where 0 is the lowest possible priority
  89. // * and 7 is the highest. Note that these priorities must be mapped by the OSA
  90. // * to some suitable set of priorities for the underlying operating system.
  91. // * Tasks running at priority 0 will have a higher priority than the idle task
  92. // * of the underlying operating system.
  93. // *****************************************************************************
  94. SAMP(ErrCode) SAMP(OS_TaskCreate) (PRIORITY Priority, size_t Stacksize, void(*Entry)(void),IDENT *Id)
  95. {
  96. TASK_CONTEXT taskContext;
  97.    TCB *taskPtr;
  98. #ifdef _DEBUG_SCHEDULER
  99. dbg_printf (("SCHEDULER(%i) TaskCreate",CUR_TASK));
  100. //   SAMP(TH_Send)("SCHEDULER ", "TaskCreate by:", "%u", CUR_TASK);
  101. #endif
  102. //test if the priority doesnot exccedes number of tasks
  103. if (Priority >= NUMBER_OF_TASKS) return SAMP(ERR_UNKNOWN);
  104. //assume that number of tasks is equal to number of priorities minus one
  105.    //the id sets the level of priority, higher id - lower priority
  106.    *Id = NUMBER_OF_TASKS - Priority - 1;
  107. taskPtr = &(TASK[*Id]);
  108.    if (taskPtr->Status != TASK_NOT_STARTED) return SAMP(ERR_UNKNOWN);
  109. #ifdef _DEBUG_SCHEDULER
  110. dbg_printf (("(%i)n",*Id));
  111. //   SAMP(TH_Send)("SCHEDULER ", "TaskCreate new:", "%u", *Id);
  112. #endif
  113.    //initialize task stack in SDRAM
  114. taskContext.task = Entry;
  115.    //initializa first stack offset after task switch
  116.    taskPtr->StackOff = INITIAL_STACK - sizeof(TASK_CONTEXT);
  117.    wai_sem(SEM_DRAM_ID);
  118.    {
  119.     UINT8 * addr = (UINT8 *)(&taskContext);
  120.     if(sizeof(TASK_CONTEXT)%2) //odd
  121.      addr -= 1;
  122.     I49_WriteDRAMDataNSW (taskPtr->SDRAMStackAddr,(UINT16*)addr,(sizeof(TASK_CONTEXT) + 1)/2);
  123.    }
  124.    sig_sem(SEM_DRAM_ID);
  125. //change task status
  126. taskPtr->Status = TASK_STATUS_READY;
  127.    return TaskSwitch ();
  128. }
  129. // *****************************************************************************
  130. // * Name: OS_TaskDelete
  131. // * Purpose: Stop and delete a task.
  132. // * Input: Id  Identification number of the task as was returned on
  133. // *  OS_TaskCreate().
  134. // * Returns:  SAMP(ERR_OK) Operation successful.
  135. // *  SAMP(ERR_UNKNOWN) Unknown internal failure.
  136. // * Description: See purpose.
  137. // * Note: The task Id will be invalidated by this function. A new call to
  138. // * OS_TaskCreate() for the same entry-function may or may not return the same
  139. // * value.
  140. // *****************************************************************************
  141. SAMP(ErrCode) SAMP(OS_TaskDelete) (IDENT Id)
  142. {
  143. dbg_printf (("SCHEDULER(%i) TaskDelete",CUR_TASK));
  144.    dbg_printf (("(%i)n",Id));
  145. //   SAMP(TH_Send)("SCHEDULER ", "TaskDelete ID:", "%u", Id);
  146. //cannot delete task that is curently running
  147. if (CUR_TASK == Id) return SAMP(ERR_UNKNOWN);
  148.    //invalidate the task
  149. TASK[Id].Status = TASK_NOT_STARTED;
  150.    return SAMP(ERR_OK);
  151. }
  152. // *****************************************************************************
  153. // * SEMAPHORES implementation
  154. // *****************************************************************************
  155. // *****************************************************************************
  156. // * Name: OS_SemCreate
  157. // * Purpose: Create a new counting semaphore.
  158. // * Input: Units  The initial amount of units in the semaphore.
  159. // * Ouput: *Id    Unique identification number for the created semaphore.
  160. // * Returns:  SAMP(ERR_OK) Operation successful.
  161. // *  SAMP(ERR_UNKNOWN) Unknown internal failure.
  162. // * Precondition: (Units=0(Units=1)
  163. // * Description: Create a new counting semaphore and return the semaphore Id.
  164. // *****************************************************************************
  165. SAMP(ErrCode) SAMP(OS_SemCreate) (UNITS Units,IDENT *Id)
  166. {
  167. IDENT id;
  168. #ifdef _DEBUG_SCHEDULER
  169. dbg_printf (("SCHEDULER(%i) SemaphoreCreate",CUR_TASK));
  170. //   SAMP(TH_Send)("SCHEDULER ", "SemaphoreCreate by task:", "%u", CUR_TASK);
  171. #endif
  172. for (id = 0; id < NUMBER_OF_SEMAPHORES; id++)
  173.    {
  174. if (SEMA[id] == SEMAPHORE_UNINITIALIZED)
  175.       {
  176.        SEMA[id] = Units;
  177.          *Id = id;
  178. #ifdef _DEBUG_SCHEDULER
  179.          dbg_printf (("(%i)n",id));
  180. #endif
  181.        return SAMP(ERR_OK);
  182.       }
  183.    }
  184.    dbg_printf (("Errorn"));
  185. //   SAMP(TH_Send)("SCHEDULER ", "SemaphoreCreate:", "%s", "Errorn");
  186.    return SAMP(ERR_UNKNOWN);
  187. }
  188. // *****************************************************************************
  189. // * Name: OS_SemDelete
  190. // * Purpose: Delete a semaphore.
  191. // * Input: Id  Identification number of the semaphore as was returned
  192. // *  on OS_SemCreate().
  193. // * Returns:  SAMP(ERR_OK) Operation successful.
  194. // *  SAMP(ERR_UNKNOWN) Unknown internal failure.
  195. // * Description: Delete the semaphore associated with Id.
  196. // * Note: The semaphore Id will be invalidated by this function.
  197. // *****************************************************************************
  198. SAMP(ErrCode) SAMP(OS_SemDelete)(IDENT Id)
  199. {
  200. dbg_printf (("SCHEDULER(%i) SemaphoreDelete",CUR_TASK));
  201.    dbg_printf (("(%i)n",Id));
  202. //   SAMP(TH_Send)("SCHEDULER ", "SemaphoreDelete: task - sem", "%u%u", CUR_TASK, Id);
  203.    if (Id >= NUMBER_OF_SEMAPHORES) return SAMP(ERR_UNKNOWN);
  204. SEMA[Id] = SEMAPHORE_UNINITIALIZED;
  205.    return SAMP(ERR_OK);
  206. }
  207. // *****************************************************************************
  208. // * Name: OS_SemP
  209. // * Purpose: Take a unit from a semaphore.
  210. // * Input: Id  Identification number of the semaphore.
  211. // *     Timeout  The maximum time to wait for a unit to become available.
  212. // * Returns: SAMP(ERR_OK)  Operation successful.
  213. // *    ERR_FAILED No unit available (after waiting).
  214. // *    SAMP(ERR_UNKNOWN)  Unknown internal failure.
  215. // * Description: Obtain a unit from the semaphore associated with Id but don't
  216. // * wait more than Timeout centiseconds for it. If a unit is available, take it
  217. // * and return. If Timeout is OS_FOREVER, wait until an unit becomes
  218. // * available. If Timeout is 0, return immediately. If the time-out elapses
  219. // * while waiting for a unit, return ERR_FAILED. Waiting tasks are queued by
  220. // * priority, that is the highest priority task waiting will get the next
  221. // * available unit.
  222. // *****************************************************************************
  223. SAMP(ErrCode) SAMP(OS_SemP) (IDENT Id,TIMEOUT Timeout)
  224. {
  225.    STATUS_REG stReg;
  226.    TCB *taskPtr = &(TASK[CUR_TASK]);
  227. #ifdef _DEBUG_SCHEDULER
  228.    //dbg_printf (("S%i SG",CUR_TASK));
  229.    //dbg_printf (("%in",Id));
  230. //   SAMP(TH_Send)("SCHEDULER ", "SemaphoreGet: task - sem", "%u%u", CUR_TASK, Id);
  231. #endif
  232.    //test if the semaphor is already initialized
  233.    if (SEMA[Id] == SEMAPHORE_UNINITIALIZED) return SAMP(ERR_UNKNOWN);
  234.    //test if the id is correct
  235.    if (Id >= NUMBER_OF_SEMAPHORES) return SAMP(ERR_UNKNOWN);
  236. do
  237.    {
  238.    //test if semaphore unit available
  239. stReg = InterruptDisable ();
  240. if (SEMA[Id])
  241.    {
  242.      SEMA[Id]--;
  243.    set_SR (stReg);
  244. //         dbg_printf (("SCHEDULER(%i) SemaphoreReceivedn",CUR_TASK));  
  245. //         SAMP(TH_Send)("SCHEDULER ", "SemaphoreReceived: task:", "%u", CUR_TASK);
  246.    return SAMP(ERR_OK);
  247.    }
  248.    //semmaphore unit not available at this moment
  249.    
  250.     //test if need to wait for the semaphor
  251.   if (!Timeout)
  252.       {
  253.    set_SR (stReg);
  254.        return SAMP(ERR_FAILED);
  255.       }
  256.       //change task status
  257. taskPtr->Status = TASK_STATUS_WAITING_FOR_SEMAPHORE;
  258.     //save semaphore id, that is the current task waiting for
  259. taskPtr->SemaphoreID = Id;
  260.       set_SR (stReg);
  261. //return execution to task scheduler and wait semaphore unit for to arrive
  262.    }
  263.    while (TaskSwitch () == SAMP(ERR_OK));
  264.    //if we get here there was error in the scheduler
  265.    return SAMP(ERR_FAILED);
  266. }
  267. // *****************************************************************************
  268. // * Name: OS_SemV
  269. // * Purpose: Release a unit to a semaphore.
  270. // * Input: Id  Identification number of the semaphore.
  271. // * Returns:  SAMP(ERR_OK)  Operation successful.
  272. // *  SAMP(ERR_FAILED) No unit available after waiting.
  273. // *  SAMP(ERR_UNKNOWN) Unknown internal failure.
  274. // * Description: Release a unit to semaphore associated with Id.
  275. // *****************************************************************************
  276. SAMP(ErrCode) SAMP(OS_SemV) (IDENT Id)
  277. {
  278.    STATUS_REG stReg;
  279. #ifdef _DEBUG_SCHEDULER
  280. //dbg_printf (("S%i SS",CUR_TASK));
  281.    //dbg_printf (("%in",Id));
  282. //   SAMP(TH_Send)("SCHEDULER ", "SemaphoreSet: task - sem:", "%u%u", CUR_TASK, Id);
  283. #endif
  284.    //test if the semaphor is already initialized
  285.    if (SEMA[Id] == SEMAPHORE_UNINITIALIZED) return SAMP(ERR_UNKNOWN);
  286.    //test if the id is correct
  287.    if (Id >= NUMBER_OF_SEMAPHORES) return SAMP(ERR_UNKNOWN);
  288. stReg = InterruptDisable ();   
  289.    //increment semaphor count
  290.    SEMA[Id]++;
  291.    //test if needs to release task from wait state
  292.    // if (releaseTask)
  293.    {
  294. TCB *taskPtr;
  295.       
  296.       //test if there is task waiting for the semaphore
  297.       for (taskPtr = TASK; taskPtr < (TASK + NUMBER_OF_TASKS); taskPtr++)
  298.       {
  299.          if ((taskPtr->Status == TASK_STATUS_WAITING_FOR_SEMAPHORE) && 
  300.              (taskPtr->SemaphoreID == Id))
  301.          {
  302.             //release task from wait state
  303.             taskPtr->Status = TASK_STATUS_READY;
  304.             set_SR (stReg);
  305.             return TaskSwitch ();
  306.          }
  307.       }
  308.    }
  309.    
  310.    set_SR (stReg);
  311.    return SAMP(ERR_OK);
  312. }
  313. // *****************************************************************************
  314. // * Name: OS_MboxCreate
  315. // * Purpose: Create a new mailbox.
  316. // * Input: Capacity  Maximum number of messages that the maibox can
  317. // *  contain.
  318. // * Output: *Id  Unique identification number for the created mailbox.
  319. // * Returns:  SAMP(ERR_OK)   Operation successful.
  320. // *  SAMP(ERR_UNKNOWN) Unknown internal failure.
  321. // * Description: Create a new mailbox with size Capacity and return the mailbox
  322. // * Id.
  323. // *****************************************************************************
  324. SAMP(ErrCode) SAMP(OS_MboxCreate) (CAPACITY Capacity,IDENT *Id)
  325. {
  326. MAILBOX *mailboxPtr;
  327.    IDENT id;
  328.    if (Capacity > MAX_NUM_OF_MESSAGE)
  329.    {
  330.      Capacity = MAX_NUM_OF_MESSAGE;
  331.    }
  332. #ifdef _DEBUG_SCHEDULER
  333. dbg_printf (("SCHEDULER(%i) MailboxCreate",CUR_TASK));
  334. //   SAMP(TH_Send)("SCHEDULER ", "MailboxCreate: task:", "%u", CUR_TASK);
  335. #endif
  336. //search for available mailbox
  337. for (id = 0; id < NUMBER_OF_MAILBOXES; id++)
  338.    {
  339.     mailboxPtr = &(MB[id]);
  340.     //test if mailbox available
  341. if (mailboxPtr->MessageQueue == NULL)
  342.       {
  343.        //allocate memory for the mailbox on heap
  344.        mailboxPtr->MessageQueue = (MESSAGE*)(SACD_GLOBALS.mailbox_buff[id]); //(MESSAGE*)malloc(MESSAGE_LENGTH * Capacity);
  345. //if no memory available return error
  346.          if (mailboxPtr->MessageQueue == NULL)
  347.          {
  348.           printf ("Fatal! Error no memory availablen");
  349. //            SAMP(TH_Send)("SCHEDULER ", "MailboxCreate: ", "%s", "Error no memory availablen");
  350.           return SAMP(ERR_UNKNOWN);
  351.          }
  352. //initialize mailbox
  353.          memset (mailboxPtr->MessageQueue,0,MESSAGE_LENGTH * Capacity);
  354.          mailboxPtr->Capacity = Capacity;
  355.        mailboxPtr->MessageCount = 0;
  356.          mailboxPtr->WritePointer = 0;
  357.          mailboxPtr->ReadPointer = 0;
  358.          *Id = id;
  359. #ifdef _DEBUG_SCHEDULER
  360.          dbg_printf (("(%i)n",id));
  361. //         SAMP(TH_Send)("SCHEDULER ", "MailboxCreate: id:", "%u", id);
  362. #endif
  363.        return SAMP(ERR_OK);
  364.       }
  365.    }
  366.    //return error - no mailbox is available
  367. dbg_printf (("Errorn"));
  368. //   SAMP(TH_Send)("SCHEDULER ", "MailboxCreate: id:", "%s", "Errorn");
  369.    return SAMP(ERR_UNKNOWN);
  370. }
  371. // *****************************************************************************
  372. // * Name: OS_MboxDelete
  373. // * Purpose: Delete a mailbox.
  374. // * Input: Id  Identification number of the mailbox to be deleted.
  375. // * Returns:  SAMP(ERR_OK)  Operation successful.
  376. // *  SAMP(ERR_UNKNOWN) Unknown internal failure.
  377. // * Description: Delete the mailbox associated with Id.
  378. // * Note: The mailbox Id will be invalidated by this function.
  379. // *****************************************************************************
  380. SAMP(ErrCode) SAMP(OS_MboxDelete) (IDENT Id)
  381. {
  382. dbg_printf (("SCHEDULER(%i) MailboxDelete",CUR_TASK));
  383.    dbg_printf (("(%i)n",Id));
  384. //   SAMP(TH_Send)("SCHEDULER ", "MailboxDelete: task - box", "%u%u", CUR_TASK, Id);
  385. //test validity of mailbox
  386. if (Id >= NUMBER_OF_MAILBOXES) return SAMP(ERR_UNKNOWN);
  387.    //release memory allocated for the mailbox
  388.    if (MB[Id].MessageQueue != NULL)
  389.    {
  390. //    free (MB[Id].MessageQueue);
  391.     MB[Id].MessageQueue = NULL;
  392.    }
  393.    return SAMP(ERR_OK);
  394. }
  395. // *****************************************************************************
  396. // * Name: MessageSend
  397. // * Pupose: Send a message to a mailbox.
  398. // * Input: Id  Identification number of the mailbox.
  399. // *  *Ptr  Pointer to the start of the message.
  400. // *  RelTask 0 - task switch not allowed in this function
  401. // *  other - task switch can happen
  402. // * Returns:  SAMP(ERR_OK) Operation successful.
  403. // *  SAMP(ERR_INVALID_PARAM) Size exceeds maximum message size (12 bytes).
  404. // *  SAMP(ERR_FAILED) Capacity of mailbox exceeded.
  405. // * SAMP(ERR_UNKNOWN) Unknown internal failure.
  406. // * Description: Send a message of Size bytes starting at Ptr to the mailbox
  407. // * associated with Id.
  408. // *****************************************************************************
  409. SAMP(ErrCode) MessageSend (IDENT Id, void * Ptr,size_t Size, BOOL ReleaseTask)
  410. {
  411. STATUS_REG stReg;
  412. MAILBOX *mb = &(MB[Id]);
  413. TCB *taskPtr;
  414. #ifdef _DEBUG_SCHEDULER
  415. //   dbg_printf (("SCHEDULER(%i) MessageSend(%i)n",CUR_TASK,Id));
  416.    dbg_printf (("S%i MS",CUR_TASK));
  417.    dbg_printf (("%in", Id));
  418. //   SAMP(TH_Send)("SCHEDULER ", "MessageSend: task - box", "%u%u", CUR_TASK, Id);
  419. #endif
  420.    //test if mailbox is initialized already
  421.    if (mb->MessageQueue == NULL) return SAMP(ERR_UNKNOWN);
  422.    //test validity of mailobox ID
  423.    if (Id >= NUMBER_OF_MAILBOXES) return SAMP(ERR_UNKNOWN);
  424.    //test message length
  425.    if (Size > MESSAGE_LENGTH) return SAMP(ERR_INVALID_PARAM);
  426. stReg = InterruptDisable ();
  427.    //test if mailbox is full
  428. if (mb->MessageCount >= mb->Capacity)
  429.    {
  430.    set_SR (stReg);
  431.     return SAMP(ERR_FAILED);
  432.    }
  433.    //add message to mailbox
  434. #ifdef _DEBUG_SCHEDULER
  435.    dbg_printf (("WP%in",mb->WritePointer));
  436.    dbg_printf (("MC%in",mb->MessageCount));
  437. #endif
  438.    memcpy (mb->MessageQueue[mb->WritePointer].Message, Ptr, Size);
  439.    mb->MessageCount++;
  440.    if (mb->WritePointer == (mb->Capacity - 1))
  441.    {
  442.      mb->WritePointer = 0;
  443.    }
  444.    else
  445.    {
  446.      mb->WritePointer++;
  447.    }
  448.    //test if there is task waiting for this message
  449.    for (taskPtr = TASK; taskPtr < (TASK + NUMBER_OF_TASKS); taskPtr++)
  450.    {
  451.       if ((taskPtr->Status == TASK_STATUS_WAITING_FOR_MESSAGE) && 
  452.           (taskPtr->MailboxID == Id))
  453.       {
  454.        //release the task from sleep state
  455.         taskPtr->Status = TASK_STATUS_READY;
  456.    set_SR (stReg);
  457.          //test if task switch is allowed
  458.         if (ReleaseTask) return TaskSwitch ();
  459.          //send event in case all task are in sleep state
  460. ie_send_ex(IE_CORE_SAMP_WAKE_UP, (void *)(0));
  461.          return SAMP(ERR_OK);
  462.       }
  463.    }
  464.    set_SR (stReg);
  465.    return SAMP(ERR_OK);
  466. }
  467. // *****************************************************************************
  468. // * Name: OS_SendMsg
  469. // * Pupose: Send a message to a mailbox.
  470. // * Input: Id  Identification number of the mailbox.
  471. // *  *Ptr  Pointer to the start of the message.
  472. // * Returns:  SAMP(ERR_OK) Operation successful.
  473. // *  SAMP(ERR_INVALID_PARAM) Size exceeds maximum message size (12 bytes).
  474. // *  SAMP(ERR_FAILED) Capacity of mailbox exceeded.
  475. // *  SAMP(ERR_UNKNOWN) Unknown internal failure.
  476. // * Description: Send a message of Size bytes starting at Ptr to the mailbox
  477. // * associated with Id.
  478. // *****************************************************************************
  479. SAMP(ErrCode) SAMP(OS_SendMsg) (IDENT Id,void *Ptr,size_t Size)
  480. {
  481. return MessageSend (Id,Ptr,Size,1);
  482. }
  483. // *****************************************************************************
  484. // * Name: OS_ISendMsg
  485. // * Pupose: Send a message from an ISR to a mailbox.
  486. // * Input: Id  Identification number of the mailbox.
  487. // *  Ptr  Pointer to the start of the message.
  488. // * Returns:  SAMP(ERR_OK) Operation successful.
  489. // *  SAMP(ERR_INVALID_PARAM) Size exceeds maximum message size (12 bytes).
  490. // *  SAMP(ERR_FAILED) Capacity of mailbox exceeded.
  491. // *  SAMP(ERR_UNKNOWN) Unknown internal failure.
  492. // * Description: Send a message of Size bytes starting at Ptr to the mailbox
  493. // * associated with Id.
  494. // * The behaviour of this function is identical to OS_SendMsg() but is intended
  495. // * to be called by interrupt service routines only. Interrupt service routines
  496. // * are not allowed to call any other OSA functions.
  497. // *****************************************************************************
  498. SAMP(ErrCode) SAMP(OS_ISendMsg) (IDENT Id,void *Ptr,size_t Size)
  499. {
  500. return MessageSend (Id,Ptr,Size,0) ;
  501. }
  502. // *****************************************************************************
  503. // * Name: OS_RecvMsg
  504. // * Purpose: Receive a message from a mailbox.
  505. // * Input: Id Identification number of the mailbox.
  506. // * Timeout Maximum time to wait for a message to become
  507. // * available.
  508. // * Ptr Pointer to buffer where message will be stored.
  509. // * Size Size of this buffer in bytes.
  510. // * Output: *Msgsize Actual number of bytes stored in the buffer.
  511. // * Returns: SAMP(ERR_OK) Operation successful.
  512. // * SAMP(ERR_FAILED)No message available (after waiting).
  513. // * SAMP(ERR_UNKNOWN) Unknown internal failure.
  514. // * Description: Receive a message from the mailbox Id but don't wait more than
  515. // * Timeout centiseconds for it. If a message is available, the message is
  516. // * copied to the data area of Size bytes starting at Ptr. The actual message
  517. // * size is returned in Msgsize if it is known to the system. Otherwise,
  518. // * Msgsize will be set to Size.
  519. // * If Timeout is OS_FOREVER, wait until an message becomes available. If
  520. // * Timeout is 0, return immediately. If the time-out elapses while waiting for
  521. // * a message, return SAMP(ERR_FAILED).
  522. // * Note: Waiting tasks are queued by priority, that is the highest priority
  523. // * task waiting will get the next available message.
  524. // *****************************************************************************
  525. SAMP(ErrCode) SAMP(OS_RecvMsg) (IDENT Id,TIMEOUT Timeout,void *Ptr,size_t Size,size_t *Msgsize)
  526. {
  527. STATUS_REG stReg;
  528. MAILBOX *mb = &(MB[Id]);
  529.    TCB *taskPtr = &(TASK[CUR_TASK]);
  530. //   UINT16 loopcount = 0;
  531. #ifdef _DEBUG_SCHEDULER
  532.    //dbg_printf (("SCHEDULER(%i) MessageGet(%i)n",CUR_TASK,Id));
  533.    dbg_printf (("S%i MG",CUR_TASK));
  534.    dbg_printf (("%in",Id));
  535. //   SAMP(TH_Send)("SCHEDULER ", "MessageGet: task - box", "%u%u", CUR_TASK, Id);
  536. #endif
  537.    //test if mailbox is initialized already
  538.    if (mb->MessageQueue == NULL) return SAMP(ERR_UNKNOWN);
  539.    //test validity of mailobox ID
  540.    if (Id >= NUMBER_OF_MAILBOXES) return SAMP(ERR_UNKNOWN);
  541.    //size of the message
  542.    *Msgsize = Size;
  543.    do
  544.    {
  545. #if 0
  546.    //sacd todo: check later.
  547.       if(TASK_ID_SCHEDULER == CUR_TASK && loopcount > 1000)
  548.       {
  549.       taskPtr->Status = TASK_STATUS_READY;
  550.        return SAMP(ERR_OK);
  551.       }
  552.       loopcount++;
  553. #endif
  554.       //test if message available in the mailbox
  555.       stReg = InterruptDisable ();
  556.       if (mb->MessageCount)
  557.       {
  558. #ifdef _DEBUG_SCHEDULER
  559.          dbg_printf (("RP%in",mb->ReadPointer));
  560.          dbg_printf (("MC%in",mb->MessageCount));
  561. #endif
  562.        //message available decrement the counter and copy message to dest
  563.          memcpy (Ptr, mb->MessageQueue[mb->ReadPointer].Message, Size);
  564.          mb->MessageCount--;
  565. #if 1
  566.          if (mb->ReadPointer == (mb->Capacity - 1))
  567.          {
  568.            mb->ReadPointer = 0;
  569.          }
  570.          else
  571.          {
  572.            mb->ReadPointer++;
  573.          }
  574. #endif
  575.          set_SR (stReg);
  576. #ifdef _DEBUG_SCHEDULER
  577.          //dbg_printf (("SCHEDULER(%i) MessageReceivedn",CUR_TASK));
  578.          dbg_printf (("S%i MR",CUR_TASK));
  579.          dbg_printf (("%in",Id));
  580. //         SAMP(TH_Send)("SCHEDULER ", "MessageReceived: task:", "%u", CUR_TASK);
  581. #endif
  582.          return SAMP(ERR_OK);
  583.       }
  584.    //message not available in mailbox at this moment
  585.     //test if need to wait for the message
  586.   if (!Timeout)
  587.       {
  588.       set_SR (stReg);
  589.        return SAMP(ERR_FAILED);
  590.       }
  591.       //change task status
  592.       taskPtr->Status = TASK_STATUS_WAITING_FOR_MESSAGE;
  593.       //save mailbox id and message pointer, that is the current task waiting for
  594.       taskPtr->MailboxID = Id;
  595.       set_SR (stReg);
  596. //return execution to task scheduler and wait for message to arrive
  597.    }
  598.    while (TaskSwitch () == SAMP(ERR_OK));
  599.    //if we get here there was error in the scheduler
  600.    return SAMP(ERR_FAILED);
  601. }
  602. // *****************************************************************************
  603. // * Purpose          : get task ID of ready task with highest priority
  604. // * Input Parameters : none
  605. // * Return Value     : SAMP(ERR_OK) - the task switch is succesful
  606. // * Description : the function checks TCB of all tasks and select the task
  607. // *   with highest priority and ready status
  608. // * Comments   :
  609. // *****************************************************************************
  610. static IDENT SchedulerGetReadyTask (void)
  611. {
  612. TCB *taskPtr;
  613. IDENT taskID;
  614. //return the READY task with the highest priority
  615. for (taskPtr = TASK, taskID = 0; taskPtr < (TASK + NUMBER_OF_TASKS); taskPtr++,taskID++)
  616.    {
  617.     if (taskPtr->Status == TASK_STATUS_READY) return taskID;
  618.    }
  619.    return TASK_ID_SCHEDULER;
  620. }
  621. // *****************************************************************************
  622. // * Purpose          : switch execution of task
  623. // * Input Parameters : none
  624. // * Return Value     : none
  625. // * Description : the function will save stack of current task to SDRAM,
  626. // *   than download stack of next ready task from SDRAM and
  627. // *   return execution to new task
  628. // * Comments   : the si,di registers has to be preserved, it is requirment
  629. // *   of the compiler
  630. // *****************************************************************************
  631. static SAMP(ErrCode) TaskSwitch (void)
  632. {
  633. //has to be static variable, so the address will not change
  634. //get id of ready task with highest priority
  635.    static TCB *taskPtr;
  636. static IDENT id;
  637. #ifdef _DEBUG_TASK_SWITCH
  638. //static UINT32 s_time,e_time;
  639. #endif
  640.    static UINT8 * addr;
  641. _SI = _DI = 0x0000;
  642.    id = SchedulerGetReadyTask ();
  643. #ifdef _DEBUG_TASK_SWITCH
  644.    //dbg_printf (("*** TaskSwitch %i->%in",CUR_TASK,id));
  645.    dbg_printf (("TS %i->",CUR_TASK));
  646.    dbg_printf (("%in",id));
  647. //   SAMP(TH_Send)("SCHEDULER ", "TaskSwitch: task - id", "%u%u", CUR_TASK, id);
  648. #endif
  649.    if (CUR_TASK == id) return SAMP(ERR_OK);
  650. taskPtr = &(TASK[CUR_TASK]);
  651.    //force compiler to save si and di registers on stack at the beggining of TaskSwitch function
  652.    //save offset of stack pointer to TCB of current task
  653.    taskPtr->StackOff = _SP;
  654. #ifdef _DEBUG_TASK_SWITCH
  655. //dbg_printf (("  * Old stack: SDRAM %lx, Stack %Fp, Num %in",taskPtr->SDRAMStackAddr, MK_FP (_SS,taskPtr->StackOff),initialStack - taskPtr->StackOff));
  656. //   SAMP(TH_Send)("SCHEDULER ", "TaskSwitch: task - id", "%u%u", CUR_TASK, id);
  657. //s_time = gen_timer ();
  658. #endif
  659. //save stack of current task to SDRAM
  660.    wai_sem(SEM_DRAM_ID);
  661.    {
  662.     addr = MK_FP (_SS,taskPtr->StackOff);
  663.     if((INITIAL_STACK - taskPtr->StackOff)%2) //odd
  664.      addr -= 1;
  665.    I49_WriteDRAMDataNSW (taskPtr->SDRAMStackAddr,(UINT16 *)addr,(INITIAL_STACK - taskPtr->StackOff + 1)/2);
  666.    }
  667.    //change the current task to new task
  668.    CUR_TASK = id;
  669.    taskPtr = &(TASK[id]);
  670.    //reload stack pointer with value from new task
  671.    _SP = taskPtr->StackOff;
  672.    //from this point the code is using stack space of new task
  673. //restore the stack of the new task
  674.    {
  675.     addr = MK_FP (_SS,taskPtr->StackOff);
  676.     if((INITIAL_STACK - taskPtr->StackOff)%2) //odd
  677.      addr -= 1;
  678.  I49_ReadDRAMDataNSW (taskPtr->SDRAMStackAddr,(UINT16 *)addr,(INITIAL_STACK - taskPtr->StackOff + 1)/2);
  679.    }
  680.    sig_sem(SEM_DRAM_ID);
  681. #ifdef _DEBUG_TASK_SWITCH
  682.      //e_time = gen_timer();
  683.   //dbg_printf (("  * New stack: SDRAM %lx, Stack %Fp, Num %in",taskPtr->SDRAMStackAddr, MK_FP (_SS,taskPtr->StackOff),initialStack - taskPtr->StackOff));
  684.   //dbg_printf (("  * Task switch time: %liusn",e_time - s_time));
  685. #endif
  686.    return SAMP(ERR_OK);
  687. }
  688. /*
  689. Purpose: get the current elapsed time in centi seconds since startup.
  690. */
  691. SAMP(ErrCode) SAMP(OS_GetTime)(UINT32 *Ticks)
  692. {
  693.    *Ticks = timing_get_clock()/10000;
  694.    return SAMP(ERR_OK);
  695. }
  696. /*
  697. Purpose: arm logical timer to invoke callback on every interval.
  698. Return: SAMP(ERR_OK), succesful.
  699.         SAMP(ERR_FAILED), no free timer available.
  700.         SAMP(ERR_INVALID_PARAM), Ticks is 0 or OS_FOREVER.
  701. */
  702. SAMP(ErrCode) SAMP(OS_TimerEvery)(UINT32 Ticks, void (*Callback)(void), IDENT *Id)
  703. {
  704.    if(0 == Ticks || OS_FOREVER == Ticks)
  705.     return SAMP(ERR_INVALID_PARAM);
  706. *Id = timer_service_create((LPTIMERPROC)Callback, Ticks*10,
  707.  TIMER_ENABLED | TIMER_SAMP);
  708.    //*Id = timer_service_create((LPTIMERPROC)Callback, Ticks*1000,
  709. //  TIMER_ENABLED);
  710.    if(NULL == *Id)
  711.     return SAMP(ERR_FAILED);
  712.    else
  713.     return SAMP(ERR_OK);
  714. }
  715. SAMP(ErrCode) SAMP(OS_TimerCancel)(IDENT Id)
  716. {
  717.    if( TRUE == timer_service_delete(Id))
  718.     return SAMP(ERR_OK);
  719.    else
  720.     return SAMP(ERR_UNKNOWN);
  721. }
  722. // *****************************************************************************
  723. // * Purpose          : Initialize task scheduler
  724. // * Input Parameters : None
  725. // * Return Value     : None
  726. // * Description : The function sets states of all scedular resources
  727. // * to initial state and assignes SDRAM memory space for each task stack
  728. // *****************************************************************************
  729. static void Constructor (void)
  730. {
  731.    UINT8 id;
  732.   //set current task to scheduler
  733. //JERRYC_2004AUG24
  734. INITIAL_STACK = Ker_GetCoreStackBottom(); //set the stack to the end of the SRAM memory
  735.    CUR_TASK = TASK_ID_SCHEDULER;
  736. //initialize tasks including the scheduler
  737.    for (id = 0; id < NUMBER_OF_TASKS + 1; id++)
  738.    {
  739.     TASK[id].Status = TASK_NOT_STARTED;
  740.    TASK[id].SDRAMStackAddr = SDRAM_STACK_BASE + (UINT32)id * (SDRAM_STACK_SIZE/2);
  741.    }
  742.    //initialize semaphors
  743.    for (id = 0;id < NUMBER_OF_SEMAPHORES;id++)
  744.    {
  745.     SEMA[id] = SEMAPHORE_UNINITIALIZED;
  746.    }
  747.    //initialize mailboxes
  748.    for (id = 0;id < NUMBER_OF_MAILBOXES;id++)
  749.    {
  750.     MB[id].MessageQueue = NULL;
  751.    }
  752. }
  753. // *****************************************************************************
  754. // * Purpose          : Dealocate all resources used by scheduler
  755. // * Input Parameters : None
  756. // * Return Value     : None
  757. // * Description : Release heap memory allocated by mailboxes if not done
  758. // * before
  759. // *****************************************************************************
  760. static void Destructor (void)
  761. {
  762.    IDENT id;
  763.    //delete the timers otherwise core task mail box will get overflowed with timer events.
  764. // timer_service_delete_all_samp_timers(); //sacd todo: check if timers are not needed any more at this time.
  765.    SAMP_SchedulerRemove();
  766. //release memory allocated for mailboxes
  767.    for (id = 0;id < NUMBER_OF_MAILBOXES;id++) SAMP(OS_MboxDelete) (id);
  768.    //samp already does the clean up.
  769. //   for (id = 0;id < NUMBER_OF_SEMAPHORES;id++) SAMP(OS_SemDelete) (id);
  770. //   for (id = 0;id < NUMBER_OF_TASKS;id++) SAMP(OS_TaskDelete) (id);
  771. }
  772. // *****************************************************************************
  773. // * Purpose          : instal SAMP scheduler
  774. // * Input Parameters : NA
  775. // * Return Value     : even handler id
  776. // *  -1 - no even hadler position available
  777. // * Description      : see purpose
  778. // *****************************************************************************
  779. int SAMP_SchedulerInstall (void)
  780. {
  781.    if(SchedulerID == -1)
  782.    {
  783.  SchedulerID = install_core_event_handler( SAMP_Scheduler );
  784. #ifndef TEST_HARNASS
  785.     SACD_GLOBALS.nav_handler_id = install_core_event_handler( SACD_Navigator );
  786. #endif
  787.    }
  788.    return SchedulerID;
  789. }
  790. // *****************************************************************************
  791. // * Purpose          : remove SAMP scheduler
  792. // * Input Parameters : NA
  793. // * Return Value     : even handler id
  794. // *  -1 - no even hadler position available
  795. // * Description      : see purpose
  796. // *****************************************************************************
  797. void SAMP_SchedulerRemove (void)
  798. {
  799. if (SchedulerID != -1)
  800.    {
  801.     //remove_core_event_handler (SchedulerID); //ask Jerry!!!
  802. #ifndef TEST_HARNASS
  803.     remove_core_event_handler (SACD_GLOBALS.nav_handler_id);
  804. #endif
  805.     SchedulerID = -1;
  806.    }
  807. }
  808. // *****************************************************************************
  809. // * Purpose          : task scheduler implementation
  810. // * Input Parameters : Op handler operation code
  811. // * Event event type
  812. // *                    Param parameter
  813. // * Return Value     : zero
  814. // * Description : the handler will initialize all scheduler resources upon
  815. // * instalation and release memory if not done in the code. The handler manages
  816. // * following events:
  817. // *  IE_CORE_SAMP_API - request to call API function. It is processed by
  818. // * supplied SAMP_API_Handler function
  819. // * IE_CORE_SAMP_WAKE_UP - send during OS_ISendMsg to allow task switch in
  820. // * case of all tasks are in sleep state waiting for message or semaphor
  821. // *****************************************************************************
  822. static int SAMP_Scheduler (HDLR_OP Op, EVENT Event, void *Param)
  823. {
  824. switch (Op)
  825. {
  826. case HDLR_ENTER:
  827.     Constructor();
  828.       //if(gpSAMP_API_param == NULL)
  829.       //gpSAMP_API_param = malloc(8 * sizeof(UINT32));
  830.       //ASSERT(gpSAMP_API_param != NULL)
  831. break;
  832. case HDLR_EXIT:
  833.     Destructor();
  834.       //if(gpSAMP_API_param != NULL)
  835.       //{
  836.       // free(gpSAMP_API_param);
  837.       // gpSAMP_API_param =NULL;
  838.       // }
  839. break;
  840. case HDLR_EVENT:
  841. switch (Event)
  842.       {
  843.          case IE_CORE_SAMP_API:
  844.           //the API function calls occur inside of this function
  845.           SAMP_API_Handler ((UINT32)Param);
  846.          break;
  847.          case IE_CORE_SAMP_WAKE_UP:
  848.           //this message is send by OS_ISendMsg in order to allow task switch
  849.             //in case all task are in wait state
  850. TaskSwitch ();
  851.             break;
  852.          case IE_CORE_SAMP_TIMER_EVERY:
  853.          {
  854.           LPSACDTIMERPROC cb = (LPSACDTIMERPROC)Param;
  855.           cb();
  856.           break;
  857.          }
  858.          default:
  859.       //dbg_printf(("SAMP_Nav: Unexpected Event %xn",Event & 0xFF));
  860.             break;
  861.          }   
  862.          break;
  863. default:
  864. dbg_printf((" SAMP_Nav: Unknown Operation requested %dn", Op));
  865. break;
  866. }
  867. return 0;
  868. }
  869. #endif // D_SUPPORT_SACD