This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADC start trigger and CLA task trigger based on F28069 and SYS BIOS

Other Parts Discussed in Thread: SYSBIOS

HI,Sir!

I want to use CLA-C as loop control, the process is:

1. select CPU timer(0,1or2), one of them , working as peroid and continuous mode, as ADC start trigger source

 all ADC channel will be sample an converted by Sequence method. 

2 start the cpu timer, and then it will start ADC sampling and converting

3. after all channel ADC result are ready, ADC module generate ADCINT1 interrupt

4. CLA task1 will be triggered by ADCINT1(of course, CLA task1 trigger by ADCINT1 mode)

I have a look some  CLA-C demo project, such like iir2p2z, I have some question:

question A.

this CPU Timer  for ADC starting trigger source, Does SYS BIOS need to deal CPU timer interrupt? if I disable CPU timer interrupt, can it trigger ADC sample and convert? 

question B.

How to modify  the following code that copied from iir2p2z_main.c  for my SYSBIOS project? please see red code

The following  is the original  code

/* Assign user defined ISR to the PIE vector table */
EALLOW;
PieVectTable.CLA1_INT1 = &cla1_task1_isr;
PieVectTable.CLA1_INT2 = &cla1_task2_isr;
PieVectTable.CLA1_INT3 = &cla1_task3_isr;
PieVectTable.CLA1_INT4 = &cla1_task4_isr;
PieVectTable.CLA1_INT5 = &cla1_task5_isr;
PieVectTable.CLA1_INT6 = &cla1_task6_isr;
PieVectTable.CLA1_INT7 = &cla1_task7_isr;
PieVectTable.CLA1_INT8 = &cla1_task8_isr;
EDIS;

//Copy over the CLA code(if running in standalone mode from FLASH)
memcpy(&Cla1funcsRunStart, &Cla1funcsLoadStart, (Uint32)&Cla1funcsLoadSize);
//Copy over the CLA math tables(if running in standalone mode from FLASH
//and using the CLAMath Library)
//memcpy(&Cla1mathTablesRunStart, &Cla1mathTablesLoadStart, (Uint32)&Cla1mathTablesLoadSize);

/* Compute all CLA task vectors */
EALLOW;
Cla1Regs.MVECT1 = (Uint16)((Uint32)&Cla1Task1 -(Uint32)&Cla1Prog_Start);
Cla1Regs.MVECT2 = (Uint16)((Uint32)&Cla1Task2 -(Uint32)&Cla1Prog_Start);
Cla1Regs.MVECT3 = (Uint16)((Uint32)&Cla1Task3 -(Uint32)&Cla1Prog_Start);
Cla1Regs.MVECT4 = (Uint16)((Uint32)&Cla1Task4 -(Uint32)&Cla1Prog_Start);
Cla1Regs.MVECT5 = (Uint16)((Uint32)&Cla1Task5 -(Uint32)&Cla1Prog_Start);
Cla1Regs.MVECT6 = (Uint16)((Uint32)&Cla1Task6 -(Uint32)&Cla1Prog_Start);
Cla1Regs.MVECT7 = (Uint16)((Uint32)&Cla1Task7 -(Uint32)&Cla1Prog_Start);
Cla1Regs.MVECT8 = (Uint16)((Uint32)&Cla1Task8 -(Uint32)&Cla1Prog_Start);
EDIS;

// Step 3 : Mapping CLA tasks
/* All tasks are enabled and will be started by an ePWM trigger
* Map CLA program memory to the CLA and enable software breakpoints
*/
EALLOW;
Cla1Regs.MPISRCSEL1.bit.PERINT1SEL = CLA_INT1_NONE;
Cla1Regs.MPISRCSEL1.bit.PERINT2SEL = CLA_INT2_NONE;
Cla1Regs.MPISRCSEL1.bit.PERINT3SEL = CLA_INT3_NONE;
Cla1Regs.MPISRCSEL1.bit.PERINT4SEL = CLA_INT4_NONE;
Cla1Regs.MPISRCSEL1.bit.PERINT5SEL = CLA_INT5_NONE;
Cla1Regs.MPISRCSEL1.bit.PERINT6SEL = CLA_INT6_NONE;
Cla1Regs.MPISRCSEL1.bit.PERINT7SEL = CLA_INT7_NONE;
Cla1Regs.MPISRCSEL1.bit.PERINT8SEL = CLA_INT8_NONE;
Cla1Regs.MIER.all = 0x00FF;
EDIS;


/* Enable CLA interrupts at the group and subgroup levels */
PieCtrlRegs.PIEIER11.all = 0xFFFF;
IER = (M_INT11 );
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM

