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.

The Task is pending in "driverLib" issue.

Other Parts Discussed in Thread: MSP430F6779, SYSBIOS

Hello ,

I use MSP430F6779 + TI-RTOS.

The system clock is 8Mhz, (tirtos_msp430_2_00_02_36)

Now, i have a task issue.

I create three task (A/B/C).

Three tasks, only to do LED twinkling.

Three tasks are working properly.

ex :

Void taskA(UArg arg0, UArg arg1)
{

for (;;) {

GPIO_toggle(LED_RED);
Task_sleep(10);
}
}

Void taskB(UArg arg0, UArg arg1)
{

for (;;) {

GPIO_toggle(LED_BLUE);

Task_sleep(10);
}
}

Void taskC(UArg arg0, UArg arg1)
{

for (;;) {

GPIO_toggle(LED_GREEN);

Task_sleep(10);
}
}

But , If the three tasks do not the same things.

ex :

The taskA to do Read/Write nand flash (SPI driverlib).

The taskB to do Read/Write eeprom (IIC driverlib).

The taskC to do Read/Write Terminal (UART driverlib).

execution a little time, taskA don't working, only taskB and taskC are working properly.

the taskA , call API(SPI_Transfer) is pending.

PS : All task Single execution, it's working properly.

What happen? How to do fix?

