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.

SPI Interrupt not working AM3359

Other Parts Discussed in Thread: AM3359, SYSBIOS

Hello,

i am using an ICE Board (AM3359) and the SPI0 at the expansion header J12 with the API from Starterware. As example i´ve took "mcSPIflash" and ethercat_appl

The SPI (withpout interrupt) is working fine if i take a while loop and call the McSPITransfer_2() function which contains

 (McSPICSAssert(),IntEnable(),ChannelEnable(), Transmit/ReceiveData().......)

If i use the McSPITransfer() from the McSPIFlash example with  /* Wait until control returns back from McSPI ISR.*/

(McSPICSAssert(),IntEnable(),ChannelEnable(), then while(flagg);/* Wait until control returns back from McSPI ISR.*/ ) i can´t see any output data. Transmit/Receive Data would be called in the SPI-ISR. Neither in the McSPITransfer() or in the ISR function a breakpoint is not reached.

The INT is configured as follows:

IntMasterIRQEnable(); /* Enable IRQ in CPSR.*/
IntAINTCInit(); /* Initialize ARM interrupt controller */
IntRegister(SYS_INT_SPI0INT, McSPIIsr); /* Register McSPIIsr interrupt handler */
IntPrioritySet(SYS_INT_SPI0INT, 0, AINTC_HOSTINT_ROUTE_IRQ);
IntSystemEnable(SYS_INT_SPI0INT);

I don´t know where to search to solve the problem.

Where i can see if the interrupt SPI0 (Int.Nr.65) would be triggered?

Can anyone help me?

Thank you

  • Hi Daniel,

    The interrupt configuration seems to be okay. However from your post you mentioned -"(McSPICSAssert(),IntEnable(),ChannelEnable(), then while(flagg);/* Wait until control returns back from McSPI ISR.*/ ) i can´t see any output data. Transmit/Receive Data would be called in the SPI-ISR. Neither in the McSPITransfer() or in the ISR function a breakpoint is not reached."

    1) Are you able to see the control getting inside McSPITransfer()? Is the McSPI channel getting enabled?

    2) If the channel is enabled can you please check the McSPI channel status register if the required status is set?

    Regards,

    Jeethan

  • Now in debug mode i see:

    If i come out from the McSPI0AintcConfigure() function which contains:

    IntAINTCInit(); IntRegister(SYS_INT_SPI0INT, McSPIIsr); 
    IntPrioritySet(SYS_INT_SPI0INT, 0, AINTC_HOSTINT_ROUTE_IRQ); IntSystemEnable(SYS_INT_SPI0INT); 

    the Debug(cursor) moves to the next line (unsigned int index = 0;) and then the program runs (maybe around the world, i dont know) but the cursordid not go to the next line !

    And did not call the McSPITransfer() function, in which the Channel would be enabled (and CS Assert & IntEnable)

  • Hi Daniel,

    Can you please share the code where it does not work as expected? Is the code aborting?

    Regards,

    Jeethan

  • I can´t see the code ist aborting ? the CortexA8 is in "running" -mode.

    After IntSystemEnable(SYS_INT_SPI0INT); the debug cursor change to the next 1-3 lines, and then in Debug window is only CortexA8 (Running) shown. Not the function in which the cursor/programm is.

    This problem i have also with DMTimer Interrupt [see http://e2e.ti.com/support/embedded/starterware/f/790/p/300664/1048875.aspx#1048875 ]. I want to use the SPI/EDMA interrupt.

    So this problem is kind of a basic problem i must solve. Do you have an idea?

    The Code:

        /* Enable the clocks for McSPI0 module.*/
        McSPI0ModuleClkConfig();
    
        /* Perform Pin-Muxing for SPI0 Instance */
        McSPIPinMuxSetup(0);
    
        /* Perform Pin-Muxing for CS1 of SPI0 Instance */
        McSPI0CSPinMuxSetup(chNum);
    //                HWREG(SOC_CONTROL_REGS + CONTROL_CONF_SPI0_CS1) =
    //                     (CONTROL_CONF_SPI0_SCLK_CONF_SPI0_SCLK_PUTYPESEL |
    //                          CONTROL_CONF_SPI0_SCLK_CONF_SPI0_SCLK_RXACTIVE);
    
        /* Do the necessary set up configurations for McSPI.*/
        McSPISetUp();
    
        /*
         * at first a few outputs
         * it works !
         */
        unsigned int loop = 5000;
        while(loop){
        // TX Buffer write one time
    	txBuffer[0] = outbyte;
    	length = 1;
    	McSPITransfer_2();
    	loop --;
        }
    
        // start to enable the interrupt / ISR
    	/* Enable IRQ in CPSR.*/
    	IntMasterIRQEnable();
    
    	/* Map McSPI Interrupts to AINTC */
    	McSPI0AintcConfigure();
    
    	// Data for Interrupt - not working / no or hanging in Interrupt?
        unsigned int index = 0;
        for(index = 0; index < 100; index++)
        {
            txBuffer[index] = outbyte;
        }
        length = 100;
        McSPITransfer();
    
    	System_printf("starting BIOS \n");
        BIOS_start();     /* enable interrupts and start SYS/BIOS */
    /* Interrupt mapping to AINTC and registering McSPI ISR */
    static void McSPI0AintcConfigure(void)
    {
        /* Initialize ARM interrupt controller */
        IntAINTCInit();
    
        /* Register McSPIIsr interrupt handler */
        IntRegister(SYS_INT_SPI0INT, McSPIIsr);
    
        /* Set Interrupt Priority */
        IntPrioritySet(SYS_INT_SPI0INT, 0, AINTC_HOSTINT_ROUTE_IRQ); // from 0 to 127, 0 being the highest and127 being the lowest priority.
    
        /* Enable system interrupt in AINTC */
        IntSystemEnable(SYS_INT_SPI0INT);
    }
    /*
    ** This function will activate/deactivate CS line and also enable Tx and Rx
    ** interrupts of McSPI peripheral.
    */
    static void McSPITransfer(void)
    {
        p_tx = txBuffer;
        p_rx = rxBuffer;
    
        /* SPIEN line is forced to low state.*/
        McSPICSAssert(SOC_SPI_0_REGS, chNum);
    
        /* Enable the Tx/Rx interrupts of McSPI.*/
        McSPIIntEnable(SOC_SPI_0_REGS, MCSPI_INT_TX_EMPTY(chNum) |
                       MCSPI_INT_RX_FULL(chNum));
    
        /* Enable the McSPI channel for communication.*/
        McSPIChannelEnable(SOC_SPI_0_REGS, chNum);
    
        /* Wait until control returns back from McSPI ISR.*/
        while(flagg);
    
        flagg = 1;
    
        /* Force SPIEN line to the inactive state.*/
        McSPICSDeAssert(SOC_SPI_0_REGS, chNum);
    
        /* Disable the McSPI channel.*/
        McSPIChannelDisable(SOC_SPI_0_REGS, chNum);
    }
    /*
    ** McSPI Interrupt Service Routine. This function will clear the status of the
    ** Tx/Rx interrupts when generated. Will write the Tx data on transmit data
    ** register and also will put the received data from receive data register to
    ** a location in memory.
    */
    static void McSPIIsr(void)
    {
        unsigned int intCode = 0;
    
        intCode = McSPIIntStatusGet(SOC_SPI_0_REGS);
    
        while(intCode)
        {
            if(MCSPI_INT_TX_EMPTY(chNum) == (intCode & MCSPI_INT_TX_EMPTY(chNum)))
            {
                McSPIIntStatusClear(SOC_SPI_0_REGS, MCSPI_INT_TX_EMPTY(chNum));
    
                length--;
    
                McSPITransmitData(SOC_SPI_0_REGS,(unsigned int)(*p_tx++), chNum);
    
                if(!length)
                {
                    McSPIIntDisable(SOC_SPI_0_REGS, MCSPI_INT_TX_EMPTY(chNum));
    
                    McSPIIntStatusClear(SOC_SPI_0_REGS, MCSPI_INT_TX_EMPTY(chNum));
                }
            }
    
            if(MCSPI_INT_RX_FULL(chNum) == (intCode & MCSPI_INT_RX_FULL(chNum)))
            {
                McSPIIntStatusClear(SOC_SPI_0_REGS, MCSPI_INT_RX_FULL(chNum));
    
                *p_rx++ = (unsigned char) McSPIReceiveData(SOC_SPI_0_REGS, chNum);
    
                if(!(length))
                {
                    McSPIIntDisable(SOC_SPI_0_REGS, MCSPI_INT_RX_FULL(chNum));
    
                    flagg = 0;
                }
            }
    
            intCode = McSPIIntStatusGet(SOC_SPI_0_REGS);
        }
    }
  • Anyone an idea / answer?

  • Hi Daniel,

    I assume you have not referred to the McSPI Interrupt example present for AM335x GPEVM. If not can you please refer the example files present at this location "StarterWare\examples\evmAM335x\mcspi\" and see if there are any differences with respect to your code.

    Regards,

    Jeethan 

     

  • For my project i used as base the mcspiflash example.

    At first i can send via McSPITransfer_2(); SPI-Data.

    Then i configure and register the interrupt SYS_INT_SPI0INT to AINTC. After IntSystemEnable(SYS_INT_SPI0INT); the interrupt might be started. But i never reach the breakpoint in the ISR function.

    When i try to use DMTimer interrut, init via SysBios then i can reach the breakpoint in the DMTimer ISR.

    I think i must reach the breakpoint in the ISR from an interrupt generated/ initialize via starterware as like via sysbios?

    Is there maybe a problem with the project options? Or i need another .cmd file?

  • Hi Daniel,

    1. I think the INTC is configured after Tx, Rx interrupts and MCSPI channel is enabled. Please do the INTC configurations first.
    2. Is the Tx empty status getting set?
    3. For project options one can refer the MCSPI project provided with StarterWare

    Regards,

    Jeethan

  • Hello,

    thanks for your information.

    My Project  works with SPI and EDMA. For the Interrupt init i use SysBios and the INTC functions of sysbios:


        Hwi_Params hwiParams;
        Hwi_Handle tempHwiHandler12;
        Hwi_Params_init(&hwiParams);
        hwiParams.enableInt = true;
        tempHwiHandler12 = Hwi_create(intNum ,hwiFuncPointer ,&hwiParams, &eb);
        Hwi_enableInterrupt(intNum);


    With Hwi_enableInterrupt(intNum) from Sysbios/Hwi.h the ISR will be carfeully reached and it works fine.

    But when i use the Starterware APIs to register a ISR to a HWI it does not work. But i must used SYS/BIOS so it´s ok.

    But it´s still good to know, why it´s not working when i use only the Starterware APIs withput SysBios.

  • Hi,

    I have a similar problem, I have added utils, drive, platform and systems

    I cannot get the interrupts going for Timer (or uart).

    On further investigation i found that the timer module is working just fine and is giving a overflow status.

    The issue is with CPSR resistor in the cortex core.

    I am unable to enable interrupts by resetting the IRQ bit in the CPSR resistor.

    Where R0 = 0x40000110

    CPSR = 0x40000190

    When i do a  msr     CPSR, r0

    I still get CPSR = 0x40000190 where IRQ is disabled...

    I am sure that I am missing something here,.. can anyone please help

    Code below for reference -

    #include "dmtimer.h"

    #include "interrupt.h"

    #include "gpio_v2.h"

    #include "soc_AM335x.h"

    #include "beaglebone.h"

    static void hardware_init();

    static void timer_init();

    static void timer_config(unsigned long, unsigned long);

    static void isr_timer2();

    int main(void) {

    // Set up hardware and peripherals.

    hardware_init();

    // Configure timer settings

    timer_config(0xF0000000u, 0xF0000000u);

    timer_init();

    // XXX: Turn on LED

    GPIOPinWrite(SOC_GPIO_1_REGS, (23), GPIO_PIN_HIGH);

    // Enable timer interrupt

    DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);

    // Turn on actual timer

    DMTimerEnable(SOC_DMTIMER_2_REGS);

    asm(" mrs r0, CPSR");

    asm(" bic r0, r0, #0x80");

    asm(" msr CPSR, r0");

    // Loop forever- all work takes place in ISRs.

    while(1);

    }

    static void hardware_init() {

    // Configure GPIO/LED

    GPIO1ModuleClkConfig();

    GPIO1Pin23PinMuxSetup();

    GPIOModuleEnable(SOC_GPIO_1_REGS);

    GPIOModuleReset(SOC_GPIO_1_REGS);

    /* Set GPIO 1.23 as output */

    GPIODirModeSet(SOC_GPIO_1_REGS, (23), GPIO_DIR_OUTPUT);

    }

    static void timer_init() {

    // Set up the configuration for the hardware timer.

    /* Enable clocks for DMTimer2 */

    DMTimer2ModuleClkConfig();

    /* Initialize ARM interrupt controller (AINTC) */

    IntAINTCInit();

    /* Register our ISR to DMTimer2's interrupt. */

    IntRegister(SYS_INT_TINT2, isr_timer2);

    /* Set the DMTimer2's interrupt priority to 0. */

    IntPrioritySet(SYS_INT_TINT2, 0, AINTC_HOSTINT_ROUTE_IRQ);

    /* Enable the DMTimer2 interrupt. */

    IntSystemEnable(SYS_INT_TINT2);

    /* Enable IRQ in CPSR (ARM program status register) */

    // IntMasterIRQEnable();

    }

    static void timer_config(unsigned long initial, unsigned long reload) {

    // Configure timer

    // Note that instead of doing a count from 0 to some compare value, we are

    // preloading the timer with a given value and watching for it to overflow,

    // which is functionally identical.

    /* Configure the timer mode. */

    // Modes: autoreload (selected) versus one-shot mode. Does the timer automatically reset itself?

    // compare versus overflow (selected) mode. Does the timer ISR trip on equality to a value, or on overflow?

    DMTimerModeConfigure(SOC_DMTIMER_2_REGS, DMTIMER_AUTORLD_NOCMP_ENABLE);

    /* Load initial counter value into timer. */

    DMTimerCounterSet(SOC_DMTIMER_2_REGS, initial);

    /* Load reload counter value into timer, the value the timer gets every time it is reset. */

    DMTimerReloadSet(SOC_DMTIMER_2_REGS, reload);

    }

    // Interrupt vector for BeagleBone timer

    static void isr_timer2() {

    static short int mode = 0;

    /* Disable the DMTimer interrupt */

    DMTimerIntDisable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);

    /* Clear the interrupt flags (IF) status */

    DMTimerIntStatusClear(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_IT_FLAG);

    /* *********** ISR TASKS BEGIN *********** */

    if (mode == 0) {

    // Turn on LED

    GPIOPinWrite(SOC_GPIO_1_REGS, (23), GPIO_PIN_HIGH);

    mode = 1;

    } else {

    // Turn off LED

    GPIOPinWrite(SOC_GPIO_1_REGS, (23), GPIO_PIN_LOW);

    mode = 0;

    }

    /* *********** ISR TASKS END *********** */

    /* Re-enable the DMTimer interrupt */

    DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);

    }

    2502.IRQ CPSR.doc