/* Switch the CLA program space to the CLA and enable software forcing
* Also switch over CLA data ram 0,1 and 2
* CAUTION: The RAMxCPUE bits can only be enabled by writing to the register
* and not the individual bit field. Furthermore, the status of these bitfields
* is not reflected in either the watch or register views - they always read as
* zeros. This is a known bug and the user is advised to test CPU accessibilty
* first before proceeding
*/
EALLOW;
Cla1Regs.MMEMCFG.all = CLA_PROG_ENABLE|CLARAM0_ENABLE|CLARAM1_ENABLE|CLARAM2_ENABLE|CLA_RAM1CPUE;
Cla1Regs.MCTL.bit.IACKE = 1;
EDIS;

 

Tjhis is my code: 

Because My code will start from flash memory.

/* Assign user defined ISR to the PIE vector table */

/*  comment the following code ,because it shall be done by SYS BIOS, HWI ISR can be used  

//EALLOW;
//PieVectTable.CLA1_INT1 = &cla1_task1_isr;
//PieVectTable.CLA1_INT2 = &cla1_task2_isr;
//PieVectTable.CLA1_INT3 = &cla1_task3_isr;
//PieVectTable.CLA1_INT4 = &cla1_task4_isr;
//PieVectTable.CLA1_INT5 = &cla1_task5_isr;
//PieVectTable.CLA1_INT6 = &cla1_task6_isr;
//PieVectTable.CLA1_INT7 = &cla1_task7_isr;
//PieVectTable.CLA1_INT8 = &cla1_task8_isr;
//EDIS;

/* un-comment memcpy code, because my code will start from flash memory

//Copy over the CLA code(if running in standalone mode from FLASH)
memcpy(&Cla1funcsRunStart, &Cla1funcsLoadStart, (Uint32)&Cla1funcsLoadSize);
//Copy over the CLA math tables(if running in standalone mode from FLASH 
//and using the CLAMath Library)
memcpy(&Cla1mathTablesRunStart, &Cla1mathTablesLoadStart, (Uint32)&Cla1mathTablesLoadSize);

/* Compute all CLA task vectors */ 
EALLOW;
Cla1Regs.MVECT1 = (Uint16)((Uint32)&Cla1Task1 -(Uint32)&Cla1Prog_Start);
Cla1Regs.MVECT2 = (Uint16)((Uint32)&Cla1Task2 -(Uint32)&Cla1Prog_Start);
Cla1Regs.MVECT3 = (Uint16)((Uint32)&Cla1Task3 -(Uint32)&Cla1Prog_Start);
Cla1Regs.MVECT4 = (Uint16)((Uint32)&Cla1Task4 -(Uint32)&Cla1Prog_Start);
Cla1Regs.MVECT5 = (Uint16)((Uint32)&Cla1Task5 -(Uint32)&Cla1Prog_Start);
Cla1Regs.MVECT6 = (Uint16)((Uint32)&Cla1Task6 -(Uint32)&Cla1Prog_Start);
Cla1Regs.MVECT7 = (Uint16)((Uint32)&Cla1Task7 -(Uint32)&Cla1Prog_Start);
Cla1Regs.MVECT8 = (Uint16)((Uint32)&Cla1Task8 -(Uint32)&Cla1Prog_Start);
EDIS;

// Step 3 : Mapping CLA tasks
/* All tasks are enabled and will be started by an ePWM trigger
* Map CLA program memory to the CLA and enable software breakpoints
*/
EALLOW;

/* CLA TASK1 triggered by CLA_INT1_ADCINT1


Cla1Regs.MPISRCSEL1.bit.PERINT1SEL = CLA_INT1_ADCINT1;

Cla1Regs.MPISRCSEL1.bit.PERINT2SEL = CLA_INT2_NONE;
Cla1Regs.MPISRCSEL1.bit.PERINT3SEL = CLA_INT3_NONE;
Cla1Regs.MPISRCSEL1.bit.PERINT4SEL = CLA_INT4_NONE;
Cla1Regs.MPISRCSEL1.bit.PERINT5SEL = CLA_INT5_NONE;
Cla1Regs.MPISRCSEL1.bit.PERINT6SEL = CLA_INT6_NONE;
Cla1Regs.MPISRCSEL1.bit.PERINT7SEL = CLA_INT7_NONE;
Cla1Regs.MPISRCSEL1.bit.PERINT8SEL = CLA_INT8_NONE;
Cla1Regs.MIER.all = 0x00FF;
EDIS; 


/* Enable CLA interrupts at the group and subgroup levels */

 // shall be commented? because of SYS BIOS

/*
PieCtrlRegs.PIEIER11.all = 0xFFFF;                                                 
IER = (M_INT11 );                                                                                 
EINT; // Enable Global interrupt INTM                                              
ERTM; // Enable Global realtime interrupt DBGM

*/