Thanks.

  • Hi Dunk,

       Can I see the code where you create your tasks and the code where you setup and use the SPI driver?  Also, your cfg file will also be useful to help me narrow down your problem.

    Thanks,

    Moses

  • Hi Moses,

    Please review this project. (Pending of DriverLib).

    I use 

    Code Composer Studio

    Version: 6.0.0.00190

    Thanks.

    2045.Pending of DriverLib.zip

  • Dunk,

        Looking at your code nothing stands out as a problem. Are you seeing any error messages or is task A just not returning from the SPI_transfer? When you halt the application in Task A, where in SPI_transfer is it pending? Remove the other tasks and run just Task A, does the same thing happen? Open ROV and got to the Task module's Detailed View, all your Tasks should be listed. Send me a screen capture of this Detailed View so that we can see if your task's are healthy?

    Let me know if you have any questions about any of these.

    Moses

  • Hi Moses,

    1, CCS compiler don't any error messages and in CCS debug mode is same. 

    2, How do know SPI_transfer is pending?

    Add hardware LED state,

    Before SPI_transfer start, the LED is turn on,

    After SPI_transfer end, the LED is turn off.

    If SPI_transfer is pending, the LED always turn on.

    3, Remove the other tasks and run just Task A, it is fine.

    4, ROV, task1 blockedOn is "unknow". 

    Tnaks.

  • Dunk,

     Looked at your code again and still don't see anything that stands out as being wrong. You say if you take out Task 2 and 3 it works? So then it's something in Task 2 and 3 that's causing it to fail. To narrow it down, test it with just Task 1 and 2. Next, run just Task 1 and 3. Let me know what happens.

    Also in the failing case, you said it doesn't return from SPI_transfer. From your code the first time SPI_transfer is called should be from: MAT_flsh_Test() -> MAT_flsh_Block_Erase() -> MAT_spi_transfer() -> SPI_transfer(). Is this the SPI_transfer that doesn't return or is it in subsequent SPI transfers from MAT_flsh_Page_Program() or MAT_flsh_Page_Read().

    Moses

  • Dear Moses

    It is strange that we test the SPI driver lib with clock 1MHz on F5528 and it works correctly.
    When we test SPI driver lib with clock 1MHz on F6779, the SPI hangs up at SPI_transfer within 10sec.
    But when we test SPI driver lib with clock 4MHz on F6779, the communication is better (doesn't hangs up for more than 5 minutes)

    F6779 uses eUSCI but F5438 uses USCI.
    I checked the spec on the attached migration guide, the major difference it bit rate.
    Do you have any ideal why SPI clock makes things different?

    We noted that there is a timer interrupt launched on RTOS.
    Is it possible that SPI communication is too slow which is interrupted by the timer interrupt below?

    Thanks for your comment.

    This is the interrupt we created:
    #if defined(__ICC430__)
    #pragma inline=never
    #endif
    extern Void MAT_isrDMA(UArg);
    #if defined(__ICC430__)
    #pragma vector = 50 * 2
    #else
    #pragma vector = 50;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi50(Void)
    {
    UInt taskKey;

    /* disable Task scheduler */
    taskKey = ti_sysbios_knl_Task_disable();

    /* switch stacks and then run the phase 2 function */
    ti_sysbios_family_xxx_Hwi_switchAndRunFunc(&ti_sysbios_family_msp430_Hwi50_p2);

    /* handle any Task re-scheduling as required */
    ti_sysbios_knl_Task_restoreHwi(taskKey);

    }

    Void ti_sysbios_family_msp430_Hwi50_p2(Void)
    {
    ti_sysbios_BIOS_ThreadType prevThreadType;
    UInt swiKey;

    /* disable Swi scheduler */
    swiKey = ti_sysbios_knl_Swi_disable();

    /* set thread type to Hwi */
    prevThreadType = ti_sysbios_BIOS_setThreadType(ti_sysbios_BIOS_ThreadType_Hwi);

    /* run ISR function */
    MAT_isrDMA(0);

    /* run any posted Swis */
    ti_sysbios_knl_Swi_restoreHwi(swiKey);

    /* restore thread type */
    ti_sysbios_BIOS_setThreadType(prevThreadType);

    }


    This is the timer interrupt RTOS created automatically:

    #if defined(__ICC430__)
    #pragma inline=never
    #endif
    extern Void ti_sysbios_family_msp430_Timer_periodicStub__E(UArg);
    #if defined(__ICC430__)
    #pragma vector = 55 * 2
    #else
    #pragma vector = 55;
    #endif
    __interrupt Void ti_sysbios_family_msp430_Hwi55(Void)
    {
    UInt taskKey;

    /* disable Task scheduler */
    taskKey = ti_sysbios_knl_Task_disable();

    /* switch stacks and then run the phase 2 function */
    ti_sysbios_family_xxx_Hwi_switchAndRunFunc(&ti_sysbios_family_msp430_Hwi55_p2);

    /* handle any Task re-scheduling as required */
    ti_sysbios_knl_Task_restoreHwi(taskKey);

    }

    Void ti_sysbios_family_msp430_Hwi55_p2(Void)
    {
    ti_sysbios_BIOS_ThreadType prevThreadType;
    UInt swiKey;

    /* disable Swi scheduler */
    swiKey = ti_sysbios_knl_Swi_disable();

    /* set thread type to Hwi */
    prevThreadType = ti_sysbios_BIOS_setThreadType(ti_sysbios_BIOS_ThreadType_Hwi);

    /* run ISR function */
    ti_sysbios_family_msp430_Timer_periodicStub__E(0);

    /* run any posted Swis */
    ti_sysbios_knl_Swi_restoreHwi(swiKey);

    /* restore thread type */
    ti_sysbios_BIOS_setThreadType(prevThreadType);

    }

    slaa522a.pdf
  • Hi Jeffrey,

        Sorry for just getting to this now. Regarding why the behavior changes with the SPI clock, I'm not really sure. I think you have give the MSP430 guys a shout. Regardless, I don't expect it to hang during a SPI transfer. Did you guys carry out the tests I asked earlier? Dunk said it worked well when only one task ran therefore it's probably something happening in the other tasks that affects it. Let's try to narrow it down.

    Thanks,

    Moses

  • Dear Moses

    It seems we got some progress here.

    When we add a Tasksleep (100) to make DMA rest for awhile, the CPU seems works well.

    Please just read the lines marked in red below:

    We believe this CPU hangs up issue due to DMA is too busy for previous task.

    Is there an official API or mechanism on TI RTOS which can check if DMA finished previous task and ready for next task?

    Or should we set up a flag here to check if DMA is ready?

    Adding a Tasksleep is not a good method I think.

    Thanks for your comment.

    #include "MAT_Driver.h"

    void MAT_flsh_init()

    {

     uint16_t Flsh_id, MFG_id;

     MAT_flsh_reset();

     MAT_flsh_st_ftr(FLSH_REG_BLCK_LCK,0x00); //set all block to unlock

     MFG_id=MAKEUINT(FLSH_ATO_MFG_ID,FLSH_25D1GA_DEV_ID);

     Flsh_id= MAT_flsh_RdId();

     /*

     if (Flsh_id == MFG_id) {

    MAT_UART_printf(1,"ATO_Flsh ok",11);

     }else {

      MAT_UART_printf(1,"Flsh fail",9);

      MAT_UART_putWORD(Flsh_id);

     }

     */

    }

    uint16_t MAT_flsh_RdId ()

    {

    // CyU3PReturnStatus_t status = CY_U3P_SUCCESS;

    uint8_t     txBuffer[4];

    uint8_t     rxBuffer[4];

    uint16_t Flsh_Id;

    //bool transferOK;

    /* status = CyFxSpiWaitForStatus ();

       if (status != CY_U3P_SUCCESS)

           return status;*/

    txBuffer[0] = CMD_READID; /* Read command. */

    txBuffer[1] = 0x00;

    Task_sleep(100);

    GPIO_write(GPIO_NAND_CS, 0);

    MAT_spi_transfer(MAT_SPIB0, txBuffer, rxBuffer, 4);

    GPIO_write(GPIO_NAND_CS, 1);

    Flsh_Id=rxBuffer[2];

    Flsh_Id=(Flsh_Id  <<8)+rxBuffer[3];

    return Flsh_Id;

    }

    void MAT_flsh_reset()

    {

    uint8_t     txBuffer[1];

    uint8_t     rxBuffer[1];

    txBuffer[0] = CMD_RESET; /* Read command. */

    Task_sleep(100);

    GPIO_write(GPIO_NAND_CS, 0);

    MAT_spi_transfer(MAT_SPIB0, txBuffer, rxBuffer,  1);

    GPIO_write(GPIO_NAND_CS, 1);

    /* wait 1ms(see datasheet for details) */

    Task_sleep(1);//hal_board_dly_ms(1);

    }

    unsigned char MAT_flsh_Block_Erase(unsigned long addr)

    {

    uint8_t     txBuffer[4];

    uint8_t     rxBuffer[4];

    unsigned int rw_addr;

    unsigned char ers_sts;

    apl_flsh_set_W_EN_DISBL(1);

    /* send command  */

    rw_addr=apl_flsh_get_rw_addr(addr);

    txBuffer[0] =CMD_ERASE_BLOCK;

    txBuffer[1] =0x00;

    txBuffer[2] =HIBYTE(rw_addr);

    txBuffer[3] =LOBYTE(rw_addr);

    Task_sleep(100);

    GPIO_write(GPIO_NAND_CS, 0);

    MAT_spi_transfer(MAT_SPIB0, txBuffer, rxBuffer, 4);

    GPIO_write(GPIO_NAND_CS, 1);

    ers_sts=apl_flsh_Ers_Blck_Sts_Chck();

    return ers_sts;

    }

    void apl_flsh_set_W_EN_DISBL(unsigned char Enbl_Flg)

    {

    uint8_t     txBuffer[1];

    uint8_t     rxBuffer[1];

    if (Enbl_Flg) {

    txBuffer[0] = CMD_WR_ENB; /* Read command. */

    }else {

    txBuffer[0] = CMD_WR_DIS;

    }

    Task_sleep(100);

    GPIO_write(GPIO_NAND_CS, 0);

    MAT_spi_transfer(MAT_SPIB0, txBuffer, rxBuffer,  1);

    GPIO_write(GPIO_NAND_CS, 1);

    }

    /*

    void apl_flsh_set_WDSBL()

    {

     unsigned char cmmnd;

     cmmnd = CMD_WR_ENB;

     hal_spi_CS(0); //CyU3PGpioSetValue (FPGA_FLASH_SEL_PIN, CyFalse); //FPGA_FLASH_SEL set 0

     hal_spi_WriteWords (&cmmnd, 1);

     hal_spi_CS(1);

    }*/

    void MAT_flsh_st_ftr(unsigned char reg_addr, unsigned char reg_data)

    {

    uint8_t     txBuffer[4];

    uint8_t     rxBuffer[4];

    Task_sleep(100);

    GPIO_write(GPIO_NAND_CS, 0);

    txBuffer[0] =CMD_SET_FEATURE;

    txBuffer[1] =reg_addr;

    txBuffer[2] =reg_data;

    MAT_spi_transfer(MAT_SPIB0, txBuffer, rxBuffer, 3);

    GPIO_write(GPIO_NAND_CS, 1);

    }

    unsigned char apl_flsh_gt_ftr(unsigned char reg_addr)

    {

    uint8_t     txBuffer[4];

    uint8_t     rxBuffer[4];

    unsigned char status;

    Task_sleep(100);

    GPIO_write(GPIO_NAND_CS, 0);

    txBuffer[0] =CMD_GET_FEATURE;

    txBuffer[1] =reg_addr;

    MAT_spi_transfer(MAT_SPIB0, txBuffer, rxBuffer, 3);

    status=rxBuffer[2];

    GPIO_write(GPIO_NAND_CS, 1);

    return status;

    }

    /*

    unsigned char apl_flsh_wt_OIP()

    {

     unsigned char OIP_Sts, Wt_sts;

     unsigned char location[4];

     unsigned int Wt_lp;

     hal_spi_CS(0);

     location[0] =CMD_GET_FEATURE;

     location[1] =FLSH_REG_STS;

     hal_spi_WriteWords(location,2);

     Wt_lp=0;

     while (1) {

       OIP_Sts=hal_spi_ReadByte()&0x01;

       if ((OIP_Sts==0) || (WAIT_OIP_MAX_TIMES <= Wt_lp )) { //ready

         break;

       }else {

         Wt_lp++;

         appl_uart_printf("\n\rOIP");

       }

     }

     hal_spi_CS(1);

     if (WAIT_OIP_MAX_TIMES <= Wt_lp ) {

       Wt_sts=FLSH_NOT_READY;

     }else {

       Wt_sts=FLSH_READY;

     }

     return Wt_sts;

    }

    */

    #if 0

    /**

    + * sspinand_enable_ecc- send command 0x1f to write the SPI Nand OTP register

    + *

    + * Description:

    + *   There is one bit( bit 0x10 ) to set or to clear the internal ECC.

    + *   Enable chip internal ECC, set the bit to 1

    + *   Disable chip internal ECC, clear the bit to 0

    + */

    void apl_flsh_enable_ecc(unsigned char enbl_flg)

    {

     unsigned char OTP_val;

     OTP_val = apl_flsh_gt_ftr(FLSH_REG_OTP);

     if (enbl_flg) {

       OTP_val |= OTP_ECC_MASK;

     }else {

       OTP_val &= (~OTP_ECC_MASK);

     }

     MAT_flsh_st_ftr(FLSH_REG_OTP, OTP_val);

    }

    #endif

    unsigned int apl_flsh_get_rw_addr(unsigned long addr)

    {

     unsigned int rw_addrs;

     rw_addrs=(unsigned int)(addr>>11);

     return rw_addrs;

    }

    unsigned int apl_flsh_get_clm_addr(unsigned long addr)

    {

     unsigned int clm_addrs;

     clm_addrs= (unsigned int)(addr & 0x000007ff);

     return clm_addrs;

    }

    //Page program function

    unsigned char MAT_flsh_Page_Program(unsigned long addr, unsigned char *buffer, unsigned int length)

    {

     unsigned char prg_sts;

     unsigned int rw_addr,clm_addr;

     apl_flsh_set_W_EN_DISBL(1);

     //get row,column address

     rw_addr=apl_flsh_get_rw_addr(addr);

     clm_addr=apl_flsh_get_clm_addr(addr);

     //page program load to cache

     apl_flsh_program_data_to_cache(clm_addr, buffer,length );

     //page program execute

     apl_flsh_program_execute(rw_addr);

     prg_sts=apl_flsh_Pg_Prog_Sts_Chck();

     return prg_sts;

    }

    void apl_flsh_program_execute(unsigned int rw_addr )

    {

    uint8_t     txBuffer[4];

    uint8_t     rxBuffer[4];

    txBuffer[0] =CMD_PAGE_PROG_EXE;

    txBuffer[1] = 0;

    txBuffer[2] = HIBYTE(rw_addr);

    txBuffer[3] = LOBYTE(rw_addr);

    Task_sleep(100);

    GPIO_write(GPIO_NAND_CS, 0);

    MAT_spi_transfer(MAT_SPIB0, txBuffer, rxBuffer, 4);

    GPIO_write(GPIO_NAND_CS, 1);

    }

    void apl_flsh_program_data_to_cache(unsigned int clm_addr ,unsigned char *buffer, unsigned int length )

    {

    uint8_t     txBuffer[4];

    txBuffer[0] =CMD_PAGE_PROG_LD;

     //pln_slct= apl_flsh_pln_slct(rw_addr);

    txBuffer[1] = HIBYTE(clm_addr);

    txBuffer[2] = LOBYTE(clm_addr);

    Task_sleep(100);

    GPIO_write(GPIO_NAND_CS, 0);

    MAT_spi_transfer(MAT_SPIB0, txBuffer, 0, 3);//hal_spi_WriteWords(location,3);

    MAT_spi_transfer(MAT_SPIB0,buffer,0,length);

      GPIO_write(GPIO_NAND_CS, 1);

    }

    /*

    unsigned char apl_flsh_pln_slct(unsigned int rw_addrss)

    {

     unsigned int tmp_RA6;

     tmp_RA6=rw_addrss & 0x0040;

     return LOBYTE((tmp_RA6>>2));

    }

    */

    //page read function

    unsigned char MAT_flsh_Page_Read(unsigned long addr, unsigned char *buffer, unsigned int length)

    {

     unsigned int rw_addr,clm_addr,rd_sts;

     //get row,column address

     rw_addr=apl_flsh_get_rw_addr(addr);

     clm_addr=apl_flsh_get_clm_addr(addr);

     //page read to cache

     apl_flsh_Pg_Rd_To_Cch(rw_addr);

     //page read status check

     rd_sts=apl_flsh_Pg_Rd_Sts_Chck();

     //random data read

     if (rd_sts == PG_RD_STS_READY) {

       apl_flsh_read_from_cache(clm_addr,buffer,length);

     }

     return rd_sts;

    }

    void apl_flsh_read_from_cache(unsigned int clmn_addr, unsigned char * buffer, unsigned int length)

    {

    uint8_t     txBuffer[4];

    txBuffer[0] =CMD_RANDOM_READ;

     //pln_slct= apl_flsh_pln_slct(rw_addr);

    txBuffer[1] = HIBYTE(clmn_addr);

    txBuffer[2] = LOBYTE(clmn_addr);

    txBuffer[3] = 0;

    Task_sleep(100);

    GPIO_write(GPIO_NAND_CS, 0);

    MAT_spi_transfer(MAT_SPIB0, txBuffer, 0, 4);

    MAT_spi_transfer(MAT_SPIB0, 0, buffer, length);

      GPIO_write(GPIO_NAND_CS, 1);

    }

    unsigned char apl_flsh_Pg_Prog_Sts_Chck()

    {

     unsigned char lp_cnt, status,loop, sts_val;

     loop=1;

     lp_cnt=0;

     while (loop) {

       status=apl_flsh_gt_ftr(FLSH_REG_STS);

       if ((status & STATUS_OIP_MASK) == STATUS_READY) {

         if ((status & STATUS_P_FAIL_MASK) == STATUS_P_FAIL) {

           //dev_err(&spi_nand->dev, "program error, page=%d\n", page_id);

           sts_val=PG_WR_STS_FAIL;

         }else {

           sts_val=PG_WR_STS_READY;

         }

         loop=0;

       }else {

         //not ready,

         lp_cnt++;

         if (10 < lp_cnt) {

           loop=0;

           sts_val=PG_WR_STS_BUSY;

         }

       }

     }

     return sts_val;

    }

    unsigned char apl_flsh_Pg_Rd_Sts_Chck()

    {

     unsigned char lp_cnt, status,loop, sts_val;

     loop=1;

     lp_cnt=0;

     while (loop) {

       status=apl_flsh_gt_ftr(FLSH_REG_STS);

       if ((status & STATUS_OIP_MASK) == STATUS_READY) {

    #if 0

         if ((status & STATUS_ECC_MASK) == STATUS_ECC_ERROR) {

           sts_val=PG_RD_STS_ECC_ERR;

           loop=0;

           //dev_err(&spi_nand->dev, "ecc error, page=%d\n", page_id);

           //if (spi_nand == SPI_NAND_MICRON_DRIVER_KEY)

             //printk(KERN_INFO "Error: reformat or erase your device. \n");

         }else {

           loop=0;

           sts_val=PG_RD_STS_READY;

         }

    #endif

    #if 1

         loop=0;

         sts_val=PG_RD_STS_READY;

    #endif

       }else {

         //not ready,

         lp_cnt++;

         if (10 < lp_cnt) {

           loop=0;

           sts_val=PG_RD_STS_BUSY;

         }

       }

     }

     return sts_val;

    }

    unsigned char apl_flsh_Ers_Blck_Sts_Chck()

    {

     unsigned char lp_cnt, status,loop, sts_val;

     loop=1;

     lp_cnt=0;

     while (loop) {

       status=apl_flsh_gt_ftr(FLSH_REG_STS);

       if ((status & STATUS_OIP_MASK) == STATUS_READY) {

         if ((status & STATUS_E_FAIL_MASK) == STATUS_E_FAIL) {

           //dev_err(&spi_nand->dev, "program error, page=%d\n", page_id);

           sts_val=ERS_BLCK_STS_FAIL;

         }else {

           sts_val=ERS_BLCK_STS_READY;

         }

         loop=0;

       }else {

         //not ready,

         lp_cnt++;

         if (10 < lp_cnt) {

           loop=0;

           sts_val=ERS_BLCK_STS_BUSY;

         }

       }

     }

     return sts_val;

    }

    void apl_flsh_Pg_Rd_To_Cch(unsigned int rw_addr)

    {

    uint8_t     txBuffer[4];

     //page read to cache

    txBuffer[0] =CMD_PAGE_READ;

    txBuffer[1] = 0;

    txBuffer[2] = HIBYTE(rw_addr);

    txBuffer[3] = LOBYTE(rw_addr);

    Task_sleep(100);

    GPIO_write(GPIO_NAND_CS, 0);

    MAT_spi_transfer(MAT_SPIB0, txBuffer, 0, 4);

    GPIO_write(GPIO_NAND_CS, 1);

    }

    #ifdef MAT_FLSH_SELF_TEST

    uint8_t Bffr[NUM_BYTE_FLSH_TEST];//[300];

    uint8_t indata[NUM_BYTE_FLSH_TEST];//[300];

    void MAT_flsh_Test_Data_Init()

    {

    uint16_t cntr;

    for (cntr=0; cntr < NUM_BYTE_FLSH_TEST; cntr++) {

    Bffr[cntr]=cntr;

    }

    }

    unsigned char FlashS[3];

    unsigned char Count = 0;

    //For my test

    void MAT_flsh_Test()

    {

    uint16_t cntr;

    uint32_t tmp_addr=0;

    Count++;

    if (Count > 10)

    Count = 0;

    FlashS[0] = MAT_flsh_Block_Erase(tmp_addr);

    //MAT_UART_printf(1,"ERS!",4);

    FlashS[1] = MAT_flsh_Page_Program(tmp_addr,Bffr, NUM_BYTE_FLSH_TEST);

    //MAT_UART_printf(1,"PRG!",4);

    //GPIO_write(GPIO_GSM_LED,0); // led on

    //if (Count == 0)

    FlashS[2] = MAT_flsh_Page_Read(tmp_addr,indata, NUM_BYTE_FLSH_TEST);

    //GPIO_write(GPIO_GSM_LED,1); // led off

    MAT_UART_printf(1,"RD! ",4);

    for (cntr=0; cntr < NUM_BYTE_FLSH_TEST; cntr++) {

    MAT_UART_putHEX(indata[cntr]);

    MAT_UART_printf(0," ",1);

    }

    for (cntr=0;cntr<NUM_BYTE_FLSH_TEST;cntr++) {

    Bffr[cntr]++;

    indata[cntr]=0;

    }

    }

    void MAT_flsh_ReadID(void)

    {

    uint8_t     txBuffer[4]={0x9F, 0xAA, 0x00, 0x00};

    uint8_t     rxBuffer[4]={0x00, 0x00, 0x00, 0x00};

    int reID;

    Task_sleep(100);

    GPIO_write(GPIO_NAND_CS, 0);

    MAT_spi_transfer(MAT_SPIB0, txBuffer, rxBuffer, 4);

    GPIO_write(GPIO_NAND_CS, 1);

    reID = rxBuffer[2];

    reID <<= 8;

    reID |= rxBuffer[3];

    MAT_UART_printf(1,"Flsh ID=",8);

    MAT_UART_putWORD((uint16_t)reID);

    }

    #endif

  • Jeffery,
    I don't see why you'll need the Task_sleep to "rest" the DMA to get it to work. Looks like there's a lot going on in your project. I had asked you to carry out some simple tests so that we can narrow down what's causing it. My understanding is that you have 3 tasks, one talking to a SPI Flash, the other talking to an EEPROM over I2C and the 3rd task uses the UART to print stuff. Is this how things still stand? You said you think "resting" the DMA makes it work. Besides SPI are you using the DMA in another task?

    To answer your question, TI-RTOS doesn't have an API to check if the DMA is ready. I believe if you're using the SPI dirver in blocking mode, SPI_transfer should not return until the the transfer is complete i.e DMA should be done and not busy. We need to setup a simple test to see what's causing it to hang.

    Thanks,
    Moses
  • Dear Moses

    Thanks for your comment.

    We checked the driver lib again and probably found a possible reason.

    It seems the SPI_transfer() is not protected by Semaphore_pend and Semaphore_post.

    Please see the attached modified SPI driver lib SPIEUSCIADMA.c for detail.

    It is in the folder of C:\ti\tirtos_msp430_2_00_01_23\packages\ti\drivers\spi on your PC.

    Semaphore_Handle     sem[MAT_SPICOUNT];  //Please add this line

    sem[set] = Semaphore_create(1, NULL, NULL);  //Please add this line  

    /* Initiate SPI transfer */

    Semaphore_pend(sem[set], BIOS_WAIT_FOREVER);  //Please add this line  

    transferOK = SPI_transfer(spi_set[set].handle , &spi_set[set].transaction);

    Semaphore_post(sem[set]);  //Please add this line

    Compare with attached I2C drier, you may find the difference on SPIEUSCIADMA.c.

    I marked the difference in red.

    Is this the possible reason which makes the SPI task hang up?

    Should I check this driver lib issue on MSP430 forum?

    Thanks for your support.

    #include <ti/drivers/SPI.h>

    #include <ti/drivers/spi/SPIEUSCIBDMA.h>

    #include <dma.h>

    #include "MAT_Driver.h"

    const SPI_Config SPI_config[];

    unsigned char SPIisrDMA = 0;

    spi_struct    spi_set[MAT_SPICOUNT];

    Semaphore_Handle     sem[MAT_SPICOUNT];  //Please add this line

    /* SPI objects */

    SPIEUSCIBDMA_Object spiEUSCIBDMAobjects[MAT_SPICOUNT];

    uint8_t spiEUSCIBDMAscratchBuf[MAT_SPICOUNT];

    /* SPI configuration structure, describing which pins are to be used */

    const SPIEUSCIBDMA_HWAttrs spiEUSCIBDMAHWAttrs[MAT_SPICOUNT] = {

          {

                 EUSCI_B0_BASE,

                 EUSCI_B_SPI_CLOCKSOURCE_SMCLK,

                 EUSCI_B_SPI_MSB_FIRST,

                 &spiEUSCIBDMAscratchBuf[0],

                 0,

                 /* DMA */

                 DMA_BASE,

                 /* Rx Channel */

                 DMA_CHANNEL_1,

                 DMA_TRIGGERSOURCE_22,

                 /* Tx Channel */

                 DMA_CHANNEL_0,

                 DMA_TRIGGERSOURCE_23

          }

    #if (USCI_A3_TYPE == USCI_A3_SPI)

       ,{

           EUSCI_A3_BASE,

           EUSCI_A_SPI_CLOCKSOURCE_SMCLK,

           EUSCI_A_SPI_MSB_FIRST,

           &spiEUSCIBDMAscratchBuf[1],

           0,

           /* DMA */

           DMA_BASE,

           /* Rx Channel */

           DMA_CHANNEL_1,

           DMA_TRIGGERSOURCE_25,

           /* Tx Channel */

           DMA_CHANNEL_0,

           DMA_TRIGGERSOURCE_26

       }

    #endif

    #if (USCI_A2_TYPE == USCI_A2_SPI)

       ,{

           EUSCI_A2_BASE,

           EUSCI_A_SPI_CLOCKSOURCE_SMCLK,

           EUSCI_A_SPI_MSB_FIRST,

    #if (USCI_A3_TYPE == USCI_A3_SPI)

           &spiEUSCIBDMAscratchBuf[2],

    #else

           &spiEUSCIBDMAscratchBuf[1],

    #endif

           0,

           /* DMA */

           DMA_BASE,

           /* Rx Channel */

           DMA_CHANNEL_1,

           DMA_TRIGGERSOURCE_20,

           /* Tx Channel */

           DMA_CHANNEL_0,

           DMA_TRIGGERSOURCE_21

       }

    #endif

    };

    const SPI_Config SPI_config[] = {

          {

           &SPIEUSCIBDMA_fxnTable,

           &spiEUSCIBDMAobjects[0],

           &spiEUSCIBDMAHWAttrs[0]

       },

    #if (USCI_A3_TYPE == USCI_A3_SPI)

       {

           &SPIEUSCIBDMA_fxnTable,

           &spiEUSCIBDMAobjects[1],

           &spiEUSCIBDMAHWAttrs[1]

       },

    #endif

    #if (USCI_A2_TYPE == USCI_A2_SPI)

       {

           &SPIEUSCIBDMA_fxnTable,

    #if (USCI_A3_TYPE == USCI_A3_SPI)

           &spiEUSCIBDMAobjects[2],

           &spiEUSCIBDMAHWAttrs[2]

    #else

           &spiEUSCIBDMAobjects[1],

           &spiEUSCIBDMAHWAttrs[1]

    #endif

       },

    #endif

       {NULL, NULL, NULL},

    };

    /*

    *  ======== MAT_SPICOUNT_initSPI ========

    */

    void MAT_SPI_config_init(void)

    {

    #if (USCI_A3_TYPE == USCI_A3_SPI)

       /* USCIA3 */

       GPIO_setAsInputPinWithPullUpresistor(GPIO_PORT_P4,

               GPIO_PIN3 | GPIO_PIN2 | GPIO_PIN1);

       /* SOMI/MISO */

       GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4,

               GPIO_PIN1);

       /* CLK and SIMO/MOSI */

       GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P4,

               GPIO_PIN3 | GPIO_PIN2);

    #endif

       /* USCIB0 */

       GPIO_setAsInputPinWithPullUpresistor(GPIO_PORT_P2,

               GPIO_PIN7 | GPIO_PIN6 | GPIO_PIN5);

       /* SOMI/MISO */

       GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2,

               GPIO_PIN5);

       /* CLK and SIMO/MOSI */

       GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2,

               GPIO_PIN7 | GPIO_PIN6);

    #if (USCI_A2_TYPE == USCI_A2_SPI)

       /* USCIA2 */

    /*   GPIO_setAsInputPinWithPullUpresistor(GPIO_PORT_P4,

               GPIO_PIN0);

       GPIO_setAsInputPinWithPullUpresistor(GPIO_PORT_P3,

               GPIO_PIN7 | GPIO_PIN6); */

       /* MOSI */

       GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P3,

               GPIO_PIN7);

       /* CLK and SIMO/MOSI */

       GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P4,

               GPIO_PIN0);

       GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3,

               GPIO_PIN6);

    #endif

       SPI_init();

    }

    void MAT_isrDMA(UArg arg)

    {

       // see "SPIEUSCIBDMA_HWAttrs" addr polituy , define N value "SPI_config[N]"

       /* Use the SPI_Handle that operates the SPI driver */

       SPI_serviceISR((SPI_Handle) &(SPI_config[SPIisrDMA]));

    }

    void MAT_SPI_set_init(void)

    {

          uint8_t       set;//, i;

          for(set=0; set < MAT_SPICOUNT; set++){

                 SPI_Params_init(&spi_set[set].params);

    /*

                 if(set == Board_SPI0)

                        spi_set[set].params.mode = SPI_MASTER;

                 else if(set == Board_SPI1)

                        spi_set[set].params.mode = SPI_SLAVE;

                 else if(set == Board_SPI2)

                        spi_set[set].params.mode = SPI_MASTER;

    */

                 //spi_set[set].params.bitRate = 100000;

                 spi_set[set].params.frameFormat = SPI_POL1_PHA0;

                 spi_set[set].handle = SPI_open(set, &spi_set[set].params);

              if (spi_set[set].handle == NULL) {

                 System_printf("Error initializing SPI%d\n",set);

              }

              sem[set] = Semaphore_create(1, NULL, NULL);  //Please add this line  

          }

          System_printf("[driver]SPI sets initialized\n",set);

          /*

       for(i=0; i<SPI_CMD_total; i++)

       {

          spi_slave_RxBuffer[i] = '\0';

       }

       */

       System_flush();

    }

    bool MAT_spi_transfer(uint8_t set, Ptr tx_buf, Ptr rx_buf, uint8_t len)

    {

       bool transferOK;

       SPIisrDMA = set;

       /* Initialize slave SPI transaction structure */

       spi_set[set].transaction.count = len;

       spi_set[set].transaction.txBuf = tx_buf;

       spi_set[set].transaction.rxBuf = rx_buf;

       //__delay_cycles(80000);

       //GPIO_write(GPIO_GSM_LED,0); // led on

       /* Initiate SPI transfer */

       Semaphore_pend(sem[set], BIOS_WAIT_FOREVER);  //Please add this line  

       transferOK = SPI_transfer(spi_set[set].handle , &spi_set[set].transaction);

       Semaphore_post(sem[set]);  //Please add this line

       //GPIO_write(GPIO_GSM_LED,1); // led on

       //__delay_cycles(800000);

       return transferOK;

    }