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.

AM2634: Not able to communicate with DAC81408 using AM2634_CC EVM Board

Part Number: AM2634
Other Parts Discussed in Thread: DAC81408, , SYSCONFIG

Hi Team,

I am currently working on interfacing the DAC81408 module with the AM2634 controller board using the SPI1 interface, but I am unable to observe any output from the DAC.

The connections made are as follows:

  • SPI1_D0 → J8 (Pin 3)
  • SPI1_D1 → J8 (Pin 4)
  • SPI1_CLK → J8 (Pin 8)
  • SPI1_CS → J8 (Pin 2)

Additional details:

  • Common ground is established between the DAC module and the controller board.
  • Proper supply voltages (VCC and VSS) have been applied.
  • The reference voltage has been verified, and I am measuring 2.5V at J1 (Pin 7).

Despite these checks, I am still not able to get any output from the DAC. I have attached my code for your reference.

This issue is currently blocking my project progress, so I would greatly appreciate your help at the earliest. Could you please advise if there are any specific SysConfig settings, SPI configurations, or initialization steps required for proper communication?

CODE:

#include <kernel/dpl/ClockP.h>
#include <kernel/dpl/DebugP.h>
#include "ti_drivers_config.h"
#include "ti_drivers_open_close.h"
#include "ti_board_open_close.h"
#include <drivers/hw_include/tistdtypes.h>
#include <stdlib.h>
#include <string.h>
#include "analog_dac.h"

uint32_t            startTimeInUSec, elapsedTimeInUsecs;

void *dac81408_main(void *args)
{

    Drivers_open();
    Board_driversOpen();

    Reset_Signal();

    startTimeInUSec = ClockP_getTimeUsec();
    init_dac81408();
    elapsedTimeInUsecs = ClockP_getTimeUsec() - startTimeInUSec;
    DebugP_log(" \tTotal Time for Completion : \t\t%5.2f\r\n",(Float32)(elapsedTimeInUsecs / 1));


    Board_driversClose();
    Drivers_close();

    return NULL;
}


/******************************** DAC *********************************************************/

void init_dac81408()
{
    DebugP_log(" [SPI1] DAC PINS [DAC0-DAC3] DIFFERENTIAL and SINGLE ENDED[DAC4-DAC7]\r\n");
    clear_DAC_Register();
    ClockP_usleep(25);

    DebugP_log("init_dac81408!!\r\n");

    //Setting DAC Register
    DAC81408_Settings();

    //Setting DAC Range Register
    Set_DAC_Range();

    //getDAC81408_Status();

    //Setting Input Voltage to DAC Out Register
    float inVol = 18.6;
    DebugP_log("Input Voltage : %f\r\n",inVol);
    Set_InputVoltage_To_DAC(inVol);
    //getDAC81408_Status();
    DebugP_log("exit_dac81408!!\r\n");

}

void SPI_Write_To_DAC(uint8_t reg,uint16_t wdata)
{
    MCSPI_Handle spiHandle = NULL;

    uint8_t lsb = ((uint16_t)wdata >> 0) & 0xFF;
    uint8_t msb = ((uint16_t)wdata >> 8) & 0xFF;

    uint8_t txbuffer[3] = {reg,msb,lsb};
    SPI_Transaction(spiHandle, txbuffer, sizeof(txbuffer), NULL, 0);

}
void SPI_Read_Frm_DAC(uint8_t reg)
{
    MCSPI_Handle spiHandle = NULL;
    uint8_t txbuffer[3];
    txbuffer[0] = 0x80+reg;//Mask for Data Read from Register
    txbuffer[1] = 0x00;
    txbuffer[2] = 0x00;
    uint8_t rbuffer[3] = {0,0,0};

    SPI_Transaction(spiHandle, txbuffer, sizeof(txbuffer), NULL, 0);
    ClockP_usleep(5);
    SPI_Transaction(spiHandle, NULL , 0, rbuffer, sizeof(rbuffer));
    ClockP_usleep(5);

    uint16_t res = ((rbuffer[1] << 8) | rbuffer[2]) % 0x10000;

    getRegName(reg);
    DebugP_log("[SPI_Read_Frm_DAC] res = 0x%04x \r\n", res);
    //return res;
}
void SPI_Transaction(MCSPI_Handle spiHandle, uint8_t *txbuffer, size_t txSize, uint8_t *rxbuffer, size_t rxSize)
{
    MCSPI_OpenParams openParams;
    MCSPI_Transaction spiTransaction;
    int32_t transferOK;

    MCSPI_OpenParams_init(&openParams);
    //spiHandle = MCSPI_open(CONFIG_MCSPI0, &openParams);
    spiHandle = MCSPI_open(CONFIG_MCSPI1, &openParams);
    //spiHandle = MCSPI_open(CONFIG_MCSPI2, &openParams);

    if (spiHandle == NULL)
    {
        DebugP_log("Error: Unable to open SPI handle.\r\n");
        return;
    }

    SPI_CS_High_Low(0);

    MCSPI_Transaction_init(&spiTransaction);
    spiTransaction.csDisable = FALSE;
    spiTransaction.count = txSize+rxSize;
    spiTransaction.txBuf = txbuffer;
    spiTransaction.rxBuf = rxbuffer;

    transferOK = MCSPI_transfer(spiHandle, &spiTransaction);
    if (transferOK != SystemP_SUCCESS)
    {
        DebugP_log("Error: SPI transfer failed.\r\n");
    }

    SPI_CS_High_Low(1);
    MCSPI_close(spiHandle);
}

/*
 * this fun is going to clear the DAC Output Register Value
 *
 * */

void clear_DAC_Register(void)
{

    //CLR PIN in DAC is PIN9 and AM2634 Controller:GPIOPIN 44 and HSEC PIN:51

    uint32_t gpioClrDACOutRegBaseAddr = (uint32_t) AddrTranslateP_getLocalAddr(GPIO_CLR_BASE_ADDR);
    uint32_t clrDACOutPinNum = GPIO_CLR_PIN;
    GPIO_setDirMode(gpioClrDACOutRegBaseAddr, clrDACOutPinNum, GPIO_CLR_DIR);

    GPIO_pinWriteLow(gpioClrDACOutRegBaseAddr, clrDACOutPinNum);
    ClockP_usleep(25); //As per Data sheet Min delay is 20ns but given max delay for synchronization
    GPIO_pinWriteHigh(gpioClrDACOutRegBaseAddr, clrDACOutPinNum);
    ClockP_usleep(25);

}

uint16_t CodeVal_UnipolarVoltage_FSR40(float vout)
{
    /*
     *   Vout = ((code/2^n) * FSR)+ Vmin ; As per data sheet
     *   code = (Vout*2^n)/FSR
     *
     *   FSR : Full Scale Range: (Vmax-Vmin)
     *   Code : Binary value feed to DACnDATA Register
     *   Vout : Output Voltage
     *   2^n : Resolution : DAC81408 is 16Bit then 2^16 = 65536
     *
     *   NOTE : FSR is Fixed : Single Ended = 0V to 30V
     *                : Differential : -15V to +15V
     *   FSR : 0V to 40V Fixed.
     * */
    uint16_t code = 0;
    code = ((vout*RESOLUTION)/FSR_40);
    DebugP_log("Single Ended Code Value : %d and 0x%x \r\n",code,code);
    return code;
}
uint16_t CodeVal_UnipolarVoltage_FSR20(float vout)
{

    uint16_t code = 0;
    code = ((vout*RESOLUTION)/FSR_20);
    DebugP_log("Single Ended Code Value : %d and 0x%x \r\n",code,code);
    return code;
}
uint16_t CodeVal_UnipolarVoltage_FSR10(float vout)
{

    uint16_t code = 0;
    code = ((vout*RESOLUTION)/FSR_10);
    DebugP_log("Single Ended Code Value : %d and 0x%x \r\n",code,code);
    return code;
}
uint16_t CodeVal_UnipolarVoltage_FSR5(float vout)
{

    uint16_t code = 0;
    code = ((vout*RESOLUTION)/FSR_5);
    DebugP_log("Single Ended Code Value : %d and 0x%x \r\n",code,code);
    return code;
}

int16_t CodeVal_BipolarVoltage(float vout)
{
    //DebugP_log("vout = %f \r\n", vout);
    int16_t code = 0;

    // the range from -10V to +10V and 0 to 65535
    code = (uint16_t)((((vout + (FSR_20 / 2)) * RESOLUTION) / FSR_20));
    DebugP_log("Differential Code Value : %d and 0x%x \r\n", code, code);
    return code;
}

int16_t CodeVal_BipolarVoltage_FSR40(float vout)
{
    //DebugP_log("vout = %f \r\n", vout);
    int16_t code = 0;

    // the range from -10V to +10V and 0 to 65535
    code = (uint16_t)((((vout + (FSR_40 / 2)) * RESOLUTION) / FSR_40));
    DebugP_log("Differential Code Value : %d and 0x%x \r\n", code, code);
    return code;
}
int16_t CodeVal_BipolarVoltage_FSR20(float vout)
{
    //DebugP_log("vout = %f \r\n", vout);
    int16_t code = 0;

    // the range from -10V to +10V and 0 to 65535
    code = (uint16_t)((((vout + (FSR_20 / 2)) * RESOLUTION) / FSR_20));
    DebugP_log("Differential Code Value : %d and 0x%x \r\n", code, code);
    return code;
}
int16_t CodeVal_BipolarVoltage_FSR10(float vout)
{
    //DebugP_log("vout = %f \r\n", vout);
    int16_t code = 0;

    // the range from -10V to +10V and 0 to 65535
    code = (uint16_t)((((vout + (FSR_10 / 2)) * RESOLUTION) / FSR_10));
    DebugP_log("Differential Code Value : %d and 0x%x \r\n", code, code);
    return code;
}
int16_t CodeVal_BipolarVoltage_FSR5(float vout)
{
    //DebugP_log("vout = %f \r\n", vout);
    int16_t code = 0;

    // the range from -10V to +10V and 0 to 65535
    code = (uint16_t)((((vout + (FSR_5 / 2)) * RESOLUTION) / FSR_5));
    DebugP_log("Differential Code Value : %d and 0x%x \r\n", code, code);
    return code;
}