/* Switch the CLA program space to the CLA and enable software forcing
* Also switch over CLA data ram 0,1 and 2
* CAUTION: The RAMxCPUE bits can only be enabled by writing to the register
* and not the individual bit field. Furthermore, the status of these bitfields
* is not reflected in either the watch or register views - they always read as 
* zeros. This is a known bug and the user is advised to test CPU accessibilty
* first before proceeding
*/
EALLOW;
Cla1Regs.MMEMCFG.all = CLA_PROG_ENABLE|CLARAM0_ENABLE|CLARAM1_ENABLE|CLARAM2_ENABLE|CLA_RAM1CPUE;
Cla1Regs.MCTL.bit.IACKE = 1;
EDIS;


  • HI!

    I had ported iir2p2z to my project. the following is new code.

    //###########################################################################
    // Description:
    //
    // Task 1: 2 pole 2 zero IIR filter
    // Task 8: Delay Element Variable Initialization
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    //###########################################################################

    #include "F2806x_Device.h" // F2806x Headerfile Include File

    //Task 1 (C) Variables
    #pragma DATA_SECTION(S1_B,"dataRAM")
    float S1_B[];//={0.02008, 0.04017, 0.02008};
    #pragma DATA_SECTION(S1_A,"dataRAM")
    float S1_A[];//={1.0, 1.56102, -0.64135};
    #pragma DATA_SECTION(xn,"CpuToCla1MsgRAM")
    float xn;
    #pragma DATA_SECTION(yn,"Cla1ToCpuMsgRAM")
    float yn;

    //Variables global to all CLA tasks only
    float W2[2]; //w2(n) and w2(n-1)
    float W1[2]; //w1(n) and w1(n-1)

    //Task 1 : 2p2z IIR Transposed Direct Form II Filter
    // ALGORITHM:
    //
    // Difference Equation :
    //
    // The operations for each biquad, in order, is as follows
    // 1. yn = xn*b(0) + q4
    // 2. q3 = xn*b(1) + yn*a(1) + q2
    // 3. q4 = q3
    // 4. q1 = xn*b(2) + yn*a(2)
    // 5. q2 = q1
    // where
    // yn =output sample of the filter at index n
    // xn =input sample of the filter at index n
    // qx =intermediate values stored in the delay buffer
    //
    // Transfer Function :
    // The difference equation is split up into multiple Second-Order Sections(SOS)
    // Each SOS represents a Biquad with the following transfer function
    // -1 -2
    // Y(z) b(0) + b(1) z + b(2) z
    // ----- = -----------------------
    // X(z) -1 -2
    // a(0) + a(1) z + a(2) z
    //
    // For a detailed treatment of Direct II Forms see
    // [1]Digital Signal Processing, Proakis, J. G. and Manolakis, D. G. - Chapter 7
    // [2]Understanding Digital Signal Processing 3rd ed, Lyons, R. G.
    //
    // Network Diagram :
    //
    // xn------>(x)--->(+)--------------->yn
    // | ^ ^ |
    // | | |q4 |
    // | b(0) (z) |
    // | ^ |
    // | |q3 |
    // |-->(x)--->(+)<-----(x)---|
    // | ^ ^ ^ |
    // | | |q2 | |
    // | b(1) (z) a(1) |
    // | ^ |
    // | |q1 |
    // --->(x)--->(+)<-----(x)----
    // ^ ^
    // | |
    // b(2) a(2)
    //__interrupt void Cla1Task1 ( void )
    void Cla1Task1 ( void )
    {
    //Local Variables

    //Code
    __mdebugstop();
    yn = xn*S1_B[0] + W2[1];
    W2[0] = xn*S1_B[1] + yn*S1_A[1] + W1[1];
    W2[1] = W2[0];
    W1[0] = xn*S1_B[2] + yn*S1_A[2];
    W1[1] = W1[0];
    // __mnop();
    // __mnop();
    // __mnop();
    }

    //__interrupt void Cla1Task2 ( void )
    void Cla1Task2 ( void )
    {

    }
    //__interrupt void Cla1Task3 ( void )
    void Cla1Task3 ( void )
    {

    }
    //__interrupt void Cla1Task4 ( void )
    void Cla1Task4 ( void )
    {

    }
    //__interrupt void Cla1Task5 ( void )
    void Cla1Task5 ( void )
    {

    }
    //__interrupt void Cla1Task6 ( void )
    void Cla1Task6 ( void )
    {

    }
    //__interrupt void Cla1Task7 ( void )
    void Cla1Task7 ( void )
    {

    }
    //Task 8 will initialize the variables used in Task 1
    //__interrupt void Cla1Task8 ( void )

    void Cla1Task8 ( void )
    {
    W2[0] = 0; W2[1] = 0;
    W1[0] = 0; W1[1] = 0;
    }

    Because CLA-C compiler does't support global init,so comment the S1_B and S1_A init para, and they can be initialied in Cla1task8 by  = operator.

    float S1_B[];//={0.02008, 0.04017, 0.02008};
    #pragma DATA_SECTION(S1_A,"dataRAM")
    float S1_A[];//={1.0, 1.56102, -0.64135};

    And I also delete __interrupt qualifier before all CLA1task,  because it can't be supported by SYSBIOS.

    some declaration about Uint64 ,balabala (F2806x_Usb.h) shall be comented. and Make all, it is OK. I will test this code in next few days.

  • I have another question;

    1. If some interrupt enable of MIER  are not set or disable, for example. MIER.1 = 0,CLA_INT1 is disable. can CLA1task1 also be triggered by its Peripheral Interrupt ADCINT1?  

    2. and if MIER.1 is enable, and CLA1_INT1 is generated. I want to know, MIFR is set while Peripheral Interrupt is coming or after Cla1Task1 run completely?

        

  • when CLA1_INT1 is generated ? the following said this interrupt generated after cla task run completely.

      

    But the following talking about MIFR say:

    So I want to know when CLA1_INT1 is generated?

    Thanks.

  • Hi, I will try to answer what I can but I don't know much about CLA specific items.  Which version of SYSBIOS are you using?

    A.  You might want to disable the Clock in SYSBIOS unless you need it.  The Clock will use one of the timers but I don't know for sure which one it will use.  You can disable the clock by doing the following in your configuration script:

    var BIOS = xdc.useModule('ti.sysbios.BIOS');
    BIOS.clockEnabled = false;

    B.  You can remove this code to setup the PIEVECT and use the Hwi manager to do it in your configuration script.  I believe for CLA items it starts at Hwi vector #112 to #119.

    Yes, comment out anything that deals with PIEVECT.

    Judah

  • Sorry, I don't know specifics about CLA registers.  I know more about SYSBIOS.  You might post your question to a C2000 specific forum to get those answers.

  • I study the spec about CLA and know more then before.

    1. MIER and MIFR registers are as for input trigger interrupt, if they are disable, you cannot do software trigger by IACK or any peripheral interrupt to wake up the CLA task.

    2. and after CLA task run completely (meet the MSTOP ) it can generate CLA1_INTx if this feature is enabled by PIEIER11 regsiter.

    3. About ADCINTx as the peripheral interrupt trigger source as CLA TASKx, because ADC module has a special mode called auto interrupt clear mode. so ADC module can work continuously and silently. no real interrupt occur for C28X and SYS BIOS do nothing as for ADCINTx.

    BUT, I still have another question about ADC SOC trigger selection:

    Whatever I select CPU TImer0,or PWMINT, how to config these module? for example, CPU timer0 shall be configured in period and continuous mode, but its interrupt shall be enabled or not? can the CPU timer trigger the ADC sampling and converting silently and SYS BIOS or HWI don't need involved?

      

  • I study ePWM SOC mode, it can be done for ADC SOC, and don't need interrupt isr.

  • Hi Decai,

    Thanks, your post helped me to think about my software design in more detail.  

    I just did a similar exercise to you and just got everything to work correctly.  I'm not sure if this will help, but a couple of things that I found useful are: 

    1.  I start an ADC SOC with software, in my main.c routine (a timer Hwi with SYSBIOS calls a Swi that contains AdcRegs.ADCSOCFRC1.bit.SOC1 = 1; ).  Then I use the ADCINT1 to trigger the CLA to run a task.  In the cla task I clear the ADC INT, with the following command: 

    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;

    2.  The cla uses a different compiler than the main processor.  It is a limited C compiler, with slightly different features.  Your cla source code, which is identified by the cla compiler when you put a .cla extension on your file, should use the interrupt keyword for cla tasks that you call through cla interrupts.  So for example, from your code:

    void Cla1Task1 ( void )
    {
    //Local Variables

    //Code
    __mdebugstop();
    yn = xn*S1_B[0] + W2[1];
    W2[0] = xn*S1_B[1] + yn*S1_A[1] + W1[1];
    W2[1] = W2[0];
    W1[0] = xn*S1_B[2] + yn*S1_A[2];
    W1[1] = W1[0];
    // __mnop();
    // __mnop();
    // __mnop();
    }

    I assume this file has a .cla extension.  You may want to use 

    interrupt void Cla1Task1 ( void )

    ...

    Once I did this, then my code worked great.

    Make sure to use this keyword in your header files also.  

    This is one of those tricky details to remember when mixing SYSBIOS code with cla code.  

    Best Regards,

    Rick