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.

BQ79616: BQ daisy chain

Part Number: MSP430FR5994
Other Parts Discussed in Thread: BQ79616, MSP430FR5962, HALCOGEN, CODECOMPOSER

I tested a daisy chain of 3 custom BQ79616 MBBs connected to BQ79600 and MSP430 (SPI interface on custom PCB). One of the MBBs (device 2 in the middle of the daisy chain) has a damaged COMH interface from past ESD testing. When the stack of MBBs is connected to the BQ GUI ,the correct number of functioning stack devices is detected and the auto address sequence completes. The MSP430 firmware however, completes auto addressing only when the correctly functioning number of boards is provided. If the TOTALBOARDS includes the MBB with a damaged COMH interface, the MISO line has no activity, stays at 0xff. I am not aware of any missing register setup in the BQ79616. What can I do to troubleshoot this further-- I don’t have jumpers soldered to the COML lines of the MBBs.

Wakeup appears to complete correctly when the stack includes the MBB with damaged COMH interface. SPI_RDY goes active HIGH and then auto address is not proceeding.

Attached is the screenshot when auto address completes successfully with TOTALBOARDS set to 3 (2 fully working MBBs).

  • Hi Priya,

    The MCU software is designed only to function correctly when proper TOTALBOARDs variable is given based on what is connected. So this is expected behavior.

    Regards,

    Taylor

  • Taylor,

    If there is a damaged BQ79616 in the daisy chain, the auto address sequence should be able to report the correct number of functioning MBBs (79616) to the BMS. This way the tech knows which MBB in the stack to check and replace first. Eg., if MBB 3 in a daisy chain of 10 is not working, autoaddress should detect a stack of 3 working MBBs, though TOTALBOARDS including the BRIDGEDEVICE is 11. The BQ GUI is able to do this and the firmware should also do this. I will get the MBBs with jumpers soldered and I will look into the signals in two weeks. Let me know if I am missing something.

    Priya

  • I had the same issue with 20x BQ79616 devices connected to BQ79600 (using SPI)

    It required several changes in the "spi.c" -> e.g. spiTransmitAndReceiveData

            while(((spi->FLG & 0x00000100U) != 0x00000100U) && avoidEndlessLoop < 50000) // 500ms
            {
                avoidEndlessLoop++;
                delayus(10);
            } /* Wait */
    
            if(avoidEndlessLoop >= 50000) break;

    our solution to this problem is to address 20,19,18,... until we have a valid set of devices;
    ((changing the 'TOTALBOARDS' each time))
    switch to southbridge and start addressing again: 20-(valid), 20-(valid)-1, ... until we have a valid set on the other side

    you can condense down the result into a single broken wire (or a MBB or several)

    If there is an easier way, I would love to hear about it :-)

    Best regards,
    Collin

  • Collin,

    Thank you for your reply. I did try repeating the auto address sequence if it did not succeed the first time. It does not seem to make a difference in the MISO values. I have one define called MAXBOARDS that is used to allocate arrays that hold BQ response frames. TOTALBOARDS is a uint8_t variable that I decrement when autoaddress does not complete as expected. spiCommands.c uses TOTALBOARDS to calculate the length of the response bytes.  I don't however have any checks for endless loops. What MCU are you using in your project? We use the MSP430FR5962. MISO is always 0xff if I set MAXBOARDS to 4; but the actual number of working boards is only 3. 

    Auto address does complete if MAXBOARDS and TOTALBOARDS are both set to 3. I can use pointers on how else to track down where the problem is happening. 

    #define Bridge_DEV_CONF1_Response      0x14
    //Auto_addr response value
    extern uint8_t TOTALBOARDS;
    
    uint16_t autoaddr_response_frame[(1+6)*MAXBOARDS];
    
    uint8_t currentBoard;
    uint16_t bq79600Addr = 0;
    
    
    void SpiWake79600(void)
    {
        BQSPI_CS_REG  &= ~BQSPI_CS_PIN;
        delay_us(2);
        BQSPI_MOSI_REG &= ~BQSPI_MOSI_PIN;
        delay_ms(2.75);                                          // WAKE ping = 2.8ms
        BQSPI_MOSI_REG = BQSPI_MOSI_PIN;
        delay_us(2);
        BQSPI_MOSI_REG = BQSPI_MOSI_PIN;
        BQSPI_CS_REG  = BQSPI_CS_PIN;
    
        BQ_PERIPH_MOD_FUNC_SELECT |= (BQSPI_MOSI_PIN | BQSPI_MISO_PIN | BQSPI_CLK);
    
    }
    
    
    
    void SpiAutoAddress(void)
    {
        //DUMMY WRITE TO SNCHRONIZE ALL DAISY CHAIN DEVICES DLL (IF A DEVICE RESET OCCURED PRIOR TO THIS)
        SpiWriteReg(0, OTP_ECC_DATAIN1, 0X00, 1, FRMWRT_STK_W);
        SpiWriteReg(0, OTP_ECC_DATAIN2, 0X00, 1, FRMWRT_STK_W);
        SpiWriteReg(0, OTP_ECC_DATAIN3, 0X00, 1, FRMWRT_STK_W);
        SpiWriteReg(0, OTP_ECC_DATAIN4, 0X00, 1, FRMWRT_STK_W);
        SpiWriteReg(0, OTP_ECC_DATAIN5, 0X00, 1, FRMWRT_STK_W);
        SpiWriteReg(0, OTP_ECC_DATAIN6, 0X00, 1, FRMWRT_STK_W);
        SpiWriteReg(0, OTP_ECC_DATAIN7, 0X00, 1, FRMWRT_STK_W);
        SpiWriteReg(0, OTP_ECC_DATAIN8, 0X00, 1, FRMWRT_STK_W);
    
        //ENABLE AUTO ADDRESSING MODE
        SpiWriteReg(0, CONTROL1, 0X01, 1, FRMWRT_ALL_W);
    
        //SET ADDRESSES FOR EVERY BOARD
        for(currentBoard=0; currentBoard<TOTALBOARDS; currentBoard++)
        {
            SpiWriteReg(0, DIR0_ADDR, currentBoard, 1, FRMWRT_ALL_W);
        }
        //BROADCAST WRITE TO SET ALL DEVICES AS STACK DEVICE
        SpiWriteReg(0, COMM_CTRL, 0x02, 1, FRMWRT_ALL_W);
    
        //SET THE HIGHEST DEVICE IN THE STACK AS BOTH STACK AND TOP OF STACK
        SpiWriteReg(TOTALBOARDS-1, COMM_CTRL, 0x03, 1, FRMWRT_SGL_W);
    
        //SYNCRHONIZE THE DLL WITH A THROW-AWAY READ
        SpiReadReg(0, OTP_ECC_DATAIN1, autoaddr_response_frame, 1, FRMWRT_STK_R);
        SpiReadReg(0, OTP_ECC_DATAIN2, autoaddr_response_frame, 1, FRMWRT_STK_R);
        SpiReadReg(0, OTP_ECC_DATAIN3, autoaddr_response_frame, 1, FRMWRT_STK_R);
        SpiReadReg(0, OTP_ECC_DATAIN4, autoaddr_response_frame, 1, FRMWRT_STK_R);
        SpiReadReg(0, OTP_ECC_DATAIN5, autoaddr_response_frame, 1, FRMWRT_STK_R);
        SpiReadReg(0, OTP_ECC_DATAIN6, autoaddr_response_frame, 1, FRMWRT_STK_R);
        SpiReadReg(0, OTP_ECC_DATAIN7, autoaddr_response_frame, 1, FRMWRT_STK_R);
        SpiReadReg(0, OTP_ECC_DATAIN8, autoaddr_response_frame, 1, FRMWRT_STK_R);
    
        //OPTIONAL: read back all device addresses
        for(currentBoard=0; currentBoard<TOTALBOARDS; currentBoard++)
        {
            SpiReadReg(currentBoard, DIR0_ADDR, autoaddr_response_frame, 1, FRMWRT_SGL_R);
        }
    
        //OPTIONAL: read register address 0x2001 and verify that the value is 0x14
        SpiReadReg(0, Bridge_DEV_CONF1, autoaddr_response_frame, 1, FRMWRT_SGL_R);
        bq79600Addr = autoaddr_response_frame[4];
    
       return;
    }
    
    
    
    void SpiReadyComm(void)
    {
    
        while (bq79600Addr != 0x14){
    
            SpiWake79600();                                           //wake up BQ79600
            delay_ms(3.5);
    
            SpiWriteReg(0, CONTROL1, 0x20, 1, FRMWRT_SGL_W);                     //wake up BQ79616
            delay_ms(11.6*MAXBOARDS);
    
            SpiAutoAddress();                                         //start auto address for BQ79600 and BQ79616
            if (bq79600Addr != 0x14)
               TOTALBOARDS--;
        }
    
    
    /*
     * spiCommands.c
     *
     *  Created on: Mar 3, 2022
     *      Author: Priya.Nadathur
     */
    #include <driverlib.h>
    #include <string.h>
    #include "bspFuncs.h"
    #include "mbbConfig.h"
    #include "timer.h"
    
    #ifdef BQ_SPI
    #include "spiCommands.h"
    
    extern uint8_t TOTALBOARDS;
    //SpiWriteReg
    int bRes_W = 0;
    uint16_t spiBuf[8];
    uint16_t spiFrame[64];
    int spiPktLen = 0;
    uint16_t * spiPBuf = spiFrame;
    uint16_t spiWCRC;
    //SpiReadReg
    int bRes_R = 0;
    uint16_t spiReturn = 0;
    unsigned char dummy=0xFF;
    
    
    uint8_t ReceiveIndex = 0;
    uint8_t TransmitIndex = 0;
    
    /******************************************************************************
     * *********************** internal Variables**********************************
    ******************************************************************************/
    /*****************************SPI_B1_BQ79600**********************************/
    // CRC16 TABLE ---ITU_T polynomial: x^16 + x^15 + x^2 + 1
    const uint16_t crc16_table[256] = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301,
            0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1,
            0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81,
            0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
            0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00,
            0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1,
            0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380,
            0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141,
            0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501,
            0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0,
            0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881,
            0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
            0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401,
            0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1,
            0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180,
            0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740,
            0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01,
            0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1,
            0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80,
            0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
            0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200,
            0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1,
            0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780,
            0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41,
            0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901,
            0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1,
            0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80,
            0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
            0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 };
    
    /*******************************************************************************
      SpiCRC16 ********************************************************************
     *******************************************************************************
    * pBuf:    data
    * nLen:    length of data
    * ******************************************************************************
    * Function: Calculation the CRC
    ********************************************************************************/
    uint32_t SpiCRC16(uint16_t *pBuf, int nLen)
    {
        uint32_t wCRC = 0xFFFF;
        int i;
    
        for (i = 0; i < nLen; i++) {
            wCRC ^= (uint16_t)(*pBuf++) & 0x00FF;
            wCRC = crc16_table[wCRC & 0x00FF] ^ (wCRC >> 8);
        }
    
        return wCRC;
    }
    
    
    void SPI_Init()
    {
          BQSPI_CTLW0 = UCSWRST;                                 // **Put state machine in reset**
          BQSPI_CTLW0 |=  UCCKPH | UCCKPL_0 | UCMSB | UCSYNC
                      | UCMST | UCSSEL__SMCLK;                 // 3-pin, 8-bit MAB SPI master SMCLK=4M
          BQSPI_BRCREG = 2;                                      //UCB1CLK=2MHz
          BQSPI_CTLW0 &= ~UCSWRST;                               // **Initialize USCI state machine**
          BQSPI_IE |= UCRXIE;                                    // Enable USCI0 RX interrupt
    
    }
    
    #pragma vector=BQSPI_VECTOR
    
    __interrupt void BQSPI_ISR(void)
    {
        switch(__even_in_range(BQSPI_IV, USCI_SPI_UCTXIFG))
        {
            case USCI_NONE: break;
            case USCI_SPI_UCRXIFG:
                BQSPI_IFG &= ~UCRXIFG;
                __bic_SR_register_on_exit(LPM0_bits);        // Wake up to setup next TX
                break;
            case USCI_SPI_UCTXIFG:
                BQSPI_IE &= ~UCTXIE;
                break;
            default: break;
        }
    }
    
    /*******************************************************************************
      SpiWriteReg ******************************************************************
     *******************************************************************************
    * bID:          device id
    * wAddr:        register address
    * dwData:       data need to write
    * bLen:         length of data.
    * bWriteType:   command type
    * ******************************************************************************
    * Function: SPI write data to BQ79600 and BQ79616
    ********************************************************************************/
    int SpiWriteReg(uint16_t bID, uint16_t wAddr, uint64_t dwData, uint16_t bLen, uint8_t  bWriteType)
    {
        bRes_W=0;
        memset(spiBuf,0,sizeof(spiBuf));
        while(BQSPI_RDY_PORT & BQSPI_RDY == 0) delay_ms(0.025);
    
        switch (bLen)
       {
            case 1:
                spiBuf[0] = dwData & 0x00000000000000FF;
                bRes_W = SpiWriteFrame(bID, wAddr, spiBuf, 1, bWriteType);
                break;
            case 2:
                spiBuf[0] = (dwData & 0x000000000000FF00) >> 8;
                spiBuf[1] = dwData & 0x00000000000000FF;
                bRes_W = SpiWriteFrame(bID, wAddr, spiBuf, 2, bWriteType);
                break;
            case 3:
                spiBuf[0] = (dwData & 0x0000000000FF0000) >> 16;
                spiBuf[1] = (dwData & 0x000000000000FF00) >> 8;
                spiBuf[2] = dwData & 0x00000000000000FF;
                bRes_W = SpiWriteFrame(bID, wAddr, spiBuf, 3, bWriteType);
                break;
            case 4:
                spiBuf[0] = (dwData & 0x00000000FF000000) >> 24;
                spiBuf[1] = (dwData & 0x0000000000FF0000) >> 16;
                spiBuf[2] = (dwData & 0x000000000000FF00) >> 8;
                spiBuf[3] = dwData & 0x00000000000000FF;
                bRes_W = SpiWriteFrame(bID, wAddr, spiBuf, 4, bWriteType);
                break;
            case 5:
                spiBuf[0] = (dwData & 0x000000FF00000000) >> 32;
                spiBuf[1] = (dwData & 0x00000000FF000000) >> 24;
                spiBuf[2] = (dwData & 0x0000000000FF0000) >> 16;
                spiBuf[3] = (dwData & 0x000000000000FF00) >> 8;
                spiBuf[4] = dwData & 0x00000000000000FF;
                bRes_W = SpiWriteFrame(bID, wAddr, spiBuf, 5, bWriteType);
                break;
            case 6:
                spiBuf[0] = (dwData & 0x0000FF0000000000) >> 40;
                spiBuf[1] = (dwData & 0x000000FF00000000) >> 32;
                spiBuf[2] = (dwData & 0x00000000FF000000) >> 24;
                spiBuf[3] = (dwData & 0x0000000000FF0000) >> 16;
                spiBuf[4] = (dwData & 0x000000000000FF00) >> 8;
                spiBuf[5] = dwData & 0x00000000000000FF;
                bRes_W = SpiWriteFrame(bID, wAddr, spiBuf, 6, bWriteType);
                break;
            case 7:
                spiBuf[0] = (dwData & 0x00FF000000000000) >> 48;
                spiBuf[1] = (dwData & 0x0000FF0000000000) >> 40;
                spiBuf[2] = (dwData & 0x000000FF00000000) >> 32;
                spiBuf[3] = (dwData & 0x00000000FF000000) >> 24;
                spiBuf[4] = (dwData & 0x0000000000FF0000) >> 16;
                spiBuf[5] = (dwData & 0x000000000000FF00) >> 8;
                spiBuf[6] = dwData & 0x00000000000000FF;
                bRes_W = SpiWriteFrame(bID, wAddr, spiBuf, 7, bWriteType);
                break;
            case 8:
                spiBuf[0] = (dwData & 0xFF00000000000000) >> 56;
                spiBuf[1] = (dwData & 0x00FF000000000000) >> 48;
                spiBuf[2] = (dwData & 0x0000FF0000000000) >> 40;
                spiBuf[3] = (dwData & 0x000000FF00000000) >> 32;
                spiBuf[4] = (dwData & 0x00000000FF000000) >> 24;
                spiBuf[5] = (dwData & 0x0000000000FF0000) >> 16;
                spiBuf[6] = (dwData & 0x000000000000FF00) >> 8;
                spiBuf[7] = dwData & 0x00000000000000FF;
                bRes_W = SpiWriteFrame(bID, wAddr, spiBuf, 8, bWriteType);
                break;
            default:
                break;
        }
        return bRes_W;
    }
    /*******************************************************************************
      SpiWriteFrame ****************************************************************
     *******************************************************************************
    * bID:          device id
    * wAddr:        register address
    * pData:        data need to write
    * bLen:         length of data.
    * bWriteType:   command type
    * ******************************************************************************
    * Function: SPI write frame data
    ********************************************************************************/
    int SpiWriteFrame(uint16_t bID, uint16_t wAddr, uint16_t * pData, uint16_t bLen, uint8_t bWriteType)
    {
            int spiPktLen = 0;
            spiPBuf = spiFrame;
            memset(spiFrame, 0x7F, sizeof(spiFrame));
            *spiPBuf++ = 0x80 | (bWriteType) | ((bWriteType & 0x10) ? bLen - 0x01 : 0x00);   //Only include blen if it is a write; Writes are 0x90, 0xB0, 0xD0
            if (bWriteType == FRMWRT_SGL_R || bWriteType == FRMWRT_SGL_W)
            {
                *spiPBuf++ = (bID & 0x00FF);
            }
            *spiPBuf++ = (wAddr & 0xFF00) >> 8;
            *spiPBuf++ = wAddr & 0x00FF;
    
            while (bLen--)
                *spiPBuf++ = *pData++;
    
            spiPktLen = spiPBuf - spiFrame;
    
            spiWCRC = SpiCRC16(spiFrame, spiPktLen);
            *spiPBuf++ = spiWCRC & 0x00FF;
            *spiPBuf++ = (spiWCRC & 0xFF00) >> 8;
            spiPktLen += 2;
    
            spiTransmitData(spiPktLen);
    
            return spiPktLen;
    }
    
    
    void spiTransmitData(uint32_t blocksize)
    {
        TransmitIndex=0;
    
        BQSPI_CS_REG  = ~BQSPI_CS_PIN ;
        while(blocksize != 0U)
        {
            BQSPI_TXBUF=spiFrame[TransmitIndex];
            while(BQSPI_BUSY);
            dummy=BQSPI_RXBUF;
            TransmitIndex++;
            blocksize--;
        }
        BQSPI_CS_REG  = BQSPI_CS_PIN;
    
        return;
    }
    /*******************************************************************************
      SpiReadReg *******************************************************************
     *******************************************************************************
    * bID:          device id
    * wAddr:        register address
    * pData:        data need to read
    * bLen:         length of data.
    * bWriteType:   command type
    * ******************************************************************************
    * Function: SPI read data
    ********************************************************************************/
    int SpiReadReg(uint16_t bID, uint16_t wAddr, uint16_t * pData, uint16_t bLen,uint16_t bWriteType)
    {
        static int M = 0, i;                                                //expected total response bytes
        static int K = 0;
        bRes_R = 0;
    
        while(BQSPI_RDY_PORT & BQSPI_RDY == 0) delay_ms(0.055);
        spiReturn = bLen - 1;
    
        SpiWriteFrame(bID, wAddr, &spiReturn, 1, bWriteType);  //send the read request command frame
        delay_ms(0.6);
    
        uint16_t * movingPointer = pData;
    
        //prepare the correct number of bytes for the device to read
        if (bWriteType == FRMWRT_SGL_R)
        {
            M = bLen + 6;
        }
        else if (bWriteType == FRMWRT_STK_R)
        {
            M = (bLen + 6) * (TOTALBOARDS - 1);
        }
        else if (bWriteType == FRMWRT_ALL_R)
        {
            M = (bLen + 6) * TOTALBOARDS;
        }
        else
        {
            while(1);
        }
    
        //prepare the number of loops of 128-byte reads that need to occur
        i = (int)(M/128);
        //prepare the remainder that is left over after the last full 128-byte read
        K = M - i*128;
    
        //loop until we've read all data bytes
        while(i>(-1))
        {
            while(BQSPI_RDY_PORT & BQSPI_RDY == 0) delay_ms(0.055);
            //if there is more than 128 bytes remaining
            if(i>0)
            {
                if (bWriteType == FRMWRT_SGL_R)
                {
                    spiTransmitAndReceiveData(128,  movingPointer);
                }
                else if (bWriteType == FRMWRT_STK_R)
                {
                    spiTransmitAndReceiveData(128,  movingPointer);
                }
                else if (bWriteType == FRMWRT_ALL_R)
                {
                    spiTransmitAndReceiveData(128,  movingPointer);
                }
                movingPointer+=128;
            }
            //else if there is less than 128 bytes remaining
            else
            {
                if (bWriteType == FRMWRT_SGL_R)
                {
                    spiTransmitAndReceiveData(K,  movingPointer);
                    bRes_R = bLen + 6;
                }
                else if (bWriteType == FRMWRT_STK_R)
                {
                    spiTransmitAndReceiveData(K, movingPointer);
                    bRes_R = (bLen + 6) * (TOTALBOARDS - 1);
                }
                else if (bWriteType == FRMWRT_ALL_R)
                {
                    spiTransmitAndReceiveData(K,movingPointer);
                    bRes_R = (bLen + 6) * TOTALBOARDS;
                }
            }
            i--;                                              //decrement the number of groups of 128 bytes
        }
        return bRes_R;
    }
    
    
    void spiTransmitAndReceiveData(uint32_t blocksize,uint16_t * destbuff)
    {
        ReceiveIndex = 0;
    
        BQSPI_CS_REG  &= ~BQSPI_CS_PIN ;
        while(blocksize != 0U)
        {
            BQSPI_TXBUF=dummy;
            while(BQSPI_BUSY);
            destbuff[ReceiveIndex]=BQSPI_RXBUF;
            ReceiveIndex++;
            blocksize--;
        }
        BQSPI_CS_REG |= BQSPI_CS_PIN;
    
        return;
    }
    #endif
    

  • We're using ARM Cortex R4 -> TMS_Launchpad_RM46 (TMS570LS12)

    the TOTOLBOARDS-Part was surely a bit confusing ... in the end we just gave SpiAutoAddress some parameters.

    int SpiAutoAddress(int debug, uint16 direction, uint8 noOfDevicesToWake)
    {
        int returnValue = 0;
    
        //DUMMY WRITE TO SNCHRONIZE ALL DAISY CHAIN DEVICES DLL (IF A DEVICE RESET OCCURED PRIOR TO THIS)
        returnValue = SpiWriteReg(0, OTP_ECC_DATAIN1, 0X00, 1, FRMWRT_STK_W);
        if(debug==1) printf("BQ79616L125: %d\n", returnValue); if(returnValue < -900) return returnValue;
        returnValue = SpiWriteReg(0, OTP_ECC_DATAIN2, 0X00, 1, FRMWRT_STK_W);
        if(debug==1) printf("BQ79616L127: %d\n", returnValue); if(returnValue < -900) return returnValue;
        returnValue = SpiWriteReg(0, OTP_ECC_DATAIN3, 0X00, 1, FRMWRT_STK_W);
        if(debug==1) printf("BQ79616L129: %d\n", returnValue); if(returnValue < -900) return returnValue;
        returnValue = SpiWriteReg(0, OTP_ECC_DATAIN4, 0X00, 1, FRMWRT_STK_W);
        if(debug==1) printf("BQ79616L131: %d\n", returnValue); if(returnValue < -900) return returnValue;
        returnValue = SpiWriteReg(0, OTP_ECC_DATAIN5, 0X00, 1, FRMWRT_STK_W);
        if(debug==1) printf("BQ79616L133: %d\n", returnValue); if(returnValue < -900) return returnValue;
        returnValue = SpiWriteReg(0, OTP_ECC_DATAIN6, 0X00, 1, FRMWRT_STK_W);
        if(debug==1) printf("BQ79616L135: %d\n", returnValue); if(returnValue < -900) return returnValue;
        returnValue = SpiWriteReg(0, OTP_ECC_DATAIN7, 0X00, 1, FRMWRT_STK_W);
        if(debug==1) printf("BQ79616L137: %d\n", returnValue); if(returnValue < -900) return returnValue;
        returnValue = SpiWriteReg(0, OTP_ECC_DATAIN8, 0X00, 1, FRMWRT_STK_W);
        if(debug==1) printf("BQ79616L139: %d\n", returnValue); if(returnValue < -900) return returnValue;
    
        switch(direction)
        {
        case DIR0_ADDR: // North
            returnValue = SpiWriteReg(0, CONTROL1, 0x00, 1, FRMWRT_ALL_W);      // Set the complete stack to forward direction
            if(debug==1) printf("BQ79616L145: %d\n", returnValue); if(returnValue < -900) break;
            break;
        case DIR1_ADDR: // South
            returnValue = SpiWriteReg(0, CONTROL1, 0x80, 1, FRMWRT_REV_ALL_W);  // Set the complete stack to reverse direction
            if(debug==1) printf("BQ79616L149: %d\n", returnValue); if(returnValue < -900) break;
            break;
        }
    
        //BROADCAST WRITE TO SET ALL DEVICES AS STACK DEVICE
        returnValue = SpiWriteReg(0, COMM_CTRL, 0x02, 1, FRMWRT_ALL_W);
        if(debug==1) printf("BQ79616L155: %d\n", returnValue); if(returnValue < -900) return returnValue;
    
        //ENABLE AUTO ADDRESSING MODE
        switch(direction)
        {
        case DIR0_ADDR: // North
            returnValue = SpiWriteReg(0, CONTROL1, 0X01, 1, FRMWRT_ALL_W); // ADDR_WR 1; North: 0x01 South: 0x81
            if(debug==1) printf("BQ79616L143: %d\n", returnValue); if(returnValue < -900) return returnValue;
            break;
        case DIR1_ADDR: // South
            returnValue = SpiWriteReg(0, CONTROL1, 0X81, 1, FRMWRT_ALL_W); // ADDR_WR 1; North: 0x01 South: 0x81
            if(debug==1) printf("BQ79616L143: %d\n", returnValue); if(returnValue < -900) return returnValue;
            break;
        }
    
        //SET ADDRESSES FOR EVERY BOARD
        for(currentBoard=0; currentBoard<noOfDevicesToWake+1; currentBoard++)
        {
            returnValue = SpiWriteReg(0, direction, currentBoard, 1, FRMWRT_ALL_W);  // direction: "InitNorth" DIR0_ADDR  // "InitSouth" DIR1_ADDR
            if(debug==1) printf("BQ79616L149: %d - %d\n", returnValue, currentBoard);  if(returnValue < -900) return returnValue;
        }
    
        //BROADCAST WRITE TO SET ALL DEVICES AS STACK DEVICE
        returnValue = SpiWriteReg(0, COMM_CTRL, 0x02, 1, FRMWRT_ALL_W);
        if(debug==1) printf("BQ79616L155: %d\n", returnValue); if(returnValue < -900) return returnValue;
    
        //SET THE HIGHEST DEVICE IN THE STACK AS BOTH STACK AND TOP OF STACK
        returnValue = SpiWriteReg(noOfDevicesToWake, COMM_CTRL, 0x03, 1, FRMWRT_SGL_W);
        if(debug==1) printf("BQ79616L158: %d\n", returnValue); if(returnValue < -900) return returnValue;
    
        //SYNCRHONIZE THE DLL WITH A THROW-AWAY READ
        returnValue = SpiReadReg(0, OTP_ECC_DATAIN1, autoaddr_response_frame, 1, 0, FRMWRT_STK_R, noOfDevicesToWake);
        if(debug==1) printf("BQ79616L162: %d\n", returnValue); if(returnValue < -900) return returnValue;
        returnValue = SpiReadReg(0, OTP_ECC_DATAIN2, autoaddr_response_frame, 1, 0, FRMWRT_STK_R, noOfDevicesToWake);
        if(debug==1) printf("BQ79616L164: %d\n", returnValue); if(returnValue < -900) return returnValue;
        returnValue = SpiReadReg(0, OTP_ECC_DATAIN3, autoaddr_response_frame, 1, 0, FRMWRT_STK_R, noOfDevicesToWake);
        if(debug==1) printf("BQ79616L166: %d\n", returnValue); if(returnValue < -900) return returnValue;
        returnValue = SpiReadReg(0, OTP_ECC_DATAIN4, autoaddr_response_frame, 1, 0, FRMWRT_STK_R, noOfDevicesToWake);
        if(debug==1) printf("BQ79616L168: %d\n", returnValue); if(returnValue < -900) return returnValue;
        returnValue = SpiReadReg(0, OTP_ECC_DATAIN5, autoaddr_response_frame, 1, 0, FRMWRT_STK_R, noOfDevicesToWake);
        if(debug==1) printf("BQ79616L170: %d\n", returnValue); if(returnValue < -900) return returnValue;
        returnValue = SpiReadReg(0, OTP_ECC_DATAIN6, autoaddr_response_frame, 1, 0, FRMWRT_STK_R, noOfDevicesToWake);
        if(debug==1) printf("BQ79616L172: %d\n", returnValue); if(returnValue < -900) return returnValue;
        returnValue = SpiReadReg(0, OTP_ECC_DATAIN7, autoaddr_response_frame, 1, 0, FRMWRT_STK_R, noOfDevicesToWake);
        if(debug==1) printf("BQ79616L174: %d\n", returnValue); if(returnValue < -900) return returnValue;
        returnValue = SpiReadReg(0, OTP_ECC_DATAIN8, autoaddr_response_frame, 1, 0, FRMWRT_STK_R, noOfDevicesToWake);
        if(debug==1) printf("BQ79616L176: %d\n", returnValue); if(returnValue < -900) return returnValue;
    
        //OPTIONAL: read back all device addresses
        for(currentBoard=0; currentBoard<noOfDevicesToWake+1; currentBoard++)
        {
            returnValue = SpiReadReg(currentBoard, direction, autoaddr_response_frame, 1, 0, FRMWRT_SGL_R, noOfDevicesToWake);  // direction: "InitNorth" DIR0_ADDR  // "InitSouth" DIR1_ADDR
            if(debug==1) printf("BQ79616L182: %d - %d\n", returnValue, currentBoard); if(returnValue < -900) return returnValue;
        }
    
        //OPTIONAL: read register address 0x2001 and verify that the value is 0x14
        returnValue = SpiReadReg(0, 0x2001, autoaddr_response_frame, 1, 0, FRMWRT_SGL_R, noOfDevicesToWake);
        if(debug==1) printf("BQ79616L187: %d\n", returnValue); if(returnValue < -900) return returnValue;
    
       return returnValue;
    }
    

    we searched through all the code that caused endless loops and made these parts return a value below -900.
    Previously these while{}-loops caused a 120sec freeze before the watchdog on the board rebooted. (check "spi.c" again)
    Your code to transmit is actually quite different then the autogenerated one from "HALCoGen".
    Well, we also did some (mentioned) modifications :-)

    /** @fn uint32 spiTransmitData(spiBASE_t *spi, spiDAT1_t *dataconfig_t, uint32 blocksize, uint16 * srcbuff)
    *   @brief Transmits Data using polling method
    *   @param[in] spi           - Spi module base address
    *   @param[in] dataconfig_t    - Spi DAT1 register configuration
    *   @param[in] blocksize    - number of data
    *   @param[in] srcbuff        - Pointer to the source data ( 16 bit).
    *
    *   @return flag register value.
    *
    *   This function transmits blocksize number of data from source buffer using polling method.
    */
    /* SourceId : SPI_SourceId_005 */
    /* DesignId : SPI_DesignId_005 */
    /* Requirements : HL_SR131 */
    int spiTransmitData(spiBASE_t *spi, spiDAT1_t *dataconfig_t, uint32 blocksize, uint16 * srcbuff)
    {
        volatile uint32 SpiBuf;
        uint16 Tx_Data;
        uint32 Chip_Select_Hold = (dataconfig_t->CS_HOLD) ? 0x10000000U : 0U;
        uint32 WDelay = (dataconfig_t->WDEL) ? 0x04000000U : 0U;
        SPIDATAFMT_t DataFormat = dataconfig_t->DFSEL;
        uint8 ChipSelect = dataconfig_t->CSNR;
    
        int avoidEndlessLoop = 0;
    
        while(blocksize != 0U)
        {
            if((spi->FLG & 0x000000FFU) !=0U)
            {
               break;
            }
    
            if(blocksize == 1U)
            {
               Chip_Select_Hold = 0U;
            }
            /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
            Tx_Data = *srcbuff;
    
            spi->DAT1 =  ((uint32)DataFormat << 24U) |
                         ((uint32)ChipSelect << 16U) |
                         (WDelay)           |
                         (Chip_Select_Hold) |
                         (uint32)Tx_Data;
            /*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
            srcbuff++;
            /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Hardware status bit read check" */
            while(((spi->FLG & 0x00000100U) != 0x00000100U) && avoidEndlessLoop < 50000) // 500ms
            {
                avoidEndlessLoop++;
                delayus(10);
            } /* Wait */
            if(avoidEndlessLoop >= 50000) break;
    
            SpiBuf = spi->BUF;
    
            blocksize--;
        }
    
        if(avoidEndlessLoop >= 50000) return -953; // Error spiTransmitData
        return (spi->FLG & 0xFFU);
    }

    Hope you can use some of it. Best regards, Collin

  • Collin--

    Thanks for your reply. How does your spiReadReg function make use of noOfDevicesToWake? When is this parameter updated?

    Priya

  • Collin,

    Thanks for the response, yes the current way we use is TOTALBOARDs variable. Appreciate if you can comment further to help Priya on your above parameter mod.

    Regards,

    Taylor

  • I came to realize I need to reinitialize the SPI and define the peripheral module SPI pin functions following wake up as part of repeating the auto addressing until successful. It finally works! 

    Thanks for your help.

  • Happy to hear that and sorry for my delay.
    I always need to restart my Mac (to Windows) to access my CodeComposer Projects, so sometimes I can read posts but have no bases to reply :-/

    concerning the previous question, basically everywhere TOTALBOARDS came to use, I replaced it with my parameter. 

    One more hint: I'm using the "USER CODE BEGIN" and "USER CODE END" Blocks to replace the autogenerated parts with my code by using
    #if 0 and #endif statements. Using this, I'm able to generate the HALCoGen code over and over again, without losing my modifications.

    int spiTransmitAndReceiveData(spiBASE_t *spi, spiDAT1_t *dataconfig_t, uint32 blocksize, uint16 * srcbuff, uint16 * destbuff)
    {
        ... HALCoGen variables ...
    
    /* USER CODE BEGIN (14) */
        ... my code ...
    #if 0
    /* USER CODE END */
    
        ... HALCoGen code ...
        
    /* USER CODE BEGIN (15) */
    #endif
        ... my code ...
    /* USER CODE END */
    }


    this came in very handy when I extended the SPI-bridge with a CAN-Controller and Ethernet.
    Each time I modify the board settings, HALCoGen overwrites everything which is not in USER-CODE-Blocks.

    Best Regards Collin

  • Collin,

    Thanks for your help!

    Regards,

    Taylor