multitasking on at91sam7x microcontroller

Upload: ahmed

Post on 04-Jun-2018

223 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    1/30

    BUTSCHER Morgane

    DANIAUD Vivien

    DESHAYES Raphael

    MORARD Jean-Sverin

    Multitasking on

    AT91SAM7X microcontroller

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    2/30

    1

    Table of contents:

    Introduction 2

    1. Specifications 22. Fundamental concepts 3

    2.1. Generalities on multitasking 3

    2.2. Stacks 3

    3. RAM and stacks management 4

    3.1. RAM structure 4

    3.2. Stack features 4

    4. User part 7

    5. Interrupt sources 9

    5.1. Three possibilities of periodic interrupt 9

    5.2. Configuration of the Timer Counter 0 10

    5.3. Interrupt generation 10

    5.4. Behavior of AIC and TC0 during an interrupt 11

    6. Interrupt handling 12

    6.1. Some useful registers 12

    6.2. Context save 13

    7. Work on the system stack 16

    7.1. Different stacks 16

    7.2. Tasks context management 16

    8. Example of use 21

    8.1. Simple program 21

    8.2. Use programs in multitasking 22

    Conclusion 22

    Appendix: Source code 23

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    3/30

    2

    Introduction:

    The project which is presented in this report is a description of a multitasking environment in anAT91SAM7X microcontroller. The main concepts of multitasking structure are task scheduling and stack

    management. This structure has to manage tasks in order to execute them together.

    The presentation is not only aimed at users, who want to use the multitasking application, but also contains

    the description of how the system and functions are build.

    1. Specifications:

    The task number that multitasking handle is to be defined by the user

    The use of a real time clock not required

    This project is aimed at providing a tool for second-year students to be used during practical work. They

    will therefore be able to compare multitasking and interrupts.

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    4/30

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    5/30

    4

    3. RAM and stacks management:

    3.1. RAM structure:

    In the Random Access Memory, a stack table composed of Nstacks is created. Note that N is defined as

    NB_TASKSin the header file (Multi_task.h). It is the maximum number of tasks the user can execute in parallel and

    it must be less than 11 (see the specifications). Obviously, the number of tasks the user really wants to execute can

    be less than or equal toN.

    Each stack of the stacks table contains the context of one task. We assignedDATA_RAMbytes to the stacks

    table which means that STACK_SIZEbytes were assigned to each stack (where STACK_SIZEequalsDATA_RAM /

    N).

    See below in figure 3 the diagram representing the stacks table in the RAM on one side, and a zoom in on

    the other side. Addstartand Addendare respectively the stacks_table start address and the stacks_table end address,

    whereas add1startand add1endare respectively the stack_1 start address and the stack_1 end address. These addresses

    are used by the designer in order to read and write in the stacks.

    Figure 3 - RAM and stacks

    3.2. Stack features:

    The issue raised is how this stack table is managed. In order to manage each stack correctly, we created

    another table composed ofNstructures. Each structure contains important elements to handle a task, that is to say:

    num The task number (0 if this is task number 0, 1 if this is task number 1... n ifthis is task number n) ;

    state The task state (unused, sleeping, active or starting see below) ; add_fct The name of the C programming function executed by this task ; stack_bottom The address of the corresponding stack bottom ; stack_top The stack pointer to read and write in the corresponding stack (the stack top) ;

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    6/30

    5

    stack_limit The limit address delineating the STACK_SIZEbytes allocated to this task ;

    In figure 4, you can see a diagram summarizing the links between these two tables.

    Figure 4 - Link between the stack table and task tables

    The next part deals with a another task structure parameter: state. In a common working of multitasking,

    each task goes through different states depending on its life cycle. That is why there are four states:

    UNUSED When the task is not used. The first case is if the scheduler is not running and thetask not launched. The second case is if the scheduler is running but the task notlaunched or over ;

    (STARTING) This state is important because of the interrupt working. It will be detailed whybelow. For the moment, just note that this state is not visible from the user point

    of view. It is just a transitional state between the UNUSEDstate and theACTIVEstate ;

    ACTIVE When the task is initialized, ready and running. It is the state following theUNUSEDstate or alternately with the SLEEPINGstate ;

    SLEEPING When the execution of the task must be stopped during a moment (to wait for

    data for instance). Typically, it is the user who sparks off this state.

    In order to know continuously the state of each task, the task state are store in four tables: unused[],

    starting[], active[]and sleeping[]. One more time, these tables or all composed byNsquares. We just deal with the

    first n squares, the other ones being unused. The working of every table is similar. Lets take the example of

    unused[]: the first square corresponds to task number zero, the second square to task number one... A 1 is stored

    in the first square if the task number zero is in an unused state. A 0 is stored if it is not. Figure 5 shows anexample of this situation.

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    7/30

    6

    Figure 5 - Example of the different state tables

    - Tasks 0 and 6 are unused(not launched or over)

    - Tasks 8 are 9 are unused (notused by the user)

    - Tasks 1, 2, 4 and 7 arestarting

    - Task 3 is active- Task 5 is sleeping

    1 10 0 0 0 0 0 1 1unused[]

    11 1 10 000 0 0starting[]

    10 0 0 0 0 0 0 0 0active[]

    10 0 0 0 0 0 0 0 0sleeping[]

    used tasks

    NB_TASK

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    8/30

    7

    4. User part:

    This part is about the user space, that is to say all the functions he can execute in order to run this program.

    int Init_Struct ()This function initializes the data structure to implement Nparallel tasks. Then, it is up to the user to use

    fewer tasks if he wants to. Each structure of the taskstable is initialized in the same way. Lets take the standard

    example of task number i: we put iin num, UNUSEDin state, the name of the associated C function in add_fctand

    the corresponding addresses of tasks_RAMin stack_bottom, stack_topand stack_limit. As for the tables unused[],

    starting[], active[]and sleeping[], we feel unused[]with ones and the other tables with zeros.

    Input : No input Output : 0 if successful

    E_RUNNING_SCHED if the scheduler is already started

    int Create_Task (void (*function)(void))This function allows the user to add a task provided that there are less than N tasks created and that the

    scheduler is not already running. It just changes the parameter of the next free task_tsquare of the table tasksby

    fixing add_fctto the input parameterfunction. To do that, the data structure must already have been called but the

    scheduler must not be running.

    Input : The C function associated to this task Output : 0 if successful

    E_RUNNING_SCHED if the scheduler is already startedE_NO_SPACE_LEFT if all theNtasks have already been createdE_NO_INIT if the data structure is not yet initialized

    int Launch_Task (int n)This function allows starting a task. Thus, the user can control the moment he wants to start a task and is

    not obliged to start all the tasks at the scheduler setting up. It replaces the parameter stateof the corresponding

    task_tto STARTING.

    Input : The number of the task we want to launch Output : 0 if successful

    E_UNINIT_TASK if the task is not initialized

    E_RUNNING_TASK if the task is already launched

    0

    E_RUNNING_SCHEDInit_Struct

    Launch_Task

    0

    E_UNINIT_TASK

    E_RUNNING_TASK

    n

    Create_Task

    0

    E_RUNNING_SCHEDE_NO_SPACE_LEFT

    E_NO_INIT

    function

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    9/30

    8

    int Start_Scheduler ()This function starts the scheduler. It is from this moment that the launched tasks are executed, so that the

    program runs. It defines the interrupt function.

    Input : No input Output : 0 if successful

    E_NO_INIT if the data structure is not initializedE_NO_FUNCTION if no tasks are initialized

    int Scotch_Task (int n)This function allows the user to stop the execution of a task by fixing his state to SLEEPING. It changes the

    parameter stateto SLEEPINGprovided that the task is already running and not sleeping.

    Input : The number of the task we want to stop Output : 0 if successful

    E_UNINIT_TASK if the task is not initialized

    E_SLEEPING_TASK if the task is already sleeping

    int Wake_Task (int n)This function allows the user to wake a sleeping task by changing his statetoACTIVE. The task must be alreadyinitialized and sleeping.

    Input : The number of the task we want to stop Output : 0 if successful

    E_UNINIT_TASK if the task is not initializedE_ACTIVE_TASK if the task is already running

    The figure 6 is a use example of these functions :

    Figure 6 - Use example of these functions

    0

    E_NO_INIT

    E_NO_FUNCTION

    Start_Scheduler

    Scotch_Task0E_UNINIT_TASK

    E_SLEEPING_TASK

    n

    Wake_Task

    0

    E_UNINIT_TASK

    E_ACTIVE_TASK

    n

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    10/30

    9

    5. Interrupt sources:5.1. Three possibilities of periodic interrupt:

    In a multi tasks platform, an interrupt is necessary to plan a schedule for each task. When an interrupt

    occurs, the scheduler has to change the running task. In this project, a periodic interrupt is necessary; they have to

    be generated by the controller.

    In the AT91SAM7X microcontroller, there are 3 kinds of periodic interrupt: The PIT is inside the System Controller, it is used to generate periodic interrupt. This component is

    designed to offer maximum accuracy and efficient management, even for systems with long response time.

    The PIT has a 20 bits counter with a clock at MCK/16.

    Three Timer Counters are external peripherals. Timer Counter can be used to generate interrupt or a specialclock. They have a lot of option: to control the input clock and registers values. A Timer Counter has a 12

    bits counter with 5 possible input clock (MCK/2, MCK/8, MCK/32, MCK/128 and MCK/1024).

    The Real-time Timer is built around a 32-bit counter and used to count elapsed seconds. It generates aperiodic interrupt. It is inside the System Controller too.

    Figure 7 - AT91SAM7X architecture

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    11/30

    10

    The comparison of this three interrupt generators give us a crucial point: The PIT and the RTT use the

    System Controller vector. In our case if we use this kind of interrupt, users of the multi tasks will not be allowed to

    use something in the System Controller, because it will cause confrontation between each declaration.

    Regarding this, we focused on the first Timer Counter (TC0). When an interrupt from this timer will occur, the

    scheduler has to change the active task.

    5.2. Configuration of the Timer Counter 0:

    The configuration of the TC0 is determinate when a user start the scheduler (function Start_Scheduler()

    with source code in page 26).

    The beginning of this configuration active the PMC of the TC0, it power on the timer. Then we configure the AIC (Interrupt Controller) for the TC0 with a low priority. In the AIC we put the name of the interrupt function:ITSched(). The TC0 can use one of 5 clocks, we choose the slowest: MCK/1024. It corresponds to a frequency of 0.2

    MHz (199691 Hz).

    The register C stores the maximum of what the counter can reach: 2 000. We want an interrupt each 10ms:2000

    199691= 10

    5.3. Interrupt generation:

    Each period, the selected clock increments the 16-bits counter value. Each increment, this value is

    compared to the register C. When values are equal, an interrupt is generated.

    Figure 8 - Interrupt generation

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    12/30

    11

    5.4. Behavior of AIC and TC0 during an interrupt:

    During an interrupt (functionITSched(), source code in page 27), we have to change the stack pointer ( sp)

    value. Thats why all interrupt sources has to be avoid because it can cause some troubles and modify system

    register values. Before disabling all interrupt, the value of active interrupt sources must be save.

    Another action must be made in the interrupt: we have to read the TC0 status register to empty the timer

    counter interrupt vector.

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    13/30

    12

    6. Interrupt handling:

    6.1. Some useful registers:

    In the project, two different stacks are used: the IRQ stack and the Supervisor stack. They only are two

    stacks among the six existing. On the figure below, the six registers are displayed and the user stacks shows the

    different register succession.

    Figure 9: Register organization

    There are one dedicated program counter ( PC ), one dedicated current program status register ( CPSR ), 5

    dedicated saved program registers ( SPSR ) and 30 general purpose registers. However these are arranged into

    several banks, with the accessible bank being governed by the processor mode. Each mode can access:

    - a particular set of r0-r12 registers

    - a particular r13 ( the stack pointer ) and r14 ( link register ) which is used as the subroutine link register and stores

    the return address when Branch with Link operations are performed. Thus, to return from a branch the instruction

    below is used: MOV pc , lr.

    - r15 ( the program counter ). Depending on the details of the particular computer, the PC holds either the address

    of the instruction being executed, or the address of the next instruction to be executed.

    - cpsr ( the current program status register) . It contains the current value of the condition code bits ( N, Z, C and V)

    and 8 system status bits.

    and privileged modes can also access

    - a particular spsr ( saved program status register ) which stores the current value of CPSR when an exception

    occurs, so that it can be restored after handling the exception.

    Figure 10: Program Status Register

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    14/30

    13

    There are :

    Condition Code Flag which are copies from the ALU status flags Mode Bits , M[4:0] define the processor mode Interrupt Disable bits : I=1, disables the IRQ and F=1, disables the FIQ

    6.2. Context save:

    The first step of interrupt handling consists in preparing and saving their content in the IRQ stack. Once

    these registers are freed and ready to be used, the interrupt to be launched is loaded. The figure below shows the

    different program stages. First of all, the link register doesn't hold the right return address as the program counter is

    already fetching the next instruction from memory. This address is therefore adjusted. It is also stored in the IRQ

    stack. SPSR which contains the current value of CPSR has to be saved in the task using a work register : r14 which

    was just freed. R0 will be used to save other registers and is therefore saved in the IRQ stack.

    Figure 11: Context save sequence

    The next step consists in indicating which interrupt has to be launched. The address of the latter is loaded.

    The entry point of the interrupt handling is set in r14. Subsequently the interrupt is enabled by switching in

    Supervisor Mode. Then the scratch/used registers and lr are saved in svc stack. Finally the interrupt function is

    launched by branching to the address holds by r0.

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    15/30

    14

    Loads interrupt

    address

    Enables

    Interrupt and

    switches in

    Supervisor

    Mode

    Saves

    registers and

    LR in SVC

    stack

    Stores pc in

    r14

    Executes r0

    Figure 12: Context save sequence

    The figure below shows the context save sequence. Once the interrupt function ends, the registers are

    restored from supervisor stack and interrupts disabled. The mode chosen is the IRQ mode. EOICR means End of

    Interrupt Command Register and is the exit point of the interrupt handling. The AIC has to know when the current

    interrupt handling is over. This is done by writing in AIC_EOICR. The AIC restores the previous interrupt level if

    there was an ongoing one. An idle interrupt can then be handled. In our case, this ends the interrupt.

    All the registers stored in the IRQ stack can be restored: r14, SPSR and r0. The last instruction return to the

    program running before the interrupt occurred.

    Restores

    registers and

    LR from SVC

    Stack

    Disables

    Interrupt and

    switches back

    in IRQ Mode

    End of

    interrupt on

    the AIC

    Restores

    SPSR and r0

    from IRQ stack

    Restores

    LR_irq from

    IRQ stack in

    PC

    Figure 13: Context restoration sequence

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    16/30

    15

    .

    Figure 14: Exception and registers

    The figure above sums up the different steps concerning the registers during an interrupt.

    However, this whole sequence only handles interrupts but not multitasking. That is why a work had to be

    done on the stacks.

    IRQ MODESVC MODE

    Return address calculated from SVC mode

    PC value and stored in IRQ mode LR

    Use SVC mode CPSR copied to IRQ mode SPSR

    SPSR_IRQ

    CPSR

    SPSR_IRQ

    CPSR

    INTERRUPT

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    17/30

    16

    7. Work on the system stack:

    7.1. Different stacks:

    In the AT91SAM7X, six different tasks are used:

    The user stack which is use for the normal program execution state or for the operating system. The supervisor stack which is in a protected mode for the operating system, it is used during an interrupt. The third is abort mode stack which implements virtual memory and memory protection. The undefined mode stack design for supporting software emulation of hardware coprocessors. The IRQ stack which use for classical interrupt. The FIQ stack used when interrupt are chosen as fast interrupt.

    In our case tasks are managed with an interrupt, that is why only two stacks are useful, the IRQ stack and

    the supervisor stack. In fact when an interrupt occurs the stack is automatically set in the IRQ mode then turn to the

    supervisor mode as it can be seen in the assembler file.

    7.2. Tasks context management:

    In order to save the entire context in the supervisor stack, the IRQ stack must be copied each time a

    scheduler interrupt occurs. Before change the task context, three registers (R0, lr, pc) which are saved in the IRQ

    stack, have to be stored in the Supervisor stack. Conversely, before the end of an interrupt, these registers which are

    in the supervisor stack must be copied in the IRQ stack.

    7.2.1. Scheduler running:

    First the scheduler has two main aims. It starts tasks which are created (Create_Task) and ready to be

    launching (Launch_Task). The second goal is to switch between tasks which are running.

    Figure 15: Interrupt sequence

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    18/30

    17

    In this figure the two main steps can be seen. When task are starting, the IRQ stack increases. In fact during

    the scheduler interrupt a task is launched so the end of the interrupt does not occur consequently the IRQ stack does

    not fulfil. During the second step, tasks are running but the interrupt change the task but this time the end of

    interrupt occurs so the IRQ stack decreases at the end of the interrupt.

    7.2.2. Context management:

    As explained previously there is two working stack. Each time an interrupt occur all these two stacks are

    fulfilled. In order to manage these two stacks the assembly language is used because we need a low level

    programming language to operate action on registers. In fact when a scheduler interrupt occurs the stack pointer

    needs to be modify to change the context for the next task. Moreover the three registers saved in the IRQ stack

    must be copied into the supervisor stack before changing the context.

    stack pointer

    stack pointer

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    19/30

    18

    These figures show the three steps when a task runs for the first time and scheduler interrupt occurs. Thetwo middle figures show the save of the context. The last one show when the copy of the IRQ stack is performed.Then the stack pointer is changed to the next task stack.

    stack pointer

    stack pointer

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    20/30

    19

    The new task can be launched. The same actions occur and the new context is created.

    In this example only two tasks has been initialized so the stack pointer is not set to a free task but at the topof the task1 stack. Before launching task1 IRQ stack has to be change, so the task one irq stack is copied into the

    IRQ stack.

    stack pointer

    stack pointer

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    21/30

    20

    Then the task1 is launching. This operation is done at each stack change.

    stack pointer

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    22/30

    21

    8. Example of use:

    8.1. Simple program:

    Two simple led function:

    voi d l ed1 ( voi d ){

    unsi gned i nt wai t i ng_t i me ;

    i nt f l ag =0;

    i nt i ;

    whi l e( 1)

    {

    f or( wai t i ng_t i me = 0; wai t i ng_t i me < LedSpeed; wai t i ng_t i me++) ;

    i f ( f l ag == 0)

    {

    f l ag = 1;

    BASE_PI O_LED- >PI O_SODR = LED1 ;

    }

    el se i f ( f l ag == 1){

    f l ag = 0;

    BASE_PI O_LED- >PI O_CODR = LED1;

    }

    }

    }

    voi d l ed2 ( voi d )

    {

    unsi gned i nt wai t i ng_t i me ;

    i nt f l ag =0;

    i nt i ;

    whi l e( 1)

    {

    f or( wai t i ng_t i me = 0; wai t i ng_t i me < LedSpeed; wai t i ng_t i me++) ;

    i f ( f l ag == 0)

    {

    f l ag = 1;

    BASE_PI O_LED- >PI O_SODR = LED1 ;

    }

    el se i f ( f l ag == 1)

    {

    f l ag = 0;

    BASE_PI O_LED- >PI O_CODR = LED1;

    }}

    }

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    23/30

    22

    8.2. Use programs in multitasking:

    The first step is to create a variable to store the number of the task, and the task structure must be

    initializing. Then the task has to be created. Next tasks have to be launch. To finish the scheduler is launching.

    Conclusion:

    The multitasking environment is now operational, some options have been added since the beginning of the

    project. It is now possible to finish a task and to start and restart tasks. But some correction must be added: there isa leak of memory in the IRQ stack. Another drawback is that a minimum of one task must be active when an

    interrupt occurs.

    The next step to lead an operating system is the management of shared resources (memory, pins )

    between tasks. Semaphores can be added to conduct on this way.

    i nt mai n( ){

    I nt t ask[2] ;

    I ni t_Str uct ( 2) ;

    Task[ 0] =

    Cr eat e_Task(l ed1) ;

    Task[ 1] = Cr eat e_Task( l ed2) ;

    Launch_Task( t ask[ 0] ) ;

    Launch_Task( t ask[ 1] ) ;

    St ar t _Schedul er ( ) ;

    / / i nf i ni te l oop

    f or ( ; ; )

    {

    }}

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    24/30

    23

    Appendix: source codes

    multitask.h1 / *2 f i l ename : mul t i t ask. h

    3 multitask environnement for AT91SAM7X controller4 ENSEI RB- MATMECA567 Not oper ati onnal8 ver si on date who f r om9 0. 0 2010- 11- 12 ( yb) f r omscr at ch10 0. 1 2010- 11- 26 j sm f r om 0. 011 0. 2 2010- 12- 09 j sm f r om 0. 112 f i nal 2010- 01- 2613 */1415 / / Const ant s16 #def i ne NB_TASKS 10 / / number of t asks t o be managed ( l ess t han 11)

    171819 / / Er r or Messages20 #def i ne E_RUNNI NG_SCHED - 121 #def i ne E_NO_SPACE_LEFT - 222 #def i ne E_UNI NI T_TASK - 1023 #def i ne E_ACTI VE_TASK - 1124 #def i ne E_SLEEPI NG_TASK - 12252627 extern int I ni t _St ruct ( int n) ;28 / / i ni t i al i zes dat a st r uctur es t o i mpl ement n par r al l el t asks29 / / must be t he f i r st f uncti on cal l ed.30 / / cannot be cal l ed f r om a task31 / / er ases al l pr evi ous dat a when cal l ed

    32 / / err or messages33 / / - 1 : cal l ed af t er schedul er st art ( E_RUNNI NG_SCHED)3435 int Cr eat e_Task( void ( *t ask_f unc) ( void) ) ;36 / / i ni t i al i zes a task wi t h t he functi on gi ven i n ar gument37 / / r et ur ns t he i d number of t he new t ask ( posi t i ve val ue) or an er r or ( negat i ve val ue)38 / / t he f unct i on gi ven i n ar gument must not r eturn39 / / er r or messages :40 / / - 1 : cal l ed af t er schedul er st art ( E_RUNNI NG_SCHED)41 / / - 2 : no room f or new t ask ( E_NO_SPACE_LEFT)4243 extern int St art _Schedul er( ) ;44 / / actual l y st ar t s the schedul er45 / / 0 means success46 / / err or messages47 / / - 1 : cal l ed af t er schedul er st art ( E_RUNNI NG_SCHED)484950 extern int Wake_ Task( int n) ;51 / / moves a t ask f r om sl eepi ng t o act i ve st at e52 / / 0 means success53 / / e r ro r s :54 / / - 10 : Task Not i ni t i al i zed ( E_UNI NI T_TASK)55 / / - 11 : Act i ve Task ( E_ACTI VE_TASK)5657 extern int Scot ch_Task( int n) ;58 / / moves a t ask f r om act i ve t o sl eepi ng st at e59 / / 0 means success60 / / e r ro r s :

    61 / / - 10 : Task Not i ni t i al i zed ( E_UNI NI T_TASK)62 / / - 12 : Sl eepi ng Task ( E_SLEEPI NG_TASK)63 int Launch_Task( int t ask_number ) ;

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    25/30

    24

    64 / / Rel unch an exi st i ng unused t ask wi t h an r ei ni t i al i zi ng a i t s own st ack65 / / Ret ur n 0 i f succes66 / / e r ro r s :67 / / - 14 : Task doesn' t exi st ( E_TASK_NO_EXI STI NGG)68 / / - 15 : Task not i n unused st ate( E_TASK_RUNNI NG)69

    multitask.c1 / *2 f i l ename : mul t i t ask. c3 mul t i t ask envi r onnement f or AT91SAM7X cont rol l er4 ENSEI RB- MATMECA567 oper at i onnal8 ver si on date who f r om9 0. 0 2010- 11- 12 ( yb) f r omscr at ch10 0. 1 2010- 11- 19 r d f r om0. 011 0. 2 2010- 11- 21 j sm f r om 0. 112 0. 3 2010- 11- 26 j sm f r om 0. 2

    13 0. 4 2010- 11- 26 yb f r om0. 314 0. 5 2010- 12- 09 r d f r om0. 415 0. 6 2010- 12- 10 al l f r om 0. 516 f i nal 2010- 01- 2617 */1819 / / I ncl ude St andard f i l es20 #i ncl ude 21 #i ncl ude " i ncl ude/ AT91SAM7X- EK. h"2223 #i ncl ude "Mul t i _t ask. h"2425 / / t ask stat e def i ni t i ons26 #def i ne UNUSED 027 #def i ne SLEEPI NG 128 #def i ne ACTI VE 229 #def i ne STARTI NG 33031 / / Er r or Messages32 #def i ne E_RUNNI NG_SCHED - 133 #def i ne E_NO_SPACE_LEFT - 234 #def i ne E_NO_I NI T - 335 #def i ne E_NO_FUNCTI ON - 436 #def i ne E_UNI NI T_TASK - 1037 #def i ne E_ACTI VE_TASK - 1138 #def i ne E_SLEEPI NG_TASK - 1239 #def i ne E_TASK_NO_EXI STI NG - 1440 #def i ne E_TASK_RUNNI NG - 1541

    42 / / Const ant s43 #def i ne DATA_RAM 32000 / / si ze of RAM used f or t asks i n byt es44 #def i ne TASK_SI ZE ( DATA_RAM/ 4) / NB_TASKS / / amount of RAM per t ask i n i nt ( assumi ng t hat1i nt =4bytes. . . ; - ) )454647 typedef struct s_t ask_t ype / / st r ucture that def i nes a t ask48 {49 int num; / / t ask number50 int state; / / t ask stat e51 void ( *add_f ct ) ( void) ; / / addr ess of t he associ at e f unct i on52 void* st ack_bot t om; / / addr ess of t he f i r st ( ol der ) st ack el ement53 void* st ack_t op; / / addr ess of t he f i r st f r ee st ack el ement54 void* stack_l i mi t ; / / addr ess of t he end of st ack sect i on55 } t ask_t ;

    565758 AT91_REG save_sp; / / st ack poi nt er addr ess

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    26/30

    25

    59 AT91_REG *psave_sp = &save_sp;60 AT91_REG *pi nt _sp = NULL;61 AT91_REG i nt _sp;62 int nb_t ask_r unni ng = 0;63 int act ual _nb_t asks = 0; / / number of i ni t i al i zed t asks64 int sl eepi ng[ NB_TASKS] ; / / ar r ay of sl eepi ng t asks65 int acti ve[ NB_TASKS] ; / / ar ray of acti ve t asks66 int unused[ NB_TASKS] ; / / arr ay of not i ni t i al i zed t asks67 int start i ng[ NB_TASKS] ; / / ar r ay of not sl eepi ng t asks

    68 t ask_t t asks[ NB_TASKS] ; / / ar r ay of al l manageabl e t asks69 int t asks_RAM[ NB_TASKS] [TASK_SI ZE] ; / / t hi s t abl e cont ai ns dat a ar ea f or t asks70 int t ask_r unni ng = 0; / / cur ent l y runni ng t ask71 int st at e_mul t i t ask = 0; / / 0 when st r uct i s not i ni t , 1 when st r uct i s i ni t , 2 whenschedul er i s r unni ng72 int schedul er _st ar t ed;73 char pr emi er = 2;7475 void I Tsched( ) ;767778 int I ni t _St ruct ( int n)79 / / i ni t i al i zes dat a st r uctur es t o i mpl ement n par r al l el t asks80 / / must be t he f i r st f uncti on cal l ed.81 / / cannot be cal l ed f r om a task82 / / er ases al l pr evi ous dat a when cal l ed83 / / err or messages84 / / - 1 : cal l ed af t er schedul er st art ( E_RUNNI NG_SCHED)85 {86 int i = 0;8788 if ( schedul er _st ar t ed)89 return E_RUNNI NG_SCHED;9091 for ( i =0 ; i

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    27/30

    26

    127128 / / i f schedul er i s al r eady r unni ng129 if ( st at e_mul t i t ask == 2)130 return E_RUNNI NG_SCHED;131132 / / i f al l the tasks are i ni t i al i zed133 if ( act ual _nb_t asks == NB_TASKS)134 return E_NO_SPACE_LEFT;135

    136 t asks[ act ual _nb_t asks] . state = UNUSED;137 t asks[ act ual _nb_t asks] . add_f ct = t ask_f unc;138139 start i ng[ act ual _nb_t asks] = 1;140 act ual _nb_t asks++;141142 return ( act ual _nb_t asks- 1) ;143 }144145146147 int St art _Schedul er( )148 / / actual l y st ar t s the schedul er149 / / er r or messages :150 / / - 3 : dat a not i ni t i al i zed ( E_NO_I NI T)151 / / - 4 : no f unct i on t o run ( E_NO_FUNCTI ON)152 {153 / / i f st ruct i s not i ni t154 if ( st at e_mul t i t ask == 0)155 return E_NO_I NI T;156157 / / i f no f unct i ons are i ni t i al i zed158 if ( act ual _nb_t asks == 0)159 return E_NO_FUNCTI ON;160161 / / TC0 Conf i gur at i on162 AT91C_BASE_PMC - > PMC_PCER = ( 1 AI C_I DCR = ( 1 AI C_SMR[ AT91C_I D_TC0] = ( AT91C_AI C_PRI OR_HI GHEST) |

    ( AT91C_AI C_SRCTYPE_EXT_LOW_LEVEL) ; / / AI C Conf i gur at i on165 AT91C_BASE_AI C - > AI C_SVR[ AT91C_I D_TC0] = ( unsigned int) I Tsched; / / Def i ne i nt er r uptf uncti on166 AT91C_BASE_TC0 - >TC_CMR = AT91C_TC_CLKS_TI MER_DI V5_CLOCK | AT91C_TC_CPCTRG; / / TC0cl ock conf i gur e at 199691 Hz and aut o reset of t he count er167 AT91C_BASE_TC0 - >TC_CCR = AT91C_TC_CLKEN; / / TC0 cl ock enabl e168 AT91C_BASE_TC0 - >TC_I ER = AT91C_TC_CPCS; / / TC0 i nt er r upt t ype169 AT91C_BASE_TC0 - >TC_RC = 2000; / / 2000/ 199691=10ms bet ween each i nter r upt170 AT91C_BASE_TC0 - >TC_CCR = AT91C_TC_SWTRG;171 AT91C_BASE_AI C - > AI C_I ECR = ( 1

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    28/30

    27

    195196 return E_UNI NI T_TASK;197 }198199200201 int Scot ch_Task( int n)202 / / moves a t ask f r om act i ve t o sl eepi ng st at e203 / / 0 means success

    204 / / e r ro r s :205 / / - 10 : Task Not i ni t i al i zed ( E_UNI NI T_TASK)206 / / - 12 : Sl eepi ng Task ( E_SLEEPI NG_TASK)207 {208 if ( act i ve[ n] == 1)209 {210 t asks[ n] . state = SLEEPI NG;211 sl eepi ng[ n] = 1;212 act i ve[ n] = 0;213 return 0;214 }215216 if ( sl eepi ng[ n] == 1)217 return E_SLEEPI NG_TASK;218219 return E_UNI NI T_TASK;220 }221222223 int Launch_Task( int t ask_number )224 / / Rel unch an exi st i ng unused t ask wi t h an r ei ni t i al i zi ng a i t s own st ack225 / / Ret ur n 0 i f succes226 / / e r ro r s :227 / / - 14 : Task doesn' t exi st ( E_TASK_NO_EXI STI NGG)228 / / - 15 : Task not i n unused st at e( E_TASK_RUNNI NG)229230 {231 if( t ask_number >= act ual _nb_t asks)232 return E_TASK_NO_EXI STI NG;

    233 if( t asks[ t ask_number ] . state == SLEEPI NG| | t asks[ t ask_number ] . state == ACTI VE | |t asks[ t ask_number ] . state == STARTI NG)234 return E_TASK_RUNNI NG;235 tasks[ t ask_number ] . st ack_t op = t asks[ t ask_number ] . st ack_bot t om; / / rei ni t i al i z i ng s tack236237 tasks[ t ask_number ] . state = STARTI NG; / / Task ready to be st ar t238239 sl eepi ng[ t ask_number ] = 0;240 act i ve[ t ask_number ] = 0;241 unused[ t ask_number ] = 0;242 st ar t i ng[ t ask_number ] = 1;243244 return 0;245246 }

    247248249250 void I Tsched( )251 / / t hi s f uncti on i s i nt ent ed t o be r un as an i nt er r upt252 / / and i mpl ement s t he schedul er253 {254 int i = t ask_r unni ng;255256 / / Sear ch f or t he next acti ve or st ar t i ng t ask257 do258 {259 i ++;260 if ( i > NB_TASKS- 1)

    261 i = 0;262 } while ( ( act i ve[ i ] ! = 1) && ( s tart i ng[ i ] ! = 1) ) ;263264 / / Di sabl e i nt er r upt

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    29/30

    28

    265 AT91C_BASE_AI C- >AI C_I DCR = 1 AI C_I MR; / / Store St at us of al li nt er r upt267 AT91C_BASE_AI C - > AI C_I DCR = 0xFFFFFFFF; / / Di sabl e al l i nt err upt268 AT91C_BASE_TC0 - >TC_SR; / / Read t he St atus Regi st er t o empt y the I nt err upt Regi st er269270 / / i f next task i s "start i ng"271 / / change t ask to "act i ve"272 / / r emove I T mode

    273 / / l aunch f uncti on274 / / i nf i ni te l oop275276 / / SP modi f i cat i on277 / / commande asm278 / / i f ( j < NB_TASKS+1)279 {280 / / asm( "MOV save_sp, sp") ;281 if( premi er

  • 8/13/2019 Multitasking on AT91SAM7X Microcontroller

    30/30

    334 "l dr r 3, i nt _sp \ n"335 " l dr r 2, [ r 2] \ n"336 "str r 2, [ r 3] \ n" ) ;337 save_sp += 4;338 i nt _sp += 4;339 }340 asm( "l dr r 2, save_sp \ n" / / Change st ack341 "mov sp, r 2 \ n") ;342 premi er - - ;

    343 }344345 / / Enabl e i nt er rupt346 AT91C_BASE_AI C - > AI C_I ECR = i nt er r upt _sr ; / / Restore status of al l i nt er r upt347 AT91C_BASE_AI C - > AI C_I ECR = 1 AI C_EOI CR = 0; / / The f uncti on i s not an i nt er r upt f uncti onanymor e356 nb_t ask_r unni ng++;357 / / Launch_Funct i on( ( t asks[t ask_runni ng] . add_f ct ) ) ; / / Go t o t he new f unct i on358 ( tasks[ t ask_r unni ng] . add_f ct ) ( ) ;359 t asks[ t ask_r unni ng] . state = UNUSED; / / I n case of r et ur n f r om t he task (STOP)360 act i ve[ t ask_r unni ng] = 0;361 unused[ t ask_r unni ng] = 1;362 while( 1) {}363 }364 }365