//OFFSET FOR DIFFERENTIAL VOLATAGE ERROR SETTINGS: ±0.2%FSR(FSR=40)
void Set_Offset_All_DAC_OUT_Pin(void)
{
    write_offsetn_register(R_OFFSET1, 0x00, 0xEC, R_DAC0DATA, 0xFFFF);//-20V to +20V
    write_offsetn_register(R_OFFSET1, 0x00, 0x14, R_DAC1DATA, 0xFFFF);//-20V to +20V
    write_offsetn_register(R_OFFSET1, 0x00, 0xEC, R_DAC2DATA, 0xFFFF);//-20V to +20V
    write_offsetn_register(R_OFFSET1, 0x00, 0x14, R_DAC3DATA, 0xFFFF);//-20V to +20V

    write_offsetn_register(R_OFFSET0, 0x00, 0xEC, R_DAC4DATA, 0xFFFF);//-20V to +20V
    write_offsetn_register(R_OFFSET0, 0x00, 0x14, R_DAC5DATA, 0xFFFF);//-20V to +20V
    write_offsetn_register(R_OFFSET0, 0x00, 0xEC, R_DAC6DATA, 0xFFFF);//-20V to +20V
    write_offsetn_register(R_OFFSET0, 0x00, 0x14, R_DAC7DATA, 0xFFFF);//-20V to +20V
}
//OFFSET FOR DIFFERENTIAL VOLATAGE ERROR SETTINGS
void write_offsetn_register(uint8_t reg, uint8_t offset_ab, uint8_t offset_cd, uint8_t dac_data_reg, uint16_t dac_data)
{
    // write_offsetn_register(R_OFFSET2, 0x1A, 0x05, R_DAC1DATA, 0xFFFF);
    uint16_t offset_value = (offset_ab << 8) | offset_cd;

    // Write to the OFFSETn register
    SPI_Write_To_DAC(reg, offset_value);

    // Rewriting the DAC data register to apply the offset
    SPI_Write_To_DAC(dac_data_reg, dac_data);
}

void getRegName(uint8_t reg)
{
    switch(reg)
    {
    case 0x01:
        DebugP_log(" [ Device ID : ");
        break;
    case 0x02:
        DebugP_log(" [ DAC Status : ");
        break;
    case 0x03:
        DebugP_log(" [SPI Configuration : ");
        break;
    case 0x04:
        DebugP_log(" [General Configuration : ");
        break;
    default:
        break;

    }
}

void Set_Bipolar_DACOUTChannel(int16_t dacVal)
{
    SPI_Write_To_DAC(R_DAC0DATA,dacVal);

    SPI_Write_To_DAC(R_DAC1DATA,dacVal);

    SPI_Write_To_DAC(R_DAC2DATA,dacVal);

    SPI_Write_To_DAC(R_DAC3DATA,dacVal);

}
void Set_Unipolar_DACOUTChannel(int16_t dacVal)
{


    SPI_Write_To_DAC(R_DAC4DATA,dacVal);

    SPI_Write_To_DAC(R_DAC5DATA,dacVal);

    SPI_Write_To_DAC(R_DAC6DATA,dacVal);

    SPI_Write_To_DAC(R_DAC7DATA,dacVal);

}

void DAC81408_Settings(void)
{
    SPI_Read_Frm_DAC(R_DEVICEID);

    SPI_Write_To_DAC(R_SPICONFIG,0x0A84);
    SPI_Read_Frm_DAC(R_SPICONFIG);
    //ClockP_usleep(1);
    //SPI_Write_To_DAC(R_GENCONFIG,0x7F00);//use on board REF5025 reference
    SPI_Write_To_DAC(R_GENCONFIG,0x7F0C);// DAC PIN0 and PIN3 configured for Differential
    SPI_Read_Frm_DAC(R_GENCONFIG);
    SPI_Write_To_DAC(R_BRDCONFIG,0xFFFF);
    //to power-up the individual DAC channels
    SPI_Write_To_DAC(R_DACPWDWN,0x0000);
    //BRDCAST Register has no effect for differential voltage.
    SPI_Write_To_DAC(R_BRDCAST,0xFFFF);
}

/*
 * Fun Name: Set_DAC_Range
 * This Function is Setting the DAC Range Register;
 *  Range : 0 to 5V,0 to 10V,0V to 20V, 0 to 40V For Single Ended Channel.
 *        : -2.5V to +2.5V,-5V to +5V,-10V to +10V, -20V to +20V For Differential Channel.
 * */
void Set_DAC_Range(void)
{
    // Single Ended Range :0V to 40V for all DAC4 to DAC7
    SPI_Write_To_DAC(R_DACRANGE0,U_40V_CH7|U_40V_CH6|U_40V_CH5|U_40V_CH4);
    // Differential Range : +20V to -20V on DAC0 to DAC3
    SPI_Write_To_DAC(R_DACRANGE1,B_20V_CH3| B_20V_CH2 |B_20V_CH1|B_20V_CH0);
    //DebugP_log(" : 0x%4x \r\n", ZERO|ZERO|ZERO|B_10V_CH0);
}

/*
 * Fun Name: Set_InputVoltage_To_DAC
 * Function is Set to desired input voltage to DAC Output Channel;
 *
 * */
void Set_InputVoltage_To_DAC(float Vout)
{
    //float Vout = 9;
    int16_t dacDataVoutdiff = CodeVal_BipolarVoltage_FSR40(Vout);
    int16_t dacDataVoutSin = CodeVal_UnipolarVoltage_FSR40(Vout);

    Set_Bipolar_DACOUTChannel(dacDataVoutdiff);
    ClockP_usleep(1);
    Set_Unipolar_DACOUTChannel(dacDataVoutSin);
    ClockP_usleep(1);
}


/*
 * Fun Name: getDAC81408_Status
 * Function is get the current status of DAC81408;
 *
 * */
void getDAC81408_Status(void)
{
    //if its return 0x0008 means status : DAC is not Busy.
    //if its return 0x0002 means status : DAC is Busy.
    SPI_Write_To_DAC(R_STATUS,0x0002);
    SPI_Read_Frm_DAC(R_STATUS);
}


void Reset_Signal()
{
    //GPIO24( Signal Name: I2C1_SDA/C8) -> HSEC PIN->85

    uint32_t gpioResetBaseAddr = (uint32_t) AddrTranslateP_getLocalAddr(GPIO_RESET_BASE_ADDR);
    uint32_t resetPinNum = GPIO_RESET_PIN;
    GPIO_setDirMode(gpioResetBaseAddr, resetPinNum, GPIO_RESET_DIR);

    GPIO_pinWriteLow(gpioResetBaseAddr, resetPinNum);
    ClockP_usleep(1000);
    GPIO_pinWriteHigh(gpioResetBaseAddr, resetPinNum);
    ClockP_usleep(1000);

    DebugP_log("DAC81408 IC is successfully Reset!!\r\n");
}

void SPI_CS_High_Low(uint8_t val)
{
    //val = 1 enable and val = 0 Disable
    //GPIO Pin : GPIO43 (Signal Name:EPWM0_A/B2) and HSEC Pin : 49

    uint32_t gpioChipSelectBaseAddr = (uint32_t) AddrTranslateP_getLocalAddr(GPIO_CS_OUT_BASE_ADDR);
    uint32_t ChipSelectPinNum = GPIO_CS_OUT_PIN;
    GPIO_setDirMode(gpioChipSelectBaseAddr, ChipSelectPinNum, GPIO_CS_OUT_DIR);

    if (val == 1)
    {
        GPIO_pinWriteHigh(gpioChipSelectBaseAddr, ChipSelectPinNum);
        //DebugP_log("CS High!!\r\n");
    }
    else
    {
        GPIO_pinWriteLow(gpioChipSelectBaseAddr, ChipSelectPinNum);
        //DebugP_log("CS Low!!\r\n");
    }
}

Thanks in advance for your support.

Best regards,
Swarna

  • Hi Swarna,

    Your code has several critical issues that will prevent communication with the DAC81408. I've identified both AM2634 MCSPI driver misuse and DAC81408-specific protocol violations.


    Critical Issue #1: Opening/Closing MCSPI Handle Every Transaction

    Your SPI_Transaction() function calls MCSPI_open() and MCSPI_close() on every single SPI transfer. This is fundamentally broken — calling MCSPI_open() a second time on the same instance without closing it first returns an error [1]. Since you do close it each time, you're paying massive overhead and risking re-initialization failures across your many rapid sequential writes.

    Fix: Open the MCSPI handle once during initialization and reuse it for all transactions:

    // Open once at startup
    MCSPI_OpenParams openParams;
    MCSPI_OpenParams_init(&openParams);
    MCSPI_Handle gSpiHandle = MCSPI_open(CONFIG_MCSPI1, &openParams);
    
    // Use gSpiHandle for all transfers, close only at shutdown

    Critical Issue #2: Wrong SPI Mode

    The DAC81408 samples data on the falling edge of SCLK [2]. This means your MCSPI must be configured for SPI Mode 1 (CPOL=0, CPHA=1) or Mode 2 (CPOL=1, CPHA=0). If your SysConfig is set to Mode 0 (the default), the DAC will not latch any data correctly. This exact issue has been confirmed by multiple users who couldn't get output until switching to Mode 1 [2].

    Fix: In SysConfig, set the clock phase so that data is updated on the rising edge and sampled on the falling edge.


    Critical Issue #3: SPI Frame Length Must Be 24 Bits

    The DAC81408 expects exactly 24-bit SPI frames (8-bit address + 16-bit data) [3]. If your MCSPI is configured for 8-bit data width and you're sending 3 bytes as separate 8-bit transfers within one transaction, verify that CS remains asserted for the entire 24-bit frame. Sending 32-bit frames will cause writes to be silently ignored [3].

    Fix: Ensure your SysConfig data width and transaction count produce a continuous 24-bit transfer with CS held low throughout.


    Critical Issue #4: Conflicting Chip Select Control

    Your code manually toggles CS via GPIO (SPI_CS_High_Low()) and sets spiTransaction.csDisable = FALSE, which tells the MCSPI driver to also manage CS. This creates a conflict — the driver may assert/deassert CS at different times than your GPIO, causing timing violations [4].

    Fix: Choose one approach:

    • Option A (Recommended): Let the MCSPI driver handle CS natively. Remove SPI_CS_High_Low() calls and configure the CS pin in SysConfig as an MCSPI-managed chip select.
    • Option B: If you must use GPIO for CS, set spiTransaction.csDisable = TRUE so the driver doesn't touch CS, and ensure proper timing between your GPIO toggles and the actual data transfer.

    Critical Issue #5: DAC Initialization Sequence

    Your DAC81408_Settings() writes R_DACPWDWN = 0x0000 to power up channels, which is correct. However, ensure the sequence follows this order [5][6]:

    1. Power up the device: Write 0x0A04 to SPICONFIG (register 0x03) — you're doing 0x0A84, verify this matches your needs
    2. Enable internal reference / configure GENCONFIG
    3. Set DAC range registers
    4. Then write to DACnDATA registers (these are write-only — you cannot read them back) [3]

    Critical Issue #6: Timing Between Transactions

    The DAC81408 requires a minimum 50ns CS high time between configuration register writes, and a 2.4µs tDACWAIT delay after LDAC events before the next CS falling edge [6][7]. Your rapid-fire writes with open/close overhead may inadvertently satisfy this, but once you fix the handle reuse, add explicit delays:

    ClockP_usleep(3); // After writing DAC data registers, before next transaction

    Recommended SysConfig Settings for MCSPI1

    Parameter
    Value
    Clock Phase (CPHA)
    1 (data sampled on falling edge)
    Clock Polarity (CPOL)
    0
    Data Width
    8 bits (with 3-byte count) or 24 bits if supported
    CS Polarity
    Active Low
    Bit Rate
    ≤ 50 MHz (start with 1 MHz for debugging)
    CS Mode
    Hardware-managed (remove GPIO CS control)

    Debugging Steps

    1. Read the DEVICEID register (0x01) — you should get a known value. If you get 0xFFFF or 0x0000, SPI communication is not working at all.
    2. Use an oscilloscope/logic analyzer to verify CLK, MOSI, and CS signals are present and correctly timed.
    3. Start with a single register write/read (SPICONFIG) before attempting full initialization.

    To help refine this recommendation, it would be helpful to know:

    • What SPI mode (CPOL/CPHA) and clock frequency are currently configured in your SysConfig settings?
    • What value does SPI_Read_Frm_DAC(R_DEVICEID) return? (Expected: device-specific ID, not 0x0000 or 0xFFFF)
    • Can you capture the SPI signals (CLK, MOSI, CS) with an oscilloscope to confirm they are being generated?
    • Is MCSPI_transfer() returning SystemP_SUCCESS or failing?

    Resources:

    1. MCSPI HLD Driver Documentation - AM263x SDK
    2. DAC81408EVM: Internal Oscillator Error - E2E Forum
    3. DAC81408EVM: 24-bit SPI Frame Requirement - E2E Forum
    4. AM2634: SPI Slave FIFO and CS Timing - E2E Forum
    5. DAC81408: Initialization and Reference Enable - E2E Forum
    6. DAC81408: Register Setting Methods and Timing - E2E Forum
    7. DAC81408: tDACWAIT Timing Requirement - E2E Forum

    Best Regards,

    Zackary Fleenor

  • Hi Fleenor,

    I have been working on interfacing DAC81408 with AM2634_CC EVM using SPI1and implemented ALL the recommended fixes.

     

    Fix #1 - SPI Handle Management:

    - Changed from opening/closing handle on every transaction to a single global handle

    - SPI handle is opened once in init_spi() and reused for all transactions

    - MCSPI_close() is NOT called until the end of the program

     

    Fix #2 - SPI Mode:

    - SysConfig configured to Mode 1 (CPOL=0, CPHA=1)

    - Verified multiple times that this setting is active

     

    Fix #3 - Frame Length:

    - Using 3-byte (24-bit) transactions

    - CS is held low for all 3 bytes using manual GPIO control

     

    Fix #4 - Conflicting Chip Select Control:

    - Code: spiTransaction.csDisable = TRUE

    - SysConfig: Pin Mode = 3 Pin Mode

    - CS is controlled exclusively via GPIO161

     

    Fix #5 - Timing:

    - Added 10ms delay after RESET release

    - Added 1ms delay after power-up

    - Added small delays between SPI transactions

     

    Fix #6 - GENCONFIG Value:

    - Changed from 0x7F0C to 0x3F00 (enable internal reference)

     

    CURRENT HARDWARE SETUP

     

    AM2634_CC (HSEC)          -> DAC81408 (J8)

    SPI1_CLK (HSEC 91)         -> Pin 8 (SCLK)

    SPI1_D0(PIN 75)                -> Pin 3 (RXD/MISO)

    SPI1_D1(PIN 77)                 -> Pin 4 (TXD/MOSI)

    GND (HSEC GND)              -> Pin 6 (GND)

    GPIO75 (HSEC 161)           -> Pin 2 (CS)

    GPIO76 (HSEC 162)           -> Pin 10 (RESET)

    GPIO43 (HSEC 49)             -> Pin 9 (CLR)

     

    CURRENT RESULTS

    After implementing all fixes, the console output is:

     

    SPI1 initialized successfully.

    DAC81408 IC is successfully Reset!!

    [SPI1] DAC PINS [DAC0-DAC3] DIFFERENTIAL and SINGLE ENDED[DAC4-DAC7]

    init_dac81408!!

     [Device ID: [SPI_Read_Frm_DAC] res = 0x0000

    Device ID read: 0x0000

     [SPI Configuration: [SPI_Read_Frm_DAC] res = 0x0000

     [General Configuration: [SPI_Read_Frm_DAC] res = 0x0000

    Input Voltage: 18.600000

    Differential Code Value: -2294 (0xF70A)

    Single Ended Code Value: 30474 (0x770A)

    exit_dac81408!!

    OBSERVATIONS

     SPI signals (measured with picoscope):

       - SCLK: Clock pulses present

       - CS: Goes low during transaction

       - MOSI: Data being sent

    Code:

    #include <kernel/dpl/ClockP.h>
    #include <kernel/dpl/DebugP.h>
    #include "ti_drivers_config.h"
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"
    #include <drivers/hw_include/tistdtypes.h>
    #include <stdlib.h>
    #include <string.h>
    #include "analog_dac.h"

    // Global SPI handle - opened once and reused (FIX #1)
    static MCSPI_Handle gSpiHandle = NULL;

    // Timing variables
    uint32_t startTimeInUSec, elapsedTimeInUsecs;

    // ============================================================================
    // SPI Initialization - Call this ONCE at startup
    // ============================================================================
    void init_spi(void)
    {
    MCSPI_OpenParams openParams;

    MCSPI_OpenParams_init(&openParams);
    // SPI Mode (CPOL=0, CPHA=1) must be configured in SysConfig

    gSpiHandle = MCSPI_open(CONFIG_MCSPI1, &openParams);
    if (gSpiHandle == NULL)
    {
    DebugP_log("Error: Unable to open SPI1 handle.\r\n");
    }
    else
    {
    DebugP_log("SPI1 initialized successfully.\r\n");
    }
    }

    // ============================================================================
    // Main DAC Function
    // ============================================================================
    void *dac81408_main(void *args)
    {
    Drivers_open();
    Board_driversOpen();

    init_spi(); // Open SPI handle ONCE
    Reset_Signal(); // Reset the DAC

    startTimeInUSec = ClockP_getTimeUsec();
    init_dac81408(); // Initialize and configure DAC
    elapsedTimeInUsecs = ClockP_getTimeUsec() - startTimeInUSec;
    DebugP_log("Total Time for Completion: %5.2f ms\r\n", (Float32)(elapsedTimeInUsecs / 1000.0));

    Board_driversClose();
    Drivers_close();

    return NULL;
    }

    // ============================================================================
    // DAC Initialization Sequence
    // ============================================================================
    void init_dac81408(void)
    {
    while(1)
    {


    DebugP_log("[SPI1] DAC PINS [DAC0-DAC3] DIFFERENTIAL and SINGLE ENDED[DAC4-DAC7]\r\n");

    // Clear DAC registers
    clear_DAC_Register();
    ClockP_usleep(100);

    DebugP_log("init_dac81408!!\r\n");

    // Configure DAC registers
    DAC81408_Settings();

    // Set DAC range registers
    Set_DAC_Range();

    // Set output voltage
    float inVol = 18.6;
    DebugP_log("Input Voltage: %f\r\n", inVol);
    Set_InputVoltage_To_DAC(inVol);

    DebugP_log("exit_dac81408!!\r\n");
    ClockP_usleep(10000);
    }
    }

    // ============================================================================
    // SPI Transaction - Low level transfer (FIX #2: No open/close, csDisable=TRUE)
    // ============================================================================
    void SPI_Transaction(uint8_t *txbuffer, size_t txSize, uint8_t *rxbuffer, size_t rxSize)
    {
    MCSPI_Transaction spiTransaction;
    int32_t transferOK;

    if (gSpiHandle == NULL)
    {
    DebugP_log("Error: SPI handle not initialized.\r\n");
    return;
    }

    MCSPI_Transaction_init(&spiTransaction);
    spiTransaction.count = (txSize > rxSize) ? txSize : rxSize;
    spiTransaction.txBuf = txbuffer;
    spiTransaction.rxBuf = rxbuffer;
    spiTransaction.csDisable = TRUE; // CRITICAL: We manage CS manually via GPIO

    transferOK = MCSPI_transfer(gSpiHandle, &spiTransaction);
    if (transferOK != SystemP_SUCCESS)
    {
    DebugP_log("Error: SPI transfer failed.\r\n");
    }
    }

    // ============================================================================
    // SPI Write to DAC - 24-bit frame: Address (8-bit) + Data (16-bit)
    // ============================================================================
    void SPI_Write_To_DAC(uint8_t reg, uint16_t wdata)
    {
    uint8_t txbuffer[3];
    uint8_t rxbuffer[3];

    txbuffer[0] = reg; // Register address (bits 23-16)
    txbuffer[1] = (uint8_t)(wdata >> 8); // Data MSB (bits 15-8)
    txbuffer[2] = (uint8_t)(wdata & 0xFF); // Data LSB (bits 7-0)

    SPI_CS_High_Low(0); // Assert CS (active low)
    SPI_Transaction(txbuffer, 3, rxbuffer, 3); // Send 3 bytes, receive 3 dummy bytes
    SPI_CS_High_Low(1); // De-assert CS

    ClockP_usleep(1); // Small delay between transactions
    }

    // ============================================================================
    // SPI Read from DAC - 24-bit frame:
    // ============================================================================
    uint16_t SPI_Read_Frm_DAC(uint8_t reg)
    {
    uint8_t txbuffer[3];
    uint8_t rxbuffer[3] = {0, 0, 0};
    uint16_t result;

    // Read command: bit 7 = 1 (read operation), bits 6-0 = register address
    txbuffer[0] = 0x80 | reg; // Read command
    txbuffer[1] = 0x00; // Dummy byte
    txbuffer[2] = 0x00; // Dummy byte

    SPI_CS_High_Low(0); // Assert CS
    SPI_Transaction(txbuffer, 3, rxbuffer, 3); // Send command, receive data
    SPI_CS_High_Low(1); // De-assert CS

    // Combine received bytes into 16-bit result
    result = ((rxbuffer[1] << 8) | rxbuffer[2]) & 0xFFFF;

    getRegName(reg);
    DebugP_log("[SPI_Read_Frm_DAC] res = 0x%04x\r\n", result);

    return result;
    }

    // ============================================================================
    // GPIO: Chip Select Control
    // ============================================================================
    void SPI_CS_High_Low(uint8_t val)
    {
    // val = 1 = HIGH (inactive), val = 0 = LOW (active)
    uint32_t gpioChipSelectBaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(GPIO_CS_OUT_BASE_ADDR);
    uint32_t ChipSelectPinNum = GPIO_CS_OUT_PIN;

    GPIO_setDirMode(gpioChipSelectBaseAddr, ChipSelectPinNum, GPIO_CS_OUT_DIR);

    if (val == 1)
    {
    GPIO_pinWriteHigh(gpioChipSelectBaseAddr, ChipSelectPinNum);
    }
    else
    {
    GPIO_pinWriteLow(gpioChipSelectBaseAddr, ChipSelectPinNum);
    }
    }

    // ============================================================================
    // GPIO: Reset Signal
    // ============================================================================
    void Reset_Signal(void)
    {
    uint32_t gpioResetBaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(GPIO_RESET_BASE_ADDR);
    uint32_t resetPinNum = GPIO_RESET_PIN;

    GPIO_setDirMode(gpioResetBaseAddr, resetPinNum, GPIO_RESET_DIR);

    // Assert reset (active low)
    GPIO_pinWriteLow(gpioResetBaseAddr, resetPinNum);
    ClockP_usleep(100); // Hold reset for 100us (datasheet min 500ns)

    // Release reset
    GPIO_pinWriteHigh(gpioResetBaseAddr, resetPinNum);
    ClockP_usleep(1000); // Wait 1ms for DAC to stabilize after reset

    DebugP_log("DAC81408 IC is successfully Reset!!\r\n");
    }

    // ============================================================================
    // GPIO: Clear DAC Register 
    // ============================================================================
    void clear_DAC_Register(void)
    {
    uint32_t gpioClrDACOutRegBaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(GPIO_CLR_BASE_ADDR);
    uint32_t clrDACOutPinNum = GPIO_CLR_PIN;

    GPIO_setDirMode(gpioClrDACOutRegBaseAddr, clrDACOutPinNum, GPIO_CLR_DIR);

    // Pulse CLR low to clear registers
    GPIO_pinWriteLow(gpioClrDACOutRegBaseAddr, clrDACOutPinNum);
    ClockP_usleep(25);
    GPIO_pinWriteHigh(gpioClrDACOutRegBaseAddr, clrDACOutPinNum);
    ClockP_usleep(25);
    }

    // ============================================================================
    // DAC Register Name for Debug Logging
    // ============================================================================
    void getRegName(uint8_t reg)
    {
    switch(reg)
    {
    case 0x01: DebugP_log(" [Device ID: "); break;
    case 0x02: DebugP_log(" [DAC Status: "); break;
    case 0x03: DebugP_log(" [SPI Configuration: "); break;
    case 0x04: DebugP_log(" [General Configuration: "); break;
    default: break;
    }
    }

    // ============================================================================
    // DAC Configuration Settings (FIX #3: Correct sequence and values)
    // ============================================================================
    void DAC81408_Settings(void)
    {
    // Step 1: Read Device ID to verify communication
    uint16_t deviceId = SPI_Read_Frm_DAC(R_DEVICEID);
    DebugP_log("Device ID read: 0x%04x\r\n", deviceId);

    // Step 2: Configure SPICONFIG - Power up device
    // 0x0A04: FSDO=0 (SDO updates on rising edge), Power-up all blocks
    SPI_Write_To_DAC(R_SPICONFIG, 0x0A24);
    ClockP_usleep(100);
    SPI_Read_Frm_DAC(R_SPICONFIG);

    // Step 3: Configure GENCONFIG - Enable internal reference (CRITICAL!)
    // 0x3F00 enables internal 2.5V reference and configures outputs
    SPI_Write_To_DAC(R_GENCONFIG, 0x3F00);
    ClockP_usleep(100);
    SPI_Read_Frm_DAC(R_GENCONFIG);

    // Step 4: Power up all DAC channels (0x0000 = power up, 0xFFFF = power down)
    SPI_Write_To_DAC(R_DACPWDWN, 0x0000);
    ClockP_usleep(100);

    // Step 5: Configure broadcast
    SPI_Write_To_DAC(R_BRDCONFIG, 0xFFFF);
    SPI_Write_To_DAC(R_BRDCAST, 0xFFFF);
    }

    // ============================================================================
    // Set DAC Range Registers
    // ============================================================================
    void Set_DAC_Range(void)
    {
    // Single Ended Range: 0V to 40V for DAC4 to DAC7
    SPI_Write_To_DAC(R_DACRANGE0, U_40V_CH7 | U_40V_CH6 | U_40V_CH5 | U_40V_CH4);

    // Differential Range: -20V to +20V for DAC0 to DAC3
    SPI_Write_To_DAC(R_DACRANGE1, B_20V_CH3 | B_20V_CH2 | B_20V_CH1 | B_20V_CH0);
    }

    // ============================================================================
    // Code Value Calculation for Single Ended (0-40V range)
    // ============================================================================
    uint16_t CodeVal_UnipolarVoltage_FSR40(float vout)
    {
    uint16_t code = (uint16_t)((vout * RESOLUTION) / FSR_40);
    DebugP_log("Single Ended Code Value: %d (0x%04x)\r\n", code, code);
    return code;
    }

    // ============================================================================
    // Code Value Calculation for Differential (-20V to +20V range)
    // ============================================================================
    int16_t CodeVal_BipolarVoltage_FSR40(float vout)
    {
    int16_t code = (int16_t)((((vout + (FSR_40 / 2.0)) * RESOLUTION) / FSR_40));
    DebugP_log("Differential Code Value: %d (0x%04x)\r\n", code, (uint16_t)code);
    return code;
    }

    // ============================================================================
    // Set All Bipolar Channels (DAC0-DAC3)
    // ============================================================================
    void Set_Bipolar_DACOUTChannel(uint16_t dacVal)
    {
    SPI_Write_To_DAC(R_DAC0DATA, dacVal);
    SPI_Write_To_DAC(R_DAC1DATA, dacVal);
    SPI_Write_To_DAC(R_DAC2DATA, dacVal);
    SPI_Write_To_DAC(R_DAC3DATA, dacVal);
    }

    // ============================================================================
    // Set All Unipolar Channels (DAC4-DAC7)
    // ============================================================================
    void Set_Unipolar_DACOUTChannel(uint16_t dacVal)
    {
    SPI_Write_To_DAC(R_DAC4DATA, dacVal);
    SPI_Write_To_DAC(R_DAC5DATA, dacVal);
    SPI_Write_To_DAC(R_DAC6DATA, dacVal);
    SPI_Write_To_DAC(R_DAC7DATA, dacVal);
    }

    // ============================================================================
    // Set Output Voltage on All Channels
    // ============================================================================
    void Set_InputVoltage_To_DAC(float Vout)
    {
    uint16_t dacDataVoutdiff = (uint16_t)CodeVal_BipolarVoltage_FSR40(Vout);
    uint16_t dacDataVoutSin = CodeVal_UnipolarVoltage_FSR40(Vout);

    Set_Bipolar_DACOUTChannel(dacDataVoutdiff);
    ClockP_usleep(10);
    Set_Unipolar_DACOUTChannel(dacDataVoutSin);
    ClockP_usleep(10);
    }

    // ============================================================================
    // Set Single DAC Channel Output (Helper function)
    // ============================================================================
    void set_dac_output(uint8_t channel, uint16_t value)
    {
    uint8_t reg;

    switch(channel)
    {
    case 0: reg = R_DAC0DATA; break;
    case 1: reg = R_DAC1DATA; break;
    case 2: reg = R_DAC2DATA; break;
    case 3: reg = R_DAC3DATA; break;
    case 4: reg = R_DAC4DATA; break;
    case 5: reg = R_DAC5DATA; break;
    case 6: reg = R_DAC6DATA; break;
    case 7: reg = R_DAC7DATA; break;
    default: return;
    }

    SPI_Write_To_DAC(reg, value);
    }

     

    Please advise on what to check next. We have implemented all recommended fixes but are still stuck at 0x0000.

     

    Thank you for your support.

    Swarna

  • Hi Swarna,

    Thank you for the detailed follow-up with your updated code and SysConfig screenshots. You've implemented the recommended fixes correctly, but reading 0x0000 from all registers indicates that no SPI communication is occurring. Let me help you identify the root cause.

    Root Cause Analysis

    Reading 0x0000 from the Device ID register (which should return a non-zero device-specific ID) means one of the following is occurring:

    1. MISO line is stuck low or not connected properly
    2. DAC81408 is not powered or in reset state
    3. SPI clock polarity/phase mismatch despite Mode 1 configuration
    4. Timing violation between CS and SCLK
    5. Pin muxing issue in SysConfig

    Critical Issue #1: Incorrect Read Transaction Protocol

    Your SPI_Read_Frm_DAC() function has a fundamental flaw. You're sending the read command and receiving data in the same transaction, but the DAC81408 requires TWO separate transactions per the datasheet.

    Current implementation (incorrect):

    uint16_t SPI_Read_Frm_DAC(uint8_t reg)
    {
        txbuffer[0] = 0x80 | reg;
        txbuffer[1] = 0x00;
        txbuffer[2] = 0x00;
        
        SPI_CS_High_Low(0);
        SPI_Transaction(txbuffer, 3, rxbuffer, 3); // Wrong: expects data immediately
        SPI_CS_High_Low(1);
        
        result = ((rxbuffer[1] << 8) | rxbuffer[2]) & 0xFFFF;
        return result;
    }

    Correct DAC81408 read protocol requires:

    1. Transaction 1: Send read command (0x80 | register address) + 2 dummy bytes
    2. Wait (CS must go high, then low again)
    3. Transaction 2: Send 3 dummy bytes and receive the data

    Corrected code:

    uint16_t SPI_Read_Frm_DAC(uint8_t reg)
    {
        uint8_t txbuffer[3];
        uint8_t rxbuffer[3] = {0, 0, 0};
        uint16_t result;
    
        // Transaction 1: Send Read Command
        txbuffer[0] = 0x80 | reg;
        txbuffer[1] = 0x00;
        txbuffer[2] = 0x00;
    
        SPI_CS_High_Low(0);
        SPI_Transaction(txbuffer, 3, NULL, 0);
        SPI_CS_High_Low(1);
        
        ClockP_usleep(10); // Wait between transactions
    
        // Transaction 2: Retrieve Data
        txbuffer[0] = 0x00;
        txbuffer[1] = 0x00;
        txbuffer[2] = 0x00;
    
        SPI_CS_High_Low(0);
        SPI_Transaction(txbuffer, 3, rxbuffer, 3);
        SPI_CS_High_Low(1);
    
        result = ((rxbuffer[1] << 8) | rxbuffer[2]) & 0xFFFF;
        
        getRegName(reg);
        DebugP_log("[SPI_Read_Frm_DAC] res = 0x%04x\r\n", result);
        
        return result;
    }

    Critical Issue #2: SPI_Transaction Implementation

    Your current implementation needs adjustment to properly handle NULL buffers:

    void SPI_Transaction(uint8_t *txbuffer, size_t txSize, uint8_t *rxbuffer, size_t rxSize)
    {
        MCSPI_Transaction spiTransaction;
        int32_t transferOK;
    
        if (gSpiHandle == NULL)
        {
            DebugP_log("Error: SPI handle not initialized.\r\n");
            return;
        }
    
        MCSPI_Transaction_init(&spiTransaction);
        
        if (txSize > 0 && rxSize == 0) {
            // Write-only transaction
            spiTransaction.count = txSize;
            spiTransaction.txBuf = txbuffer;
            spiTransaction.rxBuf = NULL;
        } else if (txSize == 0 && rxSize > 0) {
            // Read-only transaction
            spiTransaction.count = rxSize;
            spiTransaction.txBuf = NULL;
            spiTransaction.rxBuf = rxbuffer;
        } else {
            // Full-duplex transaction
            spiTransaction.count = (txSize > rxSize) ? txSize : rxSize;
            spiTransaction.txBuf = txbuffer;
            spiTransaction.rxBuf = rxbuffer;
        }
        
        spiTransaction.csDisable = TRUE;
    
        transferOK = MCSPI_transfer(gSpiHandle, &spiTransaction);
        
        if (transferOK != SystemP_SUCCESS)
        {
            DebugP_log("Error: SPI transfer failed with status: %d\r\n", transferOK);
        }
    }

    Hardware Debugging Steps

    Step 1: Verify Power and Reset

    Add extended reset timing to ensure proper DAC initialization:

    void verify_dac_power_and_reset(void)
    {
        DebugP_log("=== DAC81408 Power-On Verification ===\r\n");
        
        // Check power supply pins with multimeter:
        // VDD (Pin 5): Should be 5V
        // AVDD (Pin 11): Should be 5V
        // IOVDD (Pin 1): Should be 3.3V or 5V
        // GND (Pin 6): Should be 0V
        
        uint32_t gpioResetBaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(GPIO_RESET_BASE_ADDR);
        uint32_t resetPinNum = GPIO_RESET_PIN;
        
        GPIO_setDirMode(gpioResetBaseAddr, resetPinNum, GPIO_RESET_DIR);
        
        GPIO_pinWriteLow(gpioResetBaseAddr, resetPinNum);
        DebugP_log("RESET asserted (LOW)\r\n");
        ClockP_usleep(10000); // Hold for 10ms
        
        GPIO_pinWriteHigh(gpioResetBaseAddr, resetPinNum);
        DebugP_log("RESET released (HIGH)\r\n");
        ClockP_usleep(10000); // Wait 10ms for DAC to stabilize
        
        DebugP_log("DAC should now be ready\r\n");
    }

    Step 2: SPI Loopback Test

    Before testing with the DAC, verify your SPI driver is functioning:

    void spi_loopback_test(void)
    {
        DebugP_log("=== SPI Loopback Test ===\r\n");
        
        // Physically connect MOSI (HSEC 77) to MISO (HSEC 75) with a jumper wire
        
        uint8_t txbuffer[3] = {0xAA, 0x55, 0xF0};
        uint8_t rxbuffer[3] = {0, 0, 0};
        
        SPI_CS_High_Low(0);
        SPI_Transaction(txbuffer, 3, rxbuffer, 3);
        SPI_CS_High_Low(1);
        
        DebugP_log("TX: 0x%02X 0x%02X 0x%02X\r\n", txbuffer[0], txbuffer[1], txbuffer[2]);
        DebugP_log("RX: 0x%02X 0x%02X 0x%02X\r\n", rxbuffer[0], rxbuffer[1], rxbuffer[2]);
        
        if (rxbuffer[0] == 0xAA && rxbuffer[1] == 0x55 && rxbuffer[2] == 0xF0) {
            DebugP_log("SPI Loopback PASSED - SPI driver is working\r\n");
        } else {
            DebugP_log("SPI Loopback FAILED - Check SPI configuration\r\n");
        }
    }

    Step 3: Test DAC CLR Function

    Verify the DAC is powered and responsive:

    void test_dac_clr_function(void)
    {
        DebugP_log("=== Testing DAC CLR Function ===\r\n");
        
        uint32_t gpioClrBaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(GPIO_CLR_BASE_ADDR);
        uint32_t clrPinNum = GPIO_CLR_PIN;
        
        GPIO_setDirMode(gpioClrBaseAddr, clrPinNum, GPIO_CLR_DIR);
        
        GPIO_pinWriteHigh(gpioClrBaseAddr, clrPinNum);
        DebugP_log("CLR = HIGH, measure DAC outputs (should be at mid-scale or last value)\r\n");
        ClockP_usleep(1000000);
        
        GPIO_pinWriteLow(gpioClrBaseAddr, clrPinNum);
        DebugP_log("CLR = LOW, measure DAC outputs (should go to 0V or negative full scale)\r\n");
        ClockP_usleep(1000000);
        
        GPIO_pinWriteHigh(gpioClrBaseAddr, clrPinNum);
        DebugP_log("CLR = HIGH again\r\n");
    }

    Recommended Test Sequence

    Replace your init_dac81408() with this comprehensive test:

    void init_dac81408(void)
    {
        DebugP_log("\r\n========================================\r\n");
        DebugP_log("  DAC81408 Communication Test\r\n");
        DebugP_log("========================================\r\n");
        
        verify_dac_power_and_reset();
        
        // Uncomment after connecting MOSI to MISO with jumper wire
        // spi_loopback_test();
        
        test_dac_clr_function();
        
        DebugP_log("\r\n=== Attempting Device ID Read ===\r\n");
        uint16_t deviceId = SPI_Read_Frm_DAC(R_DEVICEID);
        
        if (deviceId == 0x0000 || deviceId == 0xFFFF) {
            DebugP_log("Device ID read failed: 0x%04X\r\n", deviceId);
            DebugP_log("Possible causes:\r\n");
            DebugP_log("1. MISO not connected or wrong pin\r\n");
            DebugP_log("2. DAC not powered\r\n");
            DebugP_log("3. SPI mode mismatch\r\n");
            DebugP_log("4. CS timing issue\r\n");
            return;
        }
        
        DebugP_log("Device ID: 0x%04X\r\n", deviceId);
        
        DebugP_log("\r\n=== Configuring DAC ===\r\n");
        DAC81408_Settings();
        Set_DAC_Range();
        
        float inVol = 18.6;
        DebugP_log("Setting output voltage: %.2f V\r\n", inVol);
        Set_InputVoltage_To_DAC(inVol);
        
        DebugP_log("\r\n=== DAC Initialization Complete ===\r\n");
    }


    Information Needed to Continue Debugging

    To help identify the exact issue, please provide:

    1. Loopback test result: Connect MOSI to MISO with a jumper wire and run spi_loopback_test(). Does it pass?

    2. Oscilloscope capture: Capture CS, SCLK, MOSI, and MISO during a Device ID read. The expected waveform should show:

      • Transaction 1: CS low, 24 clock pulses, MOSI shows 0x81 0x00 0x00, MISO high-Z
      • 10us delay
      • Transaction 2: CS low, 24 clock pulses, MOSI shows 0x00 0x00 0x00, MISO shows device ID
    3. Power supply measurements with multimeter:

      • DAC81408 Pin 5 (VDD): Should be 5V
      • DAC81408 Pin 11 (AVDD): Should be 5V
      • DAC81408 Pin 1 (IOVDD): Should be 3.3V or 5V
      • DAC81408 Pin 10 (RESET): Should be HIGH (3.3V or 5V)
      • DAC81408 Pin 9 (CLR): Should be HIGH (3.3V or 5V)
    4. SysConfig Pin Mux screenshot: Specifically the pin assignments showing SPI1_D0, SPI1_D1, and SPI1_CLK configurations

    5. MCSPI_transfer() return value: Add this logging to your SPI_Transaction function:

      DebugP_log("MCSPI_transfer returned: %d (SystemP_SUCCESS = %d)\r\n", transferOK, SystemP_SUCCESS);

    The consistent 0x0000 reading (not random garbage) suggests either MISO is stuck low or the DAC is not responding. Once you provide the above information, I can pinpoint the exact issue.

    Best Regards,
    Zackary Fleenor

  • Hi Fleenor,

    I am following up on the DAC81408 interfacing issue with the AM2634_CC EVM board. I have implemented all the fixes suggested , but I am still unable to read the Device ID, which returns 0x0000.

    Fixes Implemented:

    1.A single global SPI handle is now used, opened once in init_spi and reused for all transactions, eliminating repeated open and close operations.

    2.SPI Mode 1, with CPOL equal to 0 and CPHA equal to 1, has been configured in SysConfig.

    3.The corrected two-transaction SPI read protocol has been implemented. The read command is sent in the first transaction, and the data is retrieved in a second transaction with a 10 microsecond delay between them.

    4.Manual chip select control via GPIO is being used with the csDisable parameter set to TRUE.

    5.A proper reset sequence has been implemented with a 10 millisecond assertion time followed by a 10 millisecond stabilization delay.

    Write transactions have been changed to write-only operations, removing the unnecessary dummy read buffer.

    The return value of MCSPI_transfer is now logged for debugging purposes.

    Test Results:

    1. SPI Loopback Test passed. A jumper wire was connected between MOSI on HSEC pin 75 and MISO on HSEC pin 77. Data was sent and received correctly. This confirms that the AM2634 SPI pins and the driver are working properly.

    2. Oscilloscope measurements confirm that the SCLK, CS, and MOSI signals are present and match the expected waveforms during the SPI transactions.

    3. Power supply verification results are as follows. VDD at pin 5 of J7 measures 5.0V. IOVDD at pin 4 of J7 measures 3.3V. VSS at pin 7 of J7 measures 20V. The VDD supply at pin 6 of J7 measures -20V. The reference voltage, VREF, at pin 7 of J1 measures 2.5V.

    4. For the control pins, the RESET signal on HSEC pin 162 measures 3.3V after initialization, which is the correct HIGH state. The CLR signal on HSEC pin 161 also measures 3.3V, which is the correct HIGH state.

    5. The console log shows that the SPI handle initializes successfully. The power-on verification and the CLR function test both execute. During the Device ID read attempt, MCSPI_transfer returns SystemP_SUCCESS for both transactions, but the final result is still 0x0000, causing the read to fail.

    Observations and Question:

    The MCSPI_transfer function returns SystemP_SUCCESS for both read transactions, so there are no driver-level errors. The successful loopback test proves the AM2634 SPI interface is functional. All power rails and control pins have been verified to be at the correct voltage levels. Despite all these checks, the Device ID consistently reads as 0x0000.

    With the loopback test passing and all voltages verified, what should be the next debugging step. The DAC appears to be powered, and its control pins are at the correct levels, but it is not responding to any SPI commands. Could there be a specific timing requirement or initialization sequence that I might be missing. This is urgent for our project timeline.

    I have attached the updated code, the SysConfig settings, a screenshot of the console output, and oscilloscope captures of the waveforms for your review.

    Code:

    #include <kernel/dpl/ClockP.h>
    #include <kernel/dpl/DebugP.h>
    #include "ti_drivers_config.h"
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"
    #include <drivers/hw_include/tistdtypes.h>
    #include <stdlib.h>
    #include <string.h>
    #include "analog_dac.h"

    // Global SPI handle - opened once and reused (FIX #1)
    static MCSPI_Handle gSpiHandle = NULL;
    void Reset_Signal(void);
    void test_dac_clr_function(void);
    // Timing variables
    uint32_t startTimeInUSec, elapsedTimeInUsecs;

    // ============================================================================
    // SPI Initialization - Call this ONCE at startup
    // ============================================================================
    void init_spi(void)
    {
    MCSPI_OpenParams openParams;

    MCSPI_OpenParams_init(&openParams);
    // SPI Mode (CPOL=0, CPHA=1) must be configured in SysConfig

    gSpiHandle = MCSPI_open(CONFIG_MCSPI0, &openParams);
    if (gSpiHandle == NULL)
    {
    DebugP_log("Error: Unable to open SPI0 handle.\r\n");
    }
    else
    {
    DebugP_log("SPI0 initialized successfully.\r\n");
    }
    }

    // ============================================================================
    // Main DAC Function
    // ============================================================================
    void *dac81408_main(void *args)
    {
    Drivers_open();
    Board_driversOpen();

    init_spi(); // Open SPI handle ONCE
    Reset_Signal(); // Reset the DAC

    startTimeInUSec = ClockP_getTimeUsec();
    while(1)
    {
    init_dac81408(); // Initialize and configure DAC
    }
    elapsedTimeInUsecs = ClockP_getTimeUsec() - startTimeInUSec;
    DebugP_log("Total Time for Completion: %5.2f ms\r\n", (Float32)(elapsedTimeInUsecs / 1000.0));
    Board_driversClose();
    Drivers_close();

    return NULL;
    }

    // ============================================================================
    // DAC Initialization Sequence
    // ============================================================================1
    void init_dac81408(void)
    {
    DebugP_log("\r\n========================================\r\n");
    DebugP_log(" DAC81408 Communication Test\r\n");
    DebugP_log("========================================\r\n");

    Reset_Signal();

    // Uncomment after connecting MOSI to MISO with jumper wire
    spi_loopback_test();

    test_dac_clr_function();

    DebugP_log("\r\n=== Attempting Device ID Read ===\r\n");
    uint16_t deviceId = SPI_Read_Frm_DAC(R_DEVICEID);

    if (deviceId == 0x0000 || deviceId == 0xFFFF) {
    DebugP_log("Device ID read failed: 0x%04X\r\n", deviceId);
    DebugP_log("Possible causes:\r\n");
    DebugP_log("1. MISO not connected or wrong pin\r\n");
    DebugP_log("2. DAC not powered\r\n");
    DebugP_log("3. SPI mode mismatch\r\n");
    DebugP_log("4. CS timing issue\r\n");
    return;
    }

    DebugP_log("Device ID: 0x%04X\r\n", deviceId);

    DebugP_log("\r\n=== Configuring DAC ===\r\n");
    DAC81408_Settings();
    Set_DAC_Range();

    float inVol = 18.6;
    DebugP_log("Setting output voltage: %.2f V\r\n", inVol);
    Set_InputVoltage_To_DAC(inVol);

    DebugP_log("\r\n=== DAC Initialization Complete ===\r\n");
    }

    // ============================================================================
    // SPI Transaction - Low level transfer (FIX #2: No open/close, csDisable=TRUE)
    // ============================================================================
    void SPI_Transaction(uint8_t *txbuffer, size_t txSize, uint8_t *rxbuffer, size_t rxSize)
    {
    MCSPI_Transaction spiTransaction;
    int32_t transferOK;

    if (gSpiHandle == NULL)
    {
    DebugP_log("Error: SPI handle not initialized.\r\n");
    return;
    }

    MCSPI_Transaction_init(&spiTransaction);

    if (txSize > 0 && rxSize == 0) {
    // Write-only transaction
    spiTransaction.count = txSize;
    spiTransaction.txBuf = txbuffer;
    spiTransaction.rxBuf = NULL;
    } else if (txSize == 0 && rxSize > 0) {
    // Read-only transaction
    spiTransaction.count = rxSize;
    spiTransaction.txBuf = NULL;
    spiTransaction.rxBuf = rxbuffer;
    } else {
    // Full-duplex transaction
    spiTransaction.count = (txSize > rxSize) ? txSize : rxSize;
    spiTransaction.txBuf = txbuffer;
    spiTransaction.rxBuf = rxbuffer;
    }

    spiTransaction.csDisable = TRUE;

    transferOK = MCSPI_transfer(gSpiHandle, &spiTransaction);
    DebugP_log("MCSPI_transfer returned: %d (SystemP_SUCCESS = %d)\r\n", transferOK, SystemP_SUCCESS);

    if (transferOK != SystemP_SUCCESS)
    {
    DebugP_log("Error: SPI transfer failed with status: %d\r\n", transferOK);
    }
    }

    // ============================================================================
    // SPI Write to DAC - 24-bit frame: Address (8-bit) + Data (16-bit)
    // ============================================================================
    void SPI_Write_To_DAC(uint8_t reg, uint16_t wdata)
    {
    uint8_t txbuffer[3];
    uint8_t rxbuffer[3];

    txbuffer[0] = reg; // Register address (bits 23-16)
    txbuffer[1] = (uint8_t)(wdata >> 8); // Data MSB (bits 15-8)
    txbuffer[2] = (uint8_t)(wdata & 0xFF); // Data LSB (bits 7-0)

    SPI_CS_High_Low(0); // Assert CS (active low)
    SPI_Transaction(txbuffer, 3, rxbuffer, 3); // Send 3 bytes, receive 3 dummy bytes
    SPI_CS_High_Low(1); // De-assert CS

    ClockP_usleep(1); // Small delay between transactions
    }

    // ============================================================================
    // SPI Read from DAC - 24-bit frame: Read command (8-bit) + Dummy (16-bit)
    // ============================================================================
    uint16_t SPI_Read_Frm_DAC(uint8_t reg)
    {
    uint8_t txbuffer[3];
    uint8_t rxbuffer[3] = {0, 0, 0};
    uint16_t result;

    // Transaction 1: Send Read Command
    txbuffer[0] = 0x80 | reg;
    txbuffer[1] = 0x00;
    txbuffer[2] = 0x00;

    SPI_CS_High_Low(0);
    SPI_Transaction(txbuffer, 3, NULL, 0);
    SPI_CS_High_Low(1);

    ClockP_usleep(10); // Wait between transactions

    // Transaction 2: Retrieve Data
    txbuffer[0] = 0x00;
    txbuffer[1] = 0x00;
    txbuffer[2] = 0x00;

    SPI_CS_High_Low(0);
    SPI_Transaction(txbuffer, 3, rxbuffer, 3);
    SPI_CS_High_Low(1);

    result = ((rxbuffer[1] << 8) | rxbuffer[2]) & 0xFFFF;

    getRegName(reg);
    DebugP_log("[SPI_Read_Frm_DAC] res = 0x%04x\r\n", result);

    return result;
    }
    // ============================================================================
    // GPIO: Chip Select Control
    // ============================================================================
    void SPI_CS_High_Low(uint8_t val)
    {
    // val = 1 = HIGH (inactive), val = 0 = LOW (active)
    uint32_t gpioChipSelectBaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(GPIO_CS_OUT_BASE_ADDR);
    uint32_t ChipSelectPinNum = GPIO_CS_OUT_PIN;

    GPIO_setDirMode(gpioChipSelectBaseAddr, ChipSelectPinNum, GPIO_CS_OUT_DIR);

    if (val == 1)
    {
    GPIO_pinWriteHigh(gpioChipSelectBaseAddr, ChipSelectPinNum);
    }
    else
    {
    GPIO_pinWriteLow(gpioChipSelectBaseAddr, ChipSelectPinNum);
    }
    }

    void getRegName(uint8_t reg)
    {
    switch(reg)
    {
    case 0x01: DebugP_log(" [Device ID: "); break;
    case 0x02: DebugP_log(" [DAC Status: "); break;
    case 0x03: DebugP_log(" [SPI Configuration: "); break;
    case 0x04: DebugP_log(" [General Configuration: "); break;
    default: break;
    }
    }

    // ============================================================================
    // DAC Configuration Settings (FIX #3: Correct sequence and values)
    // ============================================================================
    void DAC81408_Settings(void)
    {
    // Step 1: Read Device ID to verify communication
    uint16_t deviceId = SPI_Read_Frm_DAC(R_DEVICEID);
    DebugP_log("Device ID read: 0x%04x (Expected: 0x1298)\r\n", deviceId);

    // Step 2: Configure SPICONFIG - Power up device
    // 0x0A04: FSDO=0 (SDO updates on rising edge), Power-up all blocks
    SPI_Write_To_DAC(R_SPICONFIG, 0x0A24);
    ClockP_usleep(100);
    SPI_Read_Frm_DAC(R_SPICONFIG);

    // Step 3: Configure GENCONFIG - Enable internal reference (CRITICAL!)
    // 0x3F00 enables internal 2.5V reference and configures outputs
    SPI_Write_To_DAC(R_GENCONFIG, 0x3F00);
    ClockP_usleep(100);
    SPI_Read_Frm_DAC(R_GENCONFIG);

    // Step 4: Power up all DAC channels (0x0000 = power up, 0xFFFF = power down)
    SPI_Write_To_DAC(R_DACPWDWN, 0x0000);
    ClockP_usleep(100);

    // Step 5: Configure broadcast
    SPI_Write_To_DAC(R_BRDCONFIG, 0xFFFF);
    SPI_Write_To_DAC(R_BRDCAST, 0xFFFF);
    }

    // ============================================================================
    // Set DAC Range Registers
    // ============================================================================
    void Set_DAC_Range(void)
    {
    // Single Ended Range: 0V to 40V for DAC4 to DAC7
    SPI_Write_To_DAC(R_DACRANGE0, U_40V_CH7 | U_40V_CH6 | U_40V_CH5 | U_40V_CH4);

    // Differential Range: -20V to +20V for DAC0 to DAC3
    SPI_Write_To_DAC(R_DACRANGE1, B_20V_CH3 | B_20V_CH2 | B_20V_CH1 | B_20V_CH0);
    }

    // ============================================================================
    // Code Value Calculation for Single Ended (0-40V range)
    // ============================================================================
    uint16_t CodeVal_UnipolarVoltage_FSR40(float vout)
    {
    uint16_t code = (uint16_t)((vout * RESOLUTION) / FSR_40);
    DebugP_log("Single Ended Code Value: %d (0x%04x)\r\n", code, code);
    return code;
    }

    // ============================================================================
    // Code Value Calculation for Differential (-20V to +20V range)
    // ============================================================================
    int16_t CodeVal_BipolarVoltage_FSR40(float vout)
    {
    int16_t code = (int16_t)((((vout + (FSR_40 / 2.0)) * RESOLUTION) / FSR_40));
    DebugP_log("Differential Code Value: %d (0x%04x)\r\n", code, (uint16_t)code);
    return code;
    }

    // ============================================================================
    // Set All Bipolar Channels (DAC0-DAC3)
    // ============================================================================
    void Set_Bipolar_DACOUTChannel(uint16_t dacVal)
    {
    SPI_Write_To_DAC(R_DAC0DATA, dacVal);
    SPI_Write_To_DAC(R_DAC1DATA, dacVal);
    SPI_Write_To_DAC(R_DAC2DATA, dacVal);
    SPI_Write_To_DAC(R_DAC3DATA, dacVal);
    }

    // ============================================================================
    // Set All Unipolar Channels (DAC4-DAC7)
    // ============================================================================
    void Set_Unipolar_DACOUTChannel(uint16_t dacVal)
    {
    SPI_Write_To_DAC(R_DAC4DATA, dacVal);
    SPI_Write_To_DAC(R_DAC5DATA, dacVal);
    SPI_Write_To_DAC(R_DAC6DATA, dacVal);
    SPI_Write_To_DAC(R_DAC7DATA, dacVal);
    }

    // ============================================================================
    // Set Output Voltage on All Channels
    // ============================================================================
    void Set_InputVoltage_To_DAC(float Vout)
    {
    uint16_t dacDataVoutdiff = (uint16_t)CodeVal_BipolarVoltage_FSR40(Vout);
    uint16_t dacDataVoutSin = CodeVal_UnipolarVoltage_FSR40(Vout);

    Set_Bipolar_DACOUTChannel(dacDataVoutdiff);
    ClockP_usleep(10);
    Set_Unipolar_DACOUTChannel(dacDataVoutSin);
    ClockP_usleep(10);
    }

    // ============================================================================
    // Set Single DAC Channel Output (Helper function)
    // ============================================================================
    void set_dac_output(uint8_t channel, uint16_t value)
    {
    uint8_t reg;

    switch(channel)
    {
    case 0: reg = R_DAC0DATA; break;
    case 1: reg = R_DAC1DATA; break;
    case 2: reg = R_DAC2DATA; break;
    case 3: reg = R_DAC3DATA; break;
    case 4: reg = R_DAC4DATA; break;
    case 5: reg = R_DAC5DATA; break;
    case 6: reg = R_DAC6DATA; break;
    case 7: reg = R_DAC7DATA; break;
    default: return;
    }

    SPI_Write_To_DAC(reg, value);
    }

    void Reset_Signal(void)
    {
    DebugP_log("=== DAC81408 Power-On Verification ===\r\n");

    // Check power supply pins with multimeter:
    // VDD (Pin 5): Should be 5V
    // AVDD (Pin 11): Should be 5V
    // IOVDD (Pin 1): Should be 3.3V or 5V
    // GND (Pin 6): Should be 0V

    uint32_t gpioResetBaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(GPIO_RESET_BASE_ADDR);
    uint32_t resetPinNum = GPIO_RESET_PIN;

    GPIO_setDirMode(gpioResetBaseAddr, resetPinNum, GPIO_RESET_DIR);

    GPIO_pinWriteLow(gpioResetBaseAddr, resetPinNum);
    DebugP_log("RESET asserted (LOW)\r\n");
    ClockP_usleep(10000); // Hold for 10ms

    GPIO_pinWriteHigh(gpioResetBaseAddr, resetPinNum);
    DebugP_log("RESET released (HIGH)\r\n");
    ClockP_usleep(10000); // Wait 10ms for DAC to stabilize

    DebugP_log("DAC should now be ready\r\n");
    }


    void test_dac_clr_function(void)
    {
    DebugP_log("=== Testing DAC CLR Function ===\r\n");

    uint32_t gpioClrBaseAddr = (uint32_t)AddrTranslateP_getLocalAddr(GPIO_CLR_BASE_ADDR);
    uint32_t clrPinNum = GPIO_CLR_PIN;

    GPIO_setDirMode(gpioClrBaseAddr, clrPinNum, GPIO_CLR_DIR);

    GPIO_pinWriteHigh(gpioClrBaseAddr, clrPinNum);
    DebugP_log("CLR = HIGH, measure DAC outputs (should be at mid-scale or last value)\r\n");
    ClockP_usleep(1000000);

    GPIO_pinWriteLow(gpioClrBaseAddr, clrPinNum);
    DebugP_log("CLR = LOW, measure DAC outputs (should go to 0V or negative full scale)\r\n");
    ClockP_usleep(1000000);

    GPIO_pinWriteHigh(gpioClrBaseAddr, clrPinNum);
    DebugP_log("CLR = HIGH again\r\n");
    }

    void spi_loopback_test(void)
    {
    DebugP_log("=== SPI Loopback Test ===\r\n");

    // Physically connect MOSI (HSEC 77) to MISO (HSEC 75) with a jumper wire

    uint8_t txbuffer[3] = {0xAA, 0x55, 0xF0};
    uint8_t rxbuffer[3] = {0, 0, 0};

    SPI_CS_High_Low(0);
    SPI_Transaction(txbuffer, 3, rxbuffer, 3);
    SPI_CS_High_Low(1);

    DebugP_log("TX: 0x%02X 0x%02X 0x%02X\r\n", txbuffer[0], txbuffer[1], txbuffer[2]);
    DebugP_log("RX: 0x%02X 0x%02X 0x%02X\r\n", rxbuffer[0], rxbuffer[1], rxbuffer[2]);

    if (rxbuffer[0] == 0xAA && rxbuffer[1] == 0x55 && rxbuffer[2] == 0xF0) {
    DebugP_log("SPI Loopback PASSED - SPI driver is working\r\n");
    } else {
    DebugP_log("SPI Loopback FAILED - Check SPI configuration\r\n");
    }
    }

    Output:

    [Cortex_R5_0] SPI1 initialized successfully.
    === DAC81408 Power-On Verification ===
    RESET asserted (LOW)
    RESET released (HIGH)
    DAC should now be ready

    ========================================
    DAC81408 Communication Test
    ========================================
    === DAC81408 Power-On Verification ===
    RESET asserted (LOW)
    RESET released (HIGH)
    DAC should now be ready
    === SPI Loopback Test ===
    MCSPI_transfer returned: 0 (SystemP_SUCCESS = 0)
    TX: 0xAA 0x55 0xF0
    RX: 0xAA 0x55 0xF0
    SPI Loopback PASSED - SPI driver is working
    === Testing DAC CLR Function ===
    CLR = HIGH, measure DAC outputs (should be at mid-scale or last value)
    CLR = LOW, measure DAC outputs (should go to 0V or negative full scale)
    CLR = HIGH again

    === Attempting Device ID Read ===
    MCSPI_transfer returned: 0 (SystemP_SUCCESS = 0)
    MCSPI_transfer returned: 0 (SystemP_SUCCESS = 0)
    [Device ID: [SPI_Read_Frm_DAC] res = 0x0000
    Device ID read failed: 0x0000
    Possible causes:
    1. MISO not connected or wrong pin
    2. DAC not powered
    3. SPI mode mismatch
    4. CS timing issue
    Total Time for Completion: 2091.57 ms

    Sysconfig :

    Snapshots of output:

    1.Clock and Data line                                                             2. Clock and CS

    Thanks for your continued support.

    Regards,
    Swarna

  • Hi Swarna,

    Thank you for the detailed follow-up. Your debugging has done an excellent job isolating the problem. To summarize what you have confirmed so far:

    • SPI driver is functional (loopback passed)
    • Power rails are verified correct
    • RESET and CLR pins are at correct levels
    • MCSPI_transfer returns SystemP_SUCCESS on every call
    • Device ID consistently returns 0x0000

    This specific combination — driver succeeds, signals are present on the scope, but read data is always zero — points to a physical layer issue between the AM2634 and the DAC81408, not a software problem. I have identified three issues that need to be addressed.


    Issue 1: POCI and PICO Are Swapped (Most Likely Root Cause)

    Your current wiring is:

    SPI1_D0 (HSEC Pin 75) → J8 Pin 3
    SPI1_D1 (HSEC Pin 77) → J8 Pin 4

    On the AM2634, D0 is POCI (Peripheral Out Controller In) and D1 is PICO (Peripheral In Controller Out). On the DAC81408 EVM, J8 Pin 3 is SDI (Serial Data In to the DAC) and J8 Pin 4 is SDO (Serial Data Out from the DAC). This means you are currently driving the DAC's data output pin with PICO, and your POCI is connected to the DAC's data input pin. The DAC is never receiving valid commands, and the AM2634 is never seeing the DAC's response.

    The correct wiring should be:

    AM2634 DAC81408 EVM (J8)
    SPI1_D1 / PICO (HSEC Pin 77) -> Pin 3 (SDI - data into DAC)
    SPI1_D0 / POCI (HSEC Pin 75) -> Pin 4 (SDO - data out of DAC)
    SPI1_CLK (HSEC Pin 91) -> Pin 8 (SCLK)
    GPIO CS (HSEC Pin 161) -> Pin 2 (CS)

    This also explains why your loopback test passed. With PICO connected to POCI via jumper wire, the loopback is independent of the DAC wiring and will pass regardless of how the DAC pins are connected.


    Issue 2: PICO Signal Amplitude Is Too Low

    Your oscilloscope capture of the clock and data lines shows Ch1 set to 100mV per division, and the data line amplitude appears to be in the range of 100 to 200mV. The DAC81408 requires a logic high of at least 0.7 times IOVDD on the SDI pin. With IOVDD at 3.3V, the minimum valid logic high is 2.31V. A 100 to 200mV signal will not be recognized as a valid input by the DAC under any circumstances.

    Please verify the following in SysConfig. Confirm that the SPI pin assigned as D1 (PICO) is correctly muxed as an SPI function output and not left in GPIO or default mode. Confirm the slew rate and drive strength settings for that pin are appropriate for SPI output. Also verify in the AM2634_CC EVM schematic that SPI0 ball pins A11, C10, and B11 actually route to HSEC pins 91, 75, and 77 respectively. If the ball-to-HSEC mapping is incorrect, your signals may be appearing on the wrong physical pins entirely.


    Issue 3: SPI Instance Mismatch Between Iterations

    Your most recent code opens CONFIG_MCSPI0, but your hardware is connected to the HSEC pins associated with SPI1 in your original configuration. Confirm that the SysConfig instance you have configured (showing SPI0_CLK/A11, SPI0_D0/C10, SPI0_D1/B11) physically routes to the HSEC pins where your DAC is connected. If there is any mismatch here, the correct signals will never reach the DAC regardless of software correctness.


    Recommended Next Steps

    First, correct the POCI and PICO wiring as described above. Second, measure the PICO pin voltage directly at the HSEC connector with the SPI actively transmitting and confirm it reaches at least 2.31V logic high. Third, verify the SysConfig pin assignments map correctly to your physical HSEC connections using the AM2634_CC EVM schematic. Fourth, after correcting the wiring, attempt the Device ID read again. The expected return value is 0x1298 for the DAC81408. If you receive that value, communication is established and you can proceed with the full initialization sequence.

    Please let me know the result after swapping the POCI and PICO connections, as that is the most likely cause of the issue.

    Best Regards,
    Zackary Fleenor

  • Hi Fleenor,

    Thank you for the continued support, i have made progress on SPI wiring correction. I have implemented it.

    I am now blocked by a debugger/GEL issue before I can test the DAC. Please advise.

    Problem 1: GEL Expression Popup

    - Every time I launch debug, a popup appears: `"GEL Expression: OnTargetConnect()"`
    - Options: `"Run in Background"` or `"Cancel"`
    - This happens repeatedly and blocks the debug session

    Problem 2: Memory Write Error

    - After clicking "Run in Background", I get: `"Error -1065: Unable to access device memory at 0x0"`
    - The program fails to load

    What I have tried already

    - Changed `.cmd` file: `R5F_VECS` from `0x00` to `0x00020000`.
    - Clean and rebuild after change.
    - Tried loading to different core (Cortex_R5_2).
    - Looked for "Ignore memory errors" option in Preferences but could not find it.

    Please guide me on the next steps.

    Thank you,
    Swarna

  • Hi Swarna,

    Thank you for the update. I'm glad to hear you've made progress on the SPI wiring correction. Let's resolve these debugger issues so you can test the DAC communication.

    Your symptoms indicate GEL file initialization problems combined with incorrect memory configuration. Both issues are related and can be resolved systematically.


    Solution to Problem 1: GEL Expression Popup

    The OnTargetConnect() popup is normal behavior when connecting to AM263x targets. The GEL file runs initialization scripts that configure device clocks, enable peripheral clocks, and unlock control registers automatically.

    Recommended Approach:

    Click "Run in Background" when the popup appears. This allows the GEL script to execute while you continue with the debug session. This is expected behavior and should not be suppressed.

    If the popup is blocking repeatedly, check your CCS Debug configuration:

    • Go to Window → Preferences → Code Composer Studio → Debug
    • Verify GEL-related timeout settings
    • Ensure "Auto Run and Launch Options" are properly configured


    Solution to Problem 2: Memory Write Error at 0x0

    The "Error -1065: Unable to access device memory at 0x0" indicates your linker script is trying to place code at an invalid or protected memory address.

    Root Cause:

    Your .cmd file change from 0x00 to 0x00020000 was an incorrect approach. Address 0x0 is a valid memory location on AM263x R5F cores. The error occurs because the GEL file or debugger is trying to access memory before proper initialization, or your memory map is incorrectly configured.

    Correct Memory Configuration for AM263x:

    Valid memory regions for AM263x R5F cores are:

    Memory Region
    Start Address
    Size
    Purpose
    TCMA (R5F)
    0x00000000
    32 KB
    Tightly Coupled Memory A
    TCMB (R5F)
    0x00080000
    32 KB
    Tightly Coupled Memory B
    MSRAM
    0x70000000
    Variable
    Main Shared RAM
    Flash (QSPI)
    0x60000000
    Variable
    External Flash

    Action Required:

    Revert your linker command file (.cmd) to the original SDK configuration. Your vector table should be placed at 0x00000000 in TCMA. The typical configuration should look like this:

    MEMORY
    {
        R5F_VECS  : ORIGIN = 0x00000000 , LENGTH = 0x00000040
        R5F_TCMA  : ORIGIN = 0x00000040 , LENGTH = 0x00007FC0
        R5F_TCMB  : ORIGIN = 0x00080000 , LENGTH = 0x00008000
        MSRAM     : ORIGIN = 0x70000000 , LENGTH = 0x00040000
    }
    
    SECTIONS
    {
        .vectors : ALIGN (8) {} > R5F_VECS
        .text    : ALIGN (8) {} > MSRAM
        .data    : ALIGN (8) {} > MSRAM
        .bss     : ALIGN (8) {} > MSRAM
        .stack   : ALIGN (8) {} > MSRAM
    }


    Step-by-Step Debug Procedure

    Step 1: Verify GEL File Configuration

    1. Right-click your .ccxml file → Show all cores
    2. Select MAIN_Cortex_R5_0_0
    3. Right-click → Open GEL Files View
    4. Verify the path shows: {CCS_install}/ccs_base/emulation/gel/AM263x/AM263x.gel
    5. If missing, manually load it from that location

    Step 2: Verify Correct Core Selection

    For AM2634, valid cores are:

    • Single Core: MAIN_Cortex_R5_0_0
    • Dual Lockstep: MAIN_Cortex_R5_0_0 (lockstep)
    • Dual Core: MAIN_Cortex_R5_0_0 or MAIN_Cortex_R5_0_1

    Ensure you are connecting to the correct core in your debug configuration.

    Step 3: Clean and Reconfigure

    1. Revert your .cmd file to use 0x00000000 for R5F_VECS
    2. Project → Clean Project
    3. Delete the "Debug" folder manually
    4. Right-click .syscfg → Generate Configuration Files
    5. Project → Build Project

    Step 4: Correct Debug Configuration

    1. Open your .ccxml file
    2. Under Advanced tab → Select MAIN_Cortex_R5_0_0
    3. Verify Initialization Script field points to the AM263x GEL file
    4. Set JTAG TCLK Frequency to Fixed 5.5 MHz
    5. Save the configuration

    Step 5: Debug Launch Sequence

    1. Target → Launch Selected Configuration
    2. When GEL popup appears: Click "Run in Background"
    3. Wait for console to show: "GEL Output: Initialization complete"
    4. Run → Load → Load Program
    5. Select your .out file from the Debug folder


    Alternative Solution: Use SDK Example as Template

    If the above steps do not resolve the issue, I recommend using a working SDK example as a baseline:

    1. Import the SDK MCSPI example: CCS → Import → C/C++ → CCS Projects
    2. Browse to SDK: {SDK}/examples/drivers/mcspi/mcspi_loopback
    3. Import for AM263x
    4. Verify this example loads and runs successfully
    5. Copy your DAC initialization code into this working example
    6. This ensures correct linker, GEL, and debug configuration


    Verification After Fixes

    Once you resolve the debugger issues and successfully load your program:

    1. Verify the corrected wiring from my previous message:

      • PICO (HSEC Pin 77) → DAC J8 Pin 3 (SDI)
      • POCI (HSEC Pin 75) → DAC J8 Pin 4 (SDO)
      • CLK (HSEC Pin 91) → DAC J8 Pin 8 (SCLK)
      • CS (HSEC Pin 161) → DAC J8 Pin 2 (CS)
    2. Measure PICO voltage at HSEC Pin 77 during transmission - should be 3.3V logic high, not 100-200mV

    3. Attempt the DAC81408 Device ID read - expected value is 0x1298

    4. If you still read 0x0000:

      • Verify chip select timing and clock polarity
      • Check SysConfig pin mux for SPI0_D1 (PICO) output configuration
      • Verify slew rate and drive strength settings


    Summary of Required Actions

    1. Revert your .cmd file to place R5F_VECS at 0x00000000
    2. Verify GEL file is properly configured in your .ccxml
    3. Clean and rebuild your project completely
    4. Follow the debug launch sequence above
    5. After successful load, test DAC communication with corrected wiring

    Please report back with the following information:

    • Does the memory error at 0x0 resolve after reverting the linker script?
    • Does the GEL initialization complete successfully?
    • What Device ID do you read from the DAC after the wiring corrections?

    Best Regards,
    Zackary Fleenor