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_transfer() crashes

Other Parts Discussed in Thread: TLV5637, SYSBIOS

Hello, I'm running tirtos_2_10_01_38 on a Tiva TM4C123AE6PMI processor and having problems with SPI_transfer() crashing. I'm using SPI0, SPI1 and SPI2 for my application. Currently communications to I/O expanders on SPI1 and SPI2 seem to work fine. However, I have a write only TLV5637 DAC on SPI0  that I'm trying to write to that crashes when I call SPI_transfer().

I get the following message in the output console when it crashes.

[CORTEX_M4_0] MainPollTask()

ti.sysbios.knl.Semaphore: line 202: assertion failure: A_badContext: bad calling context. Must be called from a Task.

xdc.runtime.Error.raise: terminating execution



My code to write to the DAC is listed below. I'm fairly new to TI-RTOS and any help would be greatly appreciated!

Regards,

Bob

static SPI_Handle g_handleSpi0 = 0;

//*****************************************************************************
// Initialize and open various system peripherals we'll be using
//*****************************************************************************

void MotorDAC_initialize(void)
{

SPI_Params spiParams;

/* Open SSI-0 to the TLV5637 DAC motor drive amp driver */

/* Moto fmt, polarity 1, phase 0 */

SPI_Params_init(&spiParams);

spiParams.transferMode = SPI_MODE_BLOCKING;
spiParams.mode = SPI_MASTER;
spiParams.frameFormat = SPI_POL1_PHA0;
spiParams.bitRate = 1000000;
spiParams.dataSize = 8;

g_handleSpi0 = SPI_open(Board_SPI0, &spiParams);

if (g_handleSpi0 == NULL)

System_abort("Error initializing SPI0\n");

/* Set the torque to zero on reel motors! */

MotorDAC_write(0, 0);

}

//*****************************************************************************

// This function writes the takeup and supply motor DAC values controlling

// the motor drive amp. The TLV5637 is a dual 10-bit, single supply DAC,

// based on a resistor string architecture. The output voltage (full scale

// determined by reference) is given by:

//

// Vout = (2 REF) * (CODE/0x1000)

//

// Where REF is the reference voltage and CODE is the digital

// input value in the range 0x000 to 0xFFF. Because it is a

// 10-bit DAC, only D11 to D2 are used. D0 and D1 are ignored.

// A power-on reset initially puts the internal latches to a

// defined state (all bits zero).

//

// The motor current amp delivers full torque at 1mA and

// zero torque at 5.1mA.

//

// DAC A - is the SUPPLY motor torque level

// DAC B - is the TAKEUP motor torque level

//

//*****************************************************************************

void MotorDAC_write(uint32_t supply, uint32_t takeup)

{

uint16_t ulWord;

uint16_t ulReply;

uint16_t ulDac;

bool transferOK;

SPI_Transaction transaction;

/* DEBUG - save current values */

g_servo.dac_supply = supply;

g_servo.dac_takeup = takeup;

takeup = DAC_MAX - takeup;

supply = DAC_MAX - supply;

/* (1) Set reference voltage to 1.024 V (CONTROL register) */

ulWord = (1 << 15) | (1 << 12) | 0x01;

transaction.count = sizeof(ulWord);

transaction.txBuf = (Ptr)&ulWord;

transaction.rxBuf = (Ptr)&ulReply;

GPIO_write(Board_CS_SPI0, PIN_LOW);

transferOK = SPI_transfer(g_handleSpi0, &transaction);

GPIO_write(Board_CS_SPI0, PIN_HIGH);

/* (2) Write data for DAC B to BUFFER */

ulDac = (takeup & 0x3FF) << 2;

ulWord = (1 << 12) | (uint16_t)ulDac;

transaction.count = sizeof(ulWord);

transaction.txBuf = (Ptr)&ulWord;

transaction.rxBuf = (Ptr)&ulReply;

GPIO_write(Board_CS_SPI0, PIN_LOW);

transferOK = SPI_transfer(g_handleSpi0, &transaction);

GPIO_write(Board_CS_SPI0, PIN_HIGH);

/* (3) Write DAC A value and update DAC A & B simultaneously */

ulDac = (supply & 0x3FF) << 2;

ulWord = (1 << 15) | (uint16_t)ulDac;

transaction.count = sizeof(ulWord);

transaction.txBuf = (Ptr)&ulWord;

transaction.rxBuf = (Ptr)&ulReply;

GPIO_write(Board_CS_SPI0, PIN_LOW);

transferOK = SPI_transfer(g_handleSpi0, &transaction);

GPIO_write(Board_CS_SPI0, PIN_HIGH);

}

 

  • Hi Robert,
    Can you show us the code where you initialize the task(s) that call these functions?
    Regards,
    Michel
  • Sure, but after rearranging things it's acting flakey on all SPI transactions. I could zip up the whole project and put it somewhere it that helps. The task stack size says it's 2048.

    //*****************************************************************************
    // Main Program Entry Point
    //*****************************************************************************

    Int main()
    {
    Error_Block eb;
    Task_Handle task;
    Mailbox_Params mboxParams;

    /* Call board init functions */
    Board_initGeneral();
    Board_initGPIO();
    Board_initUART();
    Board_initI2C();
    Board_initSPI();
    Board_initQEI();
    Board_initADC();

    /*
    * Create a mailbox message queues for the transport control/command tasks
    */

    /* Create transport controller task mailbox */

    Error_init(&eb);
    Mailbox_Params_init(&mboxParams);
    g_mailboxTransport = Mailbox_create(sizeof(uint8_t), 8, &mboxParams, &eb);

    /* Create servo controller task mailbox */

    Error_init(&eb);
    Mailbox_Params_init(&mboxParams);
    g_mailboxController = Mailbox_create(sizeof(CMDMSG), 8, &mboxParams, &eb);

    /*
    * Now start the main application button polling task
    */

    Error_init(&eb);
    task = Task_create(MainPollTask, NULL, &eb);
    if (task == NULL) {
    System_printf("Task_create() failed!\n");
    BIOS_exit(0);
    }

    BIOS_start(); /* does not return */

    return(0);
    }

    //*****************************************************************************
    // Initialize and open various system peripherals we'll be using
    //*****************************************************************************

    void InitPeripherals(void)
    {
    I2C_Params i2cParams;

    /*
    * Open the I2C ports for peripherals we need to communicate with.
    */

    /* Open I2C0 for U14 CAT24C08 EPROM */

    I2C_Params_init(&i2cParams);
    i2cParams.transferMode = I2C_MODE_BLOCKING;
    i2cParams.bitRate = I2C_100kHz;
    g_handleI2C0 = I2C_open(Board_I2C0, &i2cParams);

    /* Open I2C1 for U9 AT24CS01 EPROM/Serial# */

    I2C_Params_init(&i2cParams);
    i2cParams.transferMode = I2C_MODE_BLOCKING;
    i2cParams.bitRate = I2C_100kHz;
    g_handleI2C1 = I2C_open(Board_I2C1, &i2cParams);

    /*
    * Open the SPI ports for peripherals we need to communicate with.
    */

    /* Initialize the SPI-0 to the reel motor DAC's */
    MotorDAC_initialize();

    /* Initialize the SPI-1 & SPI-2 to the I/O expanders */
    IOExpander_initialize();

    /* Initialize the TTY task terminal port */
    //Terminal_initialize();
    }

    //*****************************************************************************
    //
    //*****************************************************************************

    Void MainPollTask(UArg a0, UArg a1)
    {
    uint8_t count = 0;
    uint8_t bits = 0x00;
    uint8_t tran_prev = 0xff;
    uint8_t mode_prev = 0xff;
    uint8_t tout_prev = 0xff;
    uint8_t debounce_tran = 0;
    uint8_t debounce_mode = 0;
    uint8_t debounce_tout = 0;

    Error_Block eb;

    System_printf("MainPollTask()\n");

    /* Initialize the default servo and program data values */

    memset(&g_servo, 0, sizeof(SERVODATA));
    memset(&g_sys, 0, sizeof(SYSPARMS));

    InitSysDefaults(&g_sys);

    InitPeripherals();

    /* Read the initial mode switch states */
    GetModeSwitches(&mode_prev);
    g_high_speed_flag = (mode_prev & M_HISPEED) ? 1 : 0;
    g_switch_option = mode_prev & M_DIPSW_MASK;

    /* Read the initial transport switch states */
    GetTransportSwitches(&tran_prev);
    g_tape_out_flag = (tran_prev & S_TAPEOUT) ? 0 : 1;

    /* Read the system config parameters from storage */
    //rc = SysParamsRead(&g_sys);
    //if (rc != 0)
    // LampBlinkError(); // Blink ALL lamps on error
    //else
    LampBlinkChase(); // Blink each lamp individually on success

    /* Initialize servo loop controller data */
    g_servo.offset_sample_cnt = 0;
    g_servo.offset_null_sum = 0;
    g_servo.tsense_sum = 0;
    g_servo.tsense_sample_cnt = 0;
    g_servo.brake_torque = 0;
    g_servo.dac_halt_takeup = 0;
    g_servo.dac_halt_supply = 0;

    /* Servo's start in halt mode! */
    SET_SERVO_MODE(MODE_HALT);

    /* Create the transport command/control and terminal tasks.
    * The three tasks provide the bulk of the system control services.
    */
    Error_init(&eb);
    Task_create(TransportControllerTask, NULL, &eb);

    Error_init(&eb);
    Task_create(TransportCommandTask, NULL, &eb);

    //Error_init(&eb);
    //Task_create(TerminalTask, NULL, &eb);

    /* Initialize the tape tach timers and interrupt.
    * This tach provides the tape speed from the tape
    * counter roller.
    */

    //Tachometer_initialize();

    /* Start the transport servo loop timer clock running.
    * We create an auto-reload periodic timer for the servo loop.
    * Note we are servicing the servo task at 500 Hz.
    */

    Clock_Params clockParams;

    Error_init(&eb);
    Clock_Params_init(&clockParams);

    clockParams.period = 2;
    clockParams.startFlag = TRUE;
    clockParams.arg = (UArg)0x5555;

    //Clock_create(ServoTimerCallback, 10, &clockParams, &eb);

    /****************************************************************
    * Enter the main application button processing loop forever.
    ****************************************************************/

    g_lamp_blink_mask = L_STAT1;

    for(;;)
    {
    /* Blink heartbeat LED1 on the transport interface card */
    if (++count >= 50)
    {
    count = 0;
    g_lamp_mask ^= g_lamp_blink_mask;
    }

    /* Set any new led/lamp state. We only update the LED output
    * port if a new lamp state was selected.
    */

    if (g_lamp_mask != g_lamp_mask_prev)
    {
    // Set the new lamp state
    SetLamp(g_lamp_mask);

    // Upate the previous lamp state
    g_lamp_mask_prev = g_lamp_mask;
    }

    /*
    * Poll the transport control buttons to read the
    * current transport button switch states
    */

    GetTransportSwitches(&bits);

    /* First process the tape out arm switch */
    if ((bits & S_TAPEOUT) != tout_prev)
    {
    if (++debounce_tout >= 2)
    {
    debounce_tout = 0;

    /* Save the new state */
    tout_prev = (bits & S_TAPEOUT);

    /* Set the tape out arm state */
    g_tape_out_flag = (bits & S_TAPEOUT) ? 1 : 0;

    if (!(bits & S_TAPEOUT))
    bits |= S_TAPEIN;

    /* Send the button press to transport ctrl/cmd task */
    Mailbox_post(g_mailboxTransport, &bits, 10);
    }
    }

    /* Next process the tape transport buttons */
    bits &= S_BUTTON_MASK;

    if (bits != tran_prev)
    {
    if (++debounce_tran >= 2)
    {
    debounce_tran = 0;

    /* Debounced a button press, send it to transport task */
    tran_prev = bits;

    /* Send the button press to transport ctrl/cmd task */
    Mailbox_post(g_mailboxTransport, &bits, 10);
    }
    }

    /*
    * Poll the mode config switches to read the DIP switches on
    * the PCB and the hi/lo speed switch on the transport control.
    */

    GetModeSwitches(&bits);

    if (bits != mode_prev)
    {
    if (++debounce_mode >= 2)
    {
    debounce_mode = 0;

    /* We debounced a switch change, reset and process it */
    mode_prev = bits;

    /* Save the transport speed select setting */
    g_high_speed_flag = (bits & M_HISPEED) ? 1 : 0;

    /* Save the updated DIP switch settings */
    g_switch_option = bits & M_DIPSW_MASK;
    }
    }

    /* delay for 10ms and loop */
    Task_sleep(10);
    }
    }
  • Here's my driver module if this helps...

    /*
    * Copyright (c) 2014, Texas Instruments Incorporated
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    *
    * * Redistributions of source code must retain the above copyright
    * notice, this list of conditions and the following disclaimer.
    *
    * * Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the
    * documentation and/or other materials provided with the distribution.
    *
    * * Neither the name of Texas Instruments Incorporated nor the names of
    * its contributors may be used to endorse or promote products derived
    * from this software without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    */

    #include <stdint.h>
    #include <stdbool.h>
    #include <inc/hw_sysctl.h>
    #include <inc/hw_memmap.h>
    #include <inc/hw_types.h>
    #include <inc/hw_ints.h>
    #include <inc/hw_gpio.h>
    #include <inc/hw_ssi.h>
    #include <inc/hw_i2c.h>

    #include <driverlib/gpio.h>
    #include <driverlib/flash.h>
    #include <driverlib/eeprom.h>
    #include <driverlib/sysctl.h>
    #include <driverlib/i2c.h>
    #include <driverlib/ssi.h>
    #include <driverlib/udma.h>
    #include <driverlib/adc.h>
    #include <driverlib/qei.h>
    #include <driverlib/pin_map.h>

    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/Error.h>
    #include <xdc/runtime/System.h>
    #include <ti/sysbios/family/arm/m3/Hwi.h>

    #include "DTC1200_TivaTM4C123AE6PMI.h"

    #ifndef TI_DRIVERS_UART_DMA
    #define TI_DRIVERS_UART_DMA 0
    #endif

    /*
    * =============================== DMA ===============================
    */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN(DTC1200_DMAControlTable, 1024)
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment=1024
    #elif defined(__GNUC__)
    __attribute__ ((aligned (1024)))
    #endif
    static tDMAControlTable DTC1200_DMAControlTable[32];
    static Bool DMA_initialized = false;

    /* Hwi_Struct used in the initDMA Hwi_construct call */
    static Hwi_Struct dmaHwiStruct;

    /*
    * ======== DTC1200_errorDMAHwi ========
    */
    static Void DTC1200_errorDMAHwi(UArg arg)
    {
    System_printf("DMA error code: %d\n", uDMAErrorStatusGet());
    uDMAErrorStatusClear();
    System_abort("DMA error!!");
    }

    /*
    * ======== DTC1200_initDMA ========
    */
    void DTC1200_initDMA(void)
    {
    Error_Block eb;
    Hwi_Params hwiParams;

    if (!DMA_initialized) {

    Error_init(&eb);

    Hwi_Params_init(&hwiParams);
    Hwi_construct(&(dmaHwiStruct), INT_UDMAERR, DTC1200_errorDMAHwi, &hwiParams, &eb);
    if (Error_check(&eb)) {
    System_abort("Couldn't construct DMA error hwi");
    }

    SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    uDMAEnable();
    uDMAControlBaseSet(DTC1200_DMAControlTable);

    DMA_initialized = true;
    }
    }

    /*
    * =============================== General ===============================
    */

    /*
    * ======== DTC1200_initGeneral ========
    */
    void DTC1200_initGeneral(void)
    {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);

    // Initialize the EEPROM so we can access it later

    SysCtlPeripheralEnable(SYSCTL_PERIPH_EEPROM0);

    if (EEPROMInit() != EEPROM_INIT_OK)
    System_printf("EEPROMInit() failed!\n");

    uint32_t size = EEPROMSizeGet();
    }

    /*
    * =============================== GPIO ===============================
    */

    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(GPIO_config, ".const:GPIO_config")
    #pragma DATA_SECTION(gpioHWAttrs, ".const:gpioHWAttrs")
    #endif

    #include <ti/drivers/GPIO.h>

    /* Callback functions for the GPIO interrupt example. */
    void gpioExpInt1A(void); /* U5 MCP23S17T INTA Handler */
    void gpioExpInt2B(void); /* U8 MCP23S17T INTB Handler */

    /* GPIO configuration structure */
    const GPIO_HWAttrs gpioHWAttrs[DTC1200_GPIOCOUNT] = {
    { GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_OUTPUT }, /* 0 DTC1200_SSI0FSS */
    { GPIO_PORTB_BASE, GPIO_PIN_5, GPIO_OUTPUT }, /* 1 DTC1200_SSI2FSS */
    { GPIO_PORTC_BASE, GPIO_PIN_7, GPIO_INPUT }, /* 2 DTC1200_TAPE_END */
    { GPIO_PORTC_BASE, GPIO_PIN_6, GPIO_OUTPUT }, /* 3 DTC1200_EXPANSION_PC6 */
    { GPIO_PORTD_BASE, GPIO_PIN_4, GPIO_OUTPUT }, /* 4 DTC1200_RESET_MCP */
    { GPIO_PORTD_BASE, GPIO_PIN_5, GPIO_OUTPUT }, /* 5 DTC1200_EXPANSION_PD5 */
    { GPIO_PORTD_BASE, GPIO_PIN_1, GPIO_OUTPUT }, /* 6 DTC1200_SSI1FSS */
    { GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_OUTPUT }, /* 7 DTC1200_EXPANSION_PF3 */
    { GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_OUTPUT }, /* 8 DTC1200_EXPANSION_PF2 */
    { GPIO_PORTG_BASE, GPIO_PIN_4, GPIO_INPUT }, /* 9 DTC1200_MCP23S17T_INT1A */
    { GPIO_PORTG_BASE, GPIO_PIN_3, GPIO_INPUT }, /* 10 DTC1200_MCP23S17T_INT2B */
    { GPIO_PORTG_BASE, GPIO_PIN_2, GPIO_INPUT }, /* 11 DTC1200_TAPE_WIDTH */
    };

    /* Memory for the GPIO module to construct a Hwi */
    Hwi_Struct callbackPortGHwi;

    const GPIO_Callbacks DTC1200_gpioPortGCallbacks = {
    GPIO_PORTG_BASE, INT_GPIOG, &callbackPortGHwi,
    {
    gpioExpInt1A, gpioExpInt2B, NULL, NULL
    }
    };

    const GPIO_Config GPIO_config[] = {
    {&gpioHWAttrs[0]},
    {&gpioHWAttrs[1]},
    {&gpioHWAttrs[2]},
    {&gpioHWAttrs[3]},
    {&gpioHWAttrs[4]},
    {&gpioHWAttrs[5]},
    {&gpioHWAttrs[6]},
    {&gpioHWAttrs[7]},
    {&gpioHWAttrs[8]},
    {&gpioHWAttrs[9]},
    {&gpioHWAttrs[10]},
    {&gpioHWAttrs[11]},
    {NULL},
    };

    /*
    * ======== DTC1200_initGPIO ========
    */
    void DTC1200_initGPIO(void)
    {
    // Enable pin PA3 for GPIOOutput
    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);
    // Enable pin PB5 for GPIOOutput
    GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_5);
    // Enable pin PC7 for GPIOInput
    GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, GPIO_PIN_7);
    // Enable pin PC6 for GPIOOutput
    GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, GPIO_PIN_6);
    // Enable pin PD4 for GPIOOutput
    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_4);
    // Enable pin PD5 for GPIOOutput
    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_5);
    // Enable pin PD1 for GPIOOutput
    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_1);
    // Enable pin PF3 for GPIOOutput
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3);
    // Enable pin PF2 for GPIOOutput
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
    // Enable pin PG4 for GPIOInput
    GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_4);
    // Enable pin PG3 for GPIOInput
    GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_3);
    // Enable pin PG2 for GPIOInput
    GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_2);

    /* Once GPIO_init is called, GPIO_config cannot be changed */
    GPIO_init();
    }

    /*
    * =============================== I2C ===============================
    */

    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(I2C_config, ".const:I2C_config")
    #pragma DATA_SECTION(i2cTivaHWAttrs, ".const:i2cTivaHWAttrs")
    #endif

    #include <ti/drivers/I2C.h>
    #include <ti/drivers/i2c/I2CTiva.h>

    /* I2C objects */
    I2CTiva_Object i2cTivaObjects[DTC1200_I2CCOUNT];

    /* I2C configuration structure, describing which pins are to be used */
    const I2CTiva_HWAttrs i2cTivaHWAttrs[DTC1200_I2CCOUNT] = {
    {I2C0_BASE, INT_I2C0},
    {I2C1_BASE, INT_I2C1},
    };

    const I2C_Config I2C_config[] = {
    {&I2CTiva_fxnTable, &i2cTivaObjects[0], &i2cTivaHWAttrs[0]},
    {&I2CTiva_fxnTable, &i2cTivaObjects[1], &i2cTivaHWAttrs[1]},
    {NULL, NULL, NULL}
    };

    /*
    * ======== DTC1200_initI2C ========
    */
    void DTC1200_initI2C(void)
    {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);

    // Enable pin PB2 for I2C0 I2C0SCL
    GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
    // Enable pin PB3 for I2C0 I2C0SDA
    GPIOPinConfigure(GPIO_PB3_I2C0SDA);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);

    // Enable pin PA7 for I2C1 I2C1SDA
    GPIOPinConfigure(GPIO_PA7_I2C1SDA);
    GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
    // Enable pin PA6 for I2C1 I2C1SCL
    GPIOPinConfigure(GPIO_PA6_I2C1SCL);
    GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);

    I2C_init();
    }

    /*
    * =============================== SPI ===============================
    */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(SPI_config, ".const:SPI_config")
    #pragma DATA_SECTION(spiTivaDMAHWAttrs, ".const:spiTivaDMAHWAttrs")
    #endif

    #include <ti/drivers/SPI.h>
    #include <ti/drivers/spi/SPITivaDMA.h>

    /* SPI objects */
    SPITivaDMA_Object spiTivaDMAObjects[DTC1200_SPICOUNT];
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN(spiTivaDMAscratchBuf, 32)
    #elif defined(__IAR_SYSTEM_ICC__)
    #pragma data_alignment=32
    #elif defined(__GNUC__)
    __attribute__ ((aligned (32)))
    #endif
    uint32_t spiTivaDMAscratchBuf[DTC1200_SPICOUNT];

    /* SPI configuration structure, describing which pins are to be used */
    const SPITivaDMA_HWAttrs spiTivaDMAHWAttrs[DTC1200_SPICOUNT] = {
    {
    SSI0_BASE,
    INT_SSI0,
    &spiTivaDMAscratchBuf[0],
    0,
    UDMA_CHANNEL_SSI0RX,
    UDMA_CHANNEL_SSI0TX,
    uDMAChannelAssign,
    UDMA_CH10_SSI0RX,
    UDMA_CH11_SSI0TX
    },
    {
    SSI1_BASE,
    INT_SSI1,
    &spiTivaDMAscratchBuf[1],
    0,
    UDMA_CHANNEL_SSI1RX,
    UDMA_CHANNEL_SSI1TX,
    uDMAChannelAssign,
    UDMA_CH24_SSI1RX,
    UDMA_CH25_SSI1TX
    },
    {
    SSI2_BASE,
    INT_SSI2,
    &spiTivaDMAscratchBuf[2],
    0,
    UDMA_SEC_CHANNEL_UART2RX_12,
    UDMA_SEC_CHANNEL_UART2TX_13,
    uDMAChannelAssign,
    UDMA_CH12_SSI2RX,
    UDMA_CH13_SSI2TX
    },
    };

    const SPI_Config SPI_config[] = {
    {&SPITivaDMA_fxnTable, &spiTivaDMAObjects[0], &spiTivaDMAHWAttrs[0]},
    {&SPITivaDMA_fxnTable, &spiTivaDMAObjects[1], &spiTivaDMAHWAttrs[1]},
    {&SPITivaDMA_fxnTable, &spiTivaDMAObjects[2], &spiTivaDMAHWAttrs[2]},
    {NULL, NULL, NULL},
    };

    /*
    * ======== DTC1200_initSPI ========
    */
    void DTC1200_initSPI(void)
    {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);

    /* === Configure and Enable SSI0 === */

    // Enable pin PA4 for SSI0 SSI0RX
    GPIOPinConfigure(GPIO_PA4_SSI0RX);
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_4);
    // Enable pin PA2 for SSI0 SSI0CLK
    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2);
    // Enable pin PA5 for SSI0 SSI0TX
    GPIOPinConfigure(GPIO_PA5_SSI0TX);
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5);

    /* === Configure and Enable SSI1 === */

    // Enable pin PD2 for SSI1 SSI1RX
    GPIOPinConfigure(GPIO_PD2_SSI1RX);
    GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_2);
    // Enable pin PD3 for SSI1 SSI1TX
    GPIOPinConfigure(GPIO_PD3_SSI1TX);
    GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_3);
    // Enable pin PD0 for SSI1 SSI1CLK
    GPIOPinConfigure(GPIO_PD0_SSI1CLK);
    GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_0);

    /* === Configure and Enable SSI2 === */

    // Enable pin PB7 for SSI2 SSI2TX
    GPIOPinConfigure(GPIO_PB7_SSI2TX);
    GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_7);
    // Enable pin PB4 for SSI2 SSI2CLK
    GPIOPinConfigure(GPIO_PB4_SSI2CLK);
    GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_4);
    // Enable pin PB6 for SSI2 SSI2RX
    GPIOPinConfigure(GPIO_PB6_SSI2RX);
    GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_6);

    DTC1200_initDMA();
    SPI_init();
    }
  • Here's my config file also if this helps...


    var Defaults = xdc.useModule('xdc.runtime.Defaults');
    var Diags = xdc.useModule('xdc.runtime.Diags');
    var Error = xdc.useModule('xdc.runtime.Error');
    var Log = xdc.useModule('xdc.runtime.Log');
    var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
    var Main = xdc.useModule('xdc.runtime.Main');
    var Memory = xdc.useModule('xdc.runtime.Memory')
    var SysMin = xdc.useModule('xdc.runtime.SysMin');
    var System = xdc.useModule('xdc.runtime.System');
    var Text = xdc.useModule('xdc.runtime.Text');

    var BIOS = xdc.useModule('ti.sysbios.BIOS');
    var Clock = xdc.useModule('ti.sysbios.knl.Clock');
    var Swi = xdc.useModule('ti.sysbios.knl.Swi');
    var Task = xdc.useModule('ti.sysbios.knl.Task');
    var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');
    var Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
    var Mailbox = xdc.useModule('ti.sysbios.knl.Mailbox');

    /*
    * Uncomment this line to globally disable Asserts.
    * All modules inherit the default from the 'Defaults' module. You
    * can override these defaults on a per-module basis using Module.common$.
    * Disabling Asserts will save code space and improve runtime performance.
    Defaults.common$.diags_ASSERT = Diags.ALWAYS_OFF;
    */

    /*
    * Uncomment this line to keep module names from being loaded on the target.
    * The module name strings are placed in the .const section. Setting this
    * parameter to false will save space in the .const section. Error and
    * Assert messages will contain an "unknown module" prefix instead
    * of the actual module name.
    Defaults.common$.namedModule = false;
    */

    /*
    * Minimize exit handler array in System. The System module includes
    * an array of functions that are registered with System_atexit() to be
    * called by System_exit().
    */
    System.maxAtexitHandlers = 4;

    /*
    * Uncomment this line to disable the Error print function.
    * We lose error information when this is disabled since the errors are
    * not printed. Disabling the raiseHook will save some code space if
    * your app is not using System_printf() since the Error_print() function
    * calls System_printf().
    Error.raiseHook = null;
    */

    /*
    * Uncomment this line to keep Error, Assert, and Log strings from being
    * loaded on the target. These strings are placed in the .const section.
    * Setting this parameter to false will save space in the .const section.
    * Error, Assert and Log message will print raw ids and args instead of
    * a formatted message.
    Text.isLoaded = false;
    */

    /*
    * Uncomment this line to disable the output of characters by SysMin
    * when the program exits. SysMin writes characters to a circular buffer.
    * This buffer can be viewed using the SysMin Output view in ROV.
    SysMin.flushAtExit = false;
    */

    /*
    * The BIOS module will create the default heap for the system.
    * Specify the size of this default heap.
    */
    BIOS.heapSize = 0x1000;

    /*
    * Build a custom SYS/BIOS library from sources.
    */
    BIOS.libType = BIOS.LibType_Custom;

    /* System stack size (used by ISRs and Swis) */
    Program.stack = 0x400;
    Program.argSize = 0;

    /* Circular buffer size for System_printf() */
    SysMin.bufSize = 0x200;

    /*
    * Create and install logger for the whole system
    */
    var loggerBufParams = new LoggerBuf.Params();
    loggerBufParams.numEntries = 16;
    var logger0 = LoggerBuf.create(loggerBufParams);
    Defaults.common$.logger = logger0;
    Main.common$.diags_INFO = Diags.ALWAYS_ON;

    System.SupportProxy = SysMin;

    /* ================ Driver configuration ================ */
    var TIRTOS = xdc.useModule('ti.tirtos.TIRTOS');
    TIRTOS.useGPIO = true;
    TIRTOS.useSDSPI = false;
    TIRTOS.useSPI = true;
    TIRTOS.useWatchdog = true;
    TIRTOS.useI2C = true;
    TIRTOS.useUART = true;
    Program.argSize = 0;
    TIRTOS.libType = TIRTOS.LibType_Instrumented;
    LoggerBuf.enableFlush = true;
    LoggerBuf.filterByLevel = false;
  • For some reason, it also seems to crash in the debugger if I try and step over a function that makes SPI calls. I just attempted to step over functions that call my I/O expander and it crashes with the following. However, if I hard reset the board out of the debugger it seems to come up running flashing a LED on the I/O expander like it's working.

    [CORTEX_M4_0] e: 0x20001400.
    Task stack size: 0x800.
    R0 = 0x00000000 R8 = 0xffffffff
    R1 = 0x10000000 R9 = 0xffffffff
    R2 = 0x00000000 R10 = 0xffffffff
    R3 = 0xffffffff R11 = 0xffffffff
    R4 = 0x00000000 R12 = 0x14650200
    R5 = 0x00010328 SP(R13) = 0x20001b48
    R6 = 0xffffffff LR(R14) = 0x000099a9
    R7 = 0xffffffff PC(R15) = 0x0000964c
    PSR = 0x61000000
    ICSR = 0x10400803
    MMFSR = 0x00
    BFSR = 0x00
    UFSR = 0x0008
    HFSR = 0x40000000
    DFSR = 0x00000001
    MMAR = 0xe000ed34
    BFAR = 0xe000ed38
    AFSR = 0x00000000
    Terminating execution...
    e: 0x20000608.
    Task stack size: 0x800.
    R0 = 0x00000000 R8 = 0xffffffff
    R1 = 0x00000000 R9 = 0xffffffff
    R2 = 0x00000000 R10 = 0xffffffff
    R3 = 0x00000000 R11 = 0xffffffff
    R4 = 0xffffffff R12 = 0x00000000
    R5 = 0xffffffff SP(R13) = 0x20000e50
    R6 = 0xffffffff LR(R14) = 0x00000000
    R7 = 0xffffffff PC(R15) = 0x00000000
    PSR = 0x00000000
    ICSR = 0x00423849
    MMFSR = 0x00
    BFSR = 0x00
    UFSR = 0x0008
    HFSR = 0x40000000
    DFSR = 0x00000001
    MMAR = 0xe000ed34
    BFAR = 0xe000ed38
    AFSR = 0x00000000
    Terminating execution...
  • Hi Robert,
    Have you also looked at the ROV views (it's under the Tools menu in CCS)? And what about the call stack?
    I would put a breakpoint just before the SPI_transfer just to check that there are no errors (you can check the Task and SysBios views)
    Also, could you edit your previous posts to include your code with the Syntax Highlighter or attach the source to the thread. That would make the code more readable.
    Michel
  • Sorry, didn't see the attach file option. I'm new to CCS, TI-RTOS and Tiva. Originally my project was on a Stellaris and running FreeRTOS. Since then I've been trying to port my code to TI-RTOS and Tiva TM4C123EA6PMI.

    I've looked at the ROV, but still trying to understand how to use this and what information it's showing me. Another issue is that FreeRTOS had a synchronization support for the SPI driver. It appears TI-RTOS does not, but I'm not sure how best to implement this as well. I have several tasks in my application that need to communicate over the SPI busses. My code implements a servo loop with Clock also that controls the motor DAC over SPI0 The other two SPI busses (SPI1 & SPI2) need mutual exclusion of some sort.

    Would a semaphore work for multiple tasks trying to access the SPI bus? I have a Clock callback that just writes to SPI0, but two other tasks that need to access SPI1 and SPI2.

    Sorry for the information overload. I'll try the ROV more and see if I can find anything from this. Thanks again for your help, it's greatly appreciated!

    7522.tivasupport.zipBob