Shop OBEX P1 Docs P2 Docs Learn Events
Multi Threaded SX/B - Page 2 — Parallax Forums

Multi Threaded SX/B

2

Comments

  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-06 16:29
    Since a task is just a subroutine, there is nothing stopping you
    to call another task directly from a task. As long as both tasks together
    take less than 1 TASKTICK unit there is no problem. If they do take
    longer you miss a TASKTICK.
    The demands are actually the same as for the isr.
    You cannot have more cycles than assigned (via TASKTICK) or ticks will be missed.
    It really depends on the application if that matters.
    For a·task that blinks a led·it would not matter if a tick was missed.

    regards peter
  • BeanBean Posts: 8,129
    edited 2007-03-06 17:50
    Okay I'm missing something vital here... I thought that if a task took longer than 1 tick the interrupt would keep track of that and adjust the next task. Or that the task would be run from where it left off.

    Why won't something like this work ? I don't see what all the "context switching" is doing...

     
    DEVICE SX28, OSC4MHZ, TURBO, OPTIONX, STACKX
    FREQ 4_000_000
    LED1    PIN RC.0 OUTPUT
    LED2    PIN RC.1 OUTPUT
    LED3    PIN RC.2 OUTPUT
    LED4    PIN RC.3 OUTPUT
    
    cnt           VAR Byte
    task_ID       VAR BYTE (4)
    task_Interval VAR BYTE (4)
    task_Count    VAR BYTE (4)
     
    INTERRUPT 100
      GOTO HandleInt
     
    TASK1   SUB 0
    TASK2   SUB 0
    TASK3   SUB 0
    TASK4   SUB 0
     
    HandleInt:
      FOR cnt = 0 TO 3
        DEC task_Count(cnt)
        IF task_Count(cnt) = 0 THEN
          ON cnt GOSUB TASK1, TASK2, TASK3, TASK4
          task_Count(cnt) = task_Interval(cnt)
        ENDIF
      NEXT
    RETURNINT
    
     
     
    PROGRAM Start
    
     
     
    Start:
      PUT task_ID, 0, 1, 2, 3
      PUT task_Interval, 10, 50, 75, 100
      PUT task_Count, 1, 1, 1, 1
      ' Main code here, do whatever...
    END
    
    Task1:
      LED1 = ~LED1
      RETURN
    
    Task2:
      LED2 = ~LED2
      RETURN
    
    Task3:
      LED3 = ~LED3
      RETURN
    
    Task4:
      LED4 = ~LED4
      RETURN
    
     
    


    Bean

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheap used 4-digit LED display with driver IC·www.hc4led.com

    Low power SD Data Logger www.sddatalogger.com
    SX-Video Display Modules www.sxvm.com
    Coming soon! Propeller based OSD module www.hittconsulting.com
    ·
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-06 17:56
    Bean,
    To support running tasks scheduled for the same tick, in one tick
    you can change

    · if taskDelay(0) = 0 then
    ··· on taskId(0) gosub Task0,Task1,Task2,Task3,Task4,Task5,Task6,Task7
    ··· taskDelay(0) = taskInterval(0)
    ··· Reschedule
    · endif

    into

    · do while·taskDelay(0) = 0
    ··· on taskId(0) gosub Task0,Task1,Task2,Task3,Task4,Task5,Task6,Task7
    ··· taskDelay(0) = taskInterval(0)
    ··· Reschedule
    · loop

    in subroutine DoSchedule
    We then need to set a pending bit for TASKTICK, in case a task is already running
    the moment a context switch should take place.

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-06 18:06
    Bean,
    Your example works, but is very limited in cycles, so you can only
    have very small tasks.

    The context switch enables a subroutine to execute directly after the isr
    exits and before returning to the mainloop. The way it is set up, this
    subroutine can not be interrupted by another task, only by the isr, but the
    isr then never does a context switch.
    The task may take a considerable longer time than the isr allows.

    regards peter
  • BeanBean Posts: 8,129
    edited 2007-03-06 18:25
    Please be patient with me Peter... I must get my head around this to implement it properly...

    So if you do the context switch, then the task CAN take longer than 1 tasktick ?
    If not how could you use more time than the isr would allow ?

    If the task CAN take longer than 1 tasktick, then does it keep the next task on-time ?
    Let's say we had two task that are at 10 tick intervals, but have a 5 tick offset.
    Could both of these tasks take 3 taskticks each time they are run, and still always be exectuted "on-time" ?
    If that is the case, then it makes sense... If not how does the context switch allow longer tasks ?

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheap used 4-digit LED display with driver IC·www.hc4led.com

    Low power SD Data Logger www.sddatalogger.com
    SX-Video Display Modules www.sxvm.com
    Coming soon! Propeller based OSD module www.hittconsulting.com
    ·
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-06 18:56
    Bean,
    If you have an int_period of 217 and no prescaler you only have 217 cycles available
    inside the isr. Inside the isr a counter is decremented and when it reaches zero it
    does a context switch, allowing a subroutine to run after the isr exits. This counter is
    reloaded and decremented inside the isr while the subroutine runs as mainline code.
    If the reload value is 100, then you have 100*217 cycles available for the subroutine,
    assuming the subroutine must return to not miss the next context switch.
    That is how it currently is setup.

    I mentioned in an earlier post that timing issues with a task, eg. the subroutine takes
    longer than 1 TASKTICK, can be resolved by using a statemachine in that subroutine
    so you can make sure the subroutine returns on time. Next time the subroutine runs
    it can continue where it was.

    Your example of two tasks each lasting for 3 TASKTICKs and 5 ticks apart made me think.
    I can change the setup so that·when a task is already running when a context switch
    should occur, that I decrement the taskDelay(1) by 1. That is sufficient to have taskDelay(1)
    set to 2 when the running task returns after 3 TASKTICKs. That is quite a bit better
    than the statemachine·solution, though that still could be used.

    regards peter
  • BeanBean Posts: 8,129
    edited 2007-03-06 18:59
    Peter,
    So the interrupt occurs many times within 1 tasktick ? If so then that is where I was getting confused.

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheap used 4-digit LED display with driver IC·www.hc4led.com

    Low power SD Data Logger www.sddatalogger.com
    SX-Video Display Modules www.sxvm.com
    Coming soon! Propeller based OSD module www.hittconsulting.com
    ·
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-06 19:02
    Yes, the context switch rate is lower than the isr rate.

    regards peter
  • JonnyMacJonnyMac Posts: 9,214
    edited 2007-03-06 19:06
    You know, Peter, I thought I was a reasonably bright guy until I tried following this stuff... wow, very heavy -- but with cool impliations. So, by "context" to you mean the current task pointer?
  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2007-03-06 19:16
    Peter,

    I want to ask if every part of every program has to be split into nice little tick-sized subroutines in order to make use of the multi-threading structure you are creating. It seems that some tasks are well suited to running whenever there is “extra” time between scheduled tasks.

    For the background UART I finally got working I would like to buffer received data and, when enough bytes have been collected, begin to process it. I would like to enter this processing subroutine without having to worry about what its longest possible execution time might be and what scheduled tasks it might be preventing from running.

    Will the multi-threading structure you are developing allow some tasks (at least the designation of one that can be changed during execution) to be run in the slack or “extra” time between the completion of the currently scheduled task and the start of the next scheduled task?

    This seems useful to me. I hope I am not missing the point!

    - Sparks
  • BeanBean Posts: 8,129
    edited 2007-03-06 19:19
    Peter, Okay now I "get it".
    Yeah, that IS pretty cool.
    Let me "play" around with the code you posted and I'll investigate how to implement it into SX/B.

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheap used 4-digit LED display with driver IC·www.hc4led.com

    Low power SD Data Logger www.sddatalogger.com
    SX-Video Display Modules www.sxvm.com
    Coming soon! Propeller based OSD module www.hittconsulting.com
    ·
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-06 19:19
    Jon,
    Not quite.
    You have the normal mainloopcode running. This gets interrupted by the isr.
    If it is not time for a context switch, the isr exits and the mainloopcode continues.
    If it is time for a context switch, the mainloopcode return address is saved and
    the TaskSchedule address is placed on the shadow stack.
    When the isr exits the subroutine TaskSchedule runs as mainline code.
    This calls DoSchedule and there it is decided which task to run.
    All this is mainline code. The isr keeps running. When the task returns TaskSchedule waits for the isr
    interrupt to restore the context for mainloopcode, or if· RTCC is low enough
    then TaskSchedule restores the context for the mainloopcode directly.

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-06 19:27
    Sparks,
    If you specify·a task rate of 1000, then the task will run every 1msec.
    That may be sufficient to pick up a received byte and store it in an array.
    Another option would be, to reschedule a task so it runs sooner, and perhaps
    only once (task on demand).

    regards peter
  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2007-03-06 19:44
    Peter,

    What are the potential drawbacks of placing code between Main: and Goto Main in this section?

    Main:
      ' main code here
      goto main
    



    It is my expectation that this section was left over from the use of the SX/B template and that while you intend to have an endless loop there you do not actually intend for user code to reside there. Is that correct?

    Thank you for your patience. I know you are receiving a lot of questions about this. smile.gif

    - Sparks
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-06 19:57
    Sparks,
    That is still the place to put your main code.
    It is the main code that is interrupted by isr and tasks.
    The tasks allow certain code to run without you explicitly
    calling this code.

    regards peter
  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2007-03-06 20:16
    Ahh…! smile.gif

    Thank you, Peter. I really was thinking that your system required every single thing to be broken into tiny little tasks that could be handled by the scheduler. I like it much, much better now that I understand I can still write big, ugly code for my main program and only use the task scheduler for tasks that I want to run at very specific intervals.

    Thank you for your patience with my questions and for the clarification.

    - Sparks
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-06 20:59
    I changed the code to adjust for a missed TASKTICK.
    Also changed DoSchedule so tasks scheduled to run at the same tick,
    are now called after each other without returning to mainloopcode first.
    Also added the save and restore of the sx/b variables __PARAM1 to __PARAM5.

    regards peter
  • BeanBean Posts: 8,129
    edited 2007-03-06 23:14
    Peter,
    I assume it is okay with you if I put this code in the SX/B compiler ?

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheap used 4-digit LED display with driver IC·www.hc4led.com

    Low power SD Data Logger www.sddatalogger.com
    SX-Video Display Modules www.sxvm.com
    Coming soon! Propeller based OSD module www.hittconsulting.com
    ·
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-07 00:08
    Sure.
    You may even (or must) relocate the kernel and list variables,
    probably moving them toward the last rambank.
    How do you plan to use the variables
    index var byte
    temp var byte
    sumDelay var byte
    indexMinus1 var byte
    moveup var byte
    that I used in the TaskSchedule, DoSchedule and Reschedule·routines?
    I would hate to loose 5 normal variables,
    especially since there are so few of those.

    regards peter
  • BeanBean Posts: 8,129
    edited 2007-03-07 00:51
    I'll have to figure that all out after I get it implemented. You're right the arrays will be moved to the highest addresses. I hope to preserve the "normal" variable space, that is very dear.

    I just didn't want to "rip-off" your code.

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheap used 4-digit LED display with driver IC·www.hc4led.com

    Low power SD Data Logger www.sddatalogger.com
    SX-Video Display Modules www.sxvm.com
    Coming soon! Propeller based OSD module www.hittconsulting.com
    ·
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-07 01:13
    I understand that.
    I managed to relocate two normal variables into kernel(16) array.
    If we decide that TASKTICK should be a constant, calculated from interrupt rate
    and totalTaskRate (or set by user via interrupt keyword or special keyword), then kTimer var kernel(6)
    could be used for moveup.
    Then the code only uses 2 normal variables, index and indexMinus1.

    Edit: I saw in the listview that sx/b does not save __PARAM5 when entering isr.
    Does it not need to be saved?

    regards peter
    ·


    Post Edited (Peter Verkaik) : 3/7/2007 1:18:08 AM GMT
  • JonnyMacJonnyMac Posts: 9,214
    edited 2007-03-07 01:42
    Peter,

    The SX/B instructions only ever use __PARAM1 .. __PARAM4, so __PARAM5 (aliased address of __PARAMCNT) would not be affected. __PARAM5 is only used by the programmer when they know that a function or subroutine needs exactly five parameters.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-07 02:41
    Jon,
    I have seen code where _PARAMCNT is used upon entry of a subroutine.
    What if the isr interrupts when main code has just entered such a subroutine,
    and the isr code itself does a gosub to some subroutine that may take a variable
    number of arguments? That would affect _PARAMCNT I think.

    regards peter
  • JonnyMacJonnyMac Posts: 9,214
    edited 2007-03-07 02:52
    Indeed, it would. If the parameter count is less than 5 then __PARAMCNT is loaded with the number of parameters; if exactly five parameters are used then this register is used for the fifth parameter (the compiler uses the SUB/FUNC declaration to determine which action to take). The programmer must be aware of the danger of using __PARAMCNT this way; it might be better to pass the address of an array if more than four parameters are required.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-07 03:05
    If _PARAMCNT is loaded with the number of arguments for any gosub,
    then you cannot use gosub in the interrupt section because that will
    destroy _PARAMCNT, unless the sub called from isr happens to have
    an identical number of parameters.
    I also know that most subroutines have a fixed number of parameters
    and therefore _PARAMCNT is hardly ever used, but still, this could lead
    to some erratic program behaviour, which might not be repeatable,
    and therefore almost impossible to debug.

    regards peter
  • JonnyMacJonnyMac Posts: 9,214
    edited 2007-03-07 03:18
    The compiler will not manipulate __PARAMCNT if you specify exactly zero or exactly five parameters in your SUB/FUNC declaration. To your point, this is rarely the case and using __PARAMCNT/__PARAM5 to pass a value can be dangerous; I don't do it.

    EDIT: __PARAMCNT is not manipulated if you're using a fixed count, no matter how many parameters are passed; if it's fixed, the compiler assumes that you know how many to expect and it doesn't pass the number to you. This allows __PARAMCNT to be used as __PARAM5 (but that should be done with caution).

    Post Edited (JonnyMac) : 3/7/2007 9:26:42 PM GMT
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-07 10:46
    The attached version runs (SX48) , generating "RESET" followed by a stream of digits.
    '0' for task0, '1' for task1 etc. It outputs '-' for·ticks where no tasks run.
    Just set pinTX to I/O port of choice and connect via level shifter to pc com port.
    Baud 9600,8N1.

    regards peter

    Post Edited (Peter Verkaik) : 3/7/2007 11:15:10 AM GMT
  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2007-03-07 20:33
    Peter,

    I am sorry to bug you about this. I know you said that your latest code was for the SX48 but… I would like to try it on my SX28. blush.gif

    I tried to make the conversion myself by reducing the number of tasks from 8 to 4 with the following changes.

    DEVICE          SX28, OSCHS1
    .
    .
    .
    tasklist var byte(12) '4 tasks supported
    taskId var tasklist(0) 'order of task running
    taskDelay var tasklist(4) 'delta time list
    taskInterval var tasklist(8) 'reload delay values for tasks
    .
    .
    .
    put taskId      , 0, 1, 2, 3
    put taskInterval,10,13,17,23
    put taskDelay   , 1, 1, 1, 1
    .
    .
    .
      for index=1 to 4
        if index=4 then exit
    .
    .
    .
      if index < 4 then
    .
    .
    .
      if moveup < 3 then
    


    I also tried the inverted serial mode but I always get 12-13 non-text bytes sent whenever I reset the SX28 no matter what serial setting I use.

    My questions are as follows. Is it possible to make your task-switching demo run on an SX28? If it is, do you mind posting an SX28 version when you have time?

    I hope I am not becoming a pain. I am just trying to figure this out!

    - Sparks
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-03-07 21:16
    The attached program compiles.
    I did NOT test this, but I think it should run.

    regards peter
  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2007-03-07 21:44
    Yes, yes! hop.gif

    The program is running, Peter. Now so am I! I am off to try to make sense of the strange sequence of numbers and dashes slowing filling my terminal window.

    Thank you for providing the demo and for re-providing it in an SX28 version. smile.gif

    - Sparks
Sign In or Register to comment.