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.
Tool/software: Code Composer Studio
I2C Slave communication test is performed using the I2C_Slave_lcdkOMAPL138_c674xTestProject project.
I set to non-dma interrupt mode and try to communicate with the other board, but after the I2C_transfer function in the 416th line, it does not move to the next line.
Even if I give Master signal TX / RX from the opponent board, I don't respond, and I want you to tell me if the code is strange or if the test method is wrong.
/** * \file main_test.c * * \brief The application Demonstrate the I2C master/slave mode functionality. * I2C data are transferred from master to slave and at the * same instance data from slave are transferred to master. * * \details * To demonstrate the example two boards are needed one board * acts as master and another as slave. * * Following is the Pin connection information: * MasterI2C_SCL-----SlaveI2C_SCL * MasterI2C_SDA-----SlaveI2C_SDA * * \Running the example * 1) Connect the master and slave boards as per above pin connections. * 2) Two consoles. One for master and another for slave. * 3) Run slave application binary and then master application binary. * * \Output * At slave end console: * All tests have passed. * * At master end console: * All tests have passed. */ /* * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include <stdio.h> #include <string.h> /* XDCtools Header files */ #include <xdc/std.h> #include <xdc/cfg/global.h> #include <xdc/runtime/System.h> #include <stdio.h> #include <ti/sysbios/knl/Task.h> /* BIOS Header files */ #include <ti/sysbios/BIOS.h> #include <xdc/runtime/Error.h> /* CSL Header files */ #ifdef _TMS320C6X #include <ti/csl/csl_chip.h> #endif /* OSAL Header files */ #include <ti/osal/osal.h> /* TI-RTOS Header files */ #include <ti/drv/i2c/I2C.h> #include <ti/drv/i2c/soc/I2C_soc.h> #include <ti/drv/i2c/src/I2C_osal.h> #include <ti/drv/i2c/test/src/I2C_log.h> /* Board Header files */ #include <ti/board/board.h> /* * slave address for master/slave board to board test, by default, * all the AM boards own slave address is set to 0x70 and all the * Keystone boards own slave address is set to 0x10. */ /* * master own slave address and transaction slave address */ #define I2C_TEST_MASTER_OSA_7B 0x20 #define I2C_TEST_MASTER_OSA_10B 0x220 #define I2C_TEST_MASTER_SA_7B 0x44 #define I2C_TEST_MASTER_SA_10B 0x230 /* * slave own slave address is set to master transaction slave address */ #define I2C_TEST_SLAVE_OSA_7B I2C_TEST_MASTER_SA_7B #define I2C_TEST_SLAVE_OSA_10B I2C_TEST_MASTER_SA_10B /* * This address is the own slave address set on the master board, * it shoud not be the same as the own slave address set on the * slave board */ #define I2C_OWN_SLAVE_ADDR_MASTER 0x60 /* I2C Test definitions */ /* Unit test IDs */ #define I2C_TEST_ID_DMA 0 /* I2C DMA mode test */ #define I2C_TEST_ID_INT 1 /* I2C non-DMA interrupt mode test */ #define I2C_TEST_ID_CB 2 /* I2C callback mode test */ #define I2C_TEST_ID_XA 3 /* I2C 10-bit address mode test */ /* Define the I2C test interface */ typedef struct I2C_Tests_s { bool (*testFunc)(void *); int16_t testId; bool master; bool pollMode; bool cbMode; bool dmaMode; uint32_t timeout; char testDesc[80]; } I2C_Tests; typedef struct I2C_XferLen_s { uint32_t wrLen; uint32_t rdLen; } I2C_XferLen; /********************************************************************** ************************** Macros ************************************ **********************************************************************/ #define I2C_MSG_LENGTH 10 #define I2C_MSG_LENGTH2 75 #define I2C_NUM_XFERS 6 I2C_XferLen masterXferLen[I2C_NUM_XFERS] = { { I2C_MSG_LENGTH, 0 }, { I2C_MSG_LENGTH2, 0 }, { 0, I2C_MSG_LENGTH }, { 0, I2C_MSG_LENGTH2 }, /* For restart transfer test */ { I2C_MSG_LENGTH, I2C_MSG_LENGTH }, { I2C_MSG_LENGTH2, I2C_MSG_LENGTH2 } }; I2C_XferLen slaveXferLen[I2C_NUM_XFERS] = { { 0, I2C_MSG_LENGTH }, { I2C_MSG_LENGTH, 0 } }; /********************************************************************** ************************** Global Variables ************************** **********************************************************************/ #pragma DATA_ALIGN (masterRxBuffer, 128) unsigned char masterRxBuffer[I2C_MSG_LENGTH2 + 1]; #pragma DATA_ALIGN (slaveRxBuffer, 128) unsigned char slaveRxBuffer[I2C_MSG_LENGTH2 + 1]; unsigned char masterTxBuffer[I2C_MSG_LENGTH2 + 1] = "Master Txd I2C Master Txd I2C Master Txd I2C Master Txd I2C Master Txd I2C "; unsigned char slaveTxBuffer[I2C_MSG_LENGTH2 + 1] = "Slave Txd I2C Slave Txd I2C Slave Txd I2C Slave Txd I2C Slave Txd I2C "; /* Transaction data */ I2C_Transaction transaction; /* Callback mode variables */ SemaphoreP_Params cbSemParams; SemaphoreP_Handle cbSem = NULL; /* Master callback mode function */ void I2C_callbackMaster(I2C_Handle handle, I2C_Transaction *transaction, int16_t transferStatus) { I2C_osalPostLock(cbSem); } /* Slave callback mode function */ void I2C_callbackSlave(I2C_Handle handle, I2C_Transaction *transaction, int16_t transferStatus) { if (transferStatus == I2C_STS_RESTART) { /* Restart condition */ transaction->writeBuf = (void *)slaveTxBuffer; transaction->writeCount = I2C_MSG_LENGTH2; } else { I2C_osalPostLock(cbSem); } } /* * ======== I2C init config ======== */ static void I2C_initConfig(uint32_t instance, I2C_Tests *test) { I2C_HwAttrs i2c_cfg; uint32_t ownSlaveAddr; bool master = test->master; bool pollMode = test->pollMode; #ifdef I2C_DMA_ENABLE bool dmaMode = test->dmaMode; #endif /* Get the default I2C init configurations */ I2C_socGetInitCfg(instance, &i2c_cfg); /* * Set blocking mode (dma mode or non-dma interrupt mode) * or callback mode */ if (pollMode == true) { /* polling mode */ i2c_cfg.enableIntr = false; } else { /* interrupt enabled */ i2c_cfg.enableIntr = true; #ifdef I2C_DMA_ENABLE if (dmaMode == true) { /* Set the DMA related init config */ } #endif } if (master) { if (test->testId == I2C_TEST_ID_XA) { ownSlaveAddr = I2C_TEST_MASTER_OSA_10B; } else { ownSlaveAddr = I2C_TEST_MASTER_OSA_7B; } } else { if (test->testId == I2C_TEST_ID_XA) { ownSlaveAddr = I2C_TEST_SLAVE_OSA_10B; } else { ownSlaveAddr = I2C_TEST_SLAVE_OSA_7B; } } #if defined (evmK2H) || defined (evmK2K) || defined (evmK2E) || defined (evmK2L) || defined (evmK2G) || defined (LCDK_OMAPL138) i2c_cfg.ownSlaveAddr = ownSlaveAddr; #else i2c_cfg.ownSlaveAddr[0] = ownSlaveAddr; #endif /* Set the I2C init configurations */ I2C_socSetInitCfg(instance, &i2c_cfg); } bool I2C_verify_data(unsigned char *data1, unsigned char *data2, uint32_t length) { uint32_t i; bool ret = true; for (i = 0; i < length; i++) { if (data1[i] != data2[i]) { ret = false; break; } } return (ret); } /* * Utility function which converts a local GEM L2 memory address * to global memory address. */ static uint32_t l2_global_address (uint32_t addr) { if ((addr >= 0x800000) && (addr < 0x1000000)) { #ifdef _TMS320C6X uint32_t coreNum; /* Get the core number. */ coreNum = CSL_chipReadReg(CSL_CHIP_DNUM); #if defined(SOC_AM572x) || defined(SOC_AM571x) || defined(SOC_AM574x) /* Compute the global address. */ return ((1 << 30) | (coreNum << 24) | (addr & 0x00ffffff)); #else /* Compute the global address. */ return ((1 << 28) | (coreNum << 24) | (addr & 0x00ffffff)); #endif #else return addr; #endif } else { /* non-L2 address range */ return addr; } } static bool I2C_test_mst_slv_xfer(I2C_Handle i2c, I2C_Tests *test, uint32_t wrLen, uint32_t rdLen) { bool transferOK; uint32_t addrMasterRxBuf, addrSlaveRxBuf; bool ret = false; bool master = test->master; bool cbMode = test->cbMode; bool dmaMode = test->dmaMode; uint32_t timeout = test->timeout; uint32_t slaveAddr; if (dmaMode) { addrMasterRxBuf = l2_global_address((uint32_t)masterRxBuffer); addrSlaveRxBuf = l2_global_address((uint32_t)slaveRxBuffer); } else { addrMasterRxBuf = (uint32_t)masterRxBuffer; addrSlaveRxBuf = (uint32_t)slaveRxBuffer; } memset(masterRxBuffer, 0, sizeof(masterRxBuffer)); memset(slaveRxBuffer, 0, sizeof(slaveRxBuffer)); if (dmaMode) { CacheP_wbInv((void *)addrMasterRxBuf, (int32_t)sizeof(masterRxBuffer)); CacheP_wbInv((void *)slaveRxBuffer, (int32_t)sizeof(slaveRxBuffer)); } /* Initialize slave I2C transaction structure */ I2C_transactionInit(&transaction); transaction.writeCount = wrLen; transaction.readCount = rdLen; transaction.timeout = timeout; if (test->testId == I2C_TEST_ID_XA) { /* 10-bit slave address */ slaveAddr = I2C_TEST_MASTER_SA_10B; transaction.expandSA = true; } else { /* 7-bit slave address */ slaveAddr = I2C_TEST_MASTER_SA_7B; transaction.expandSA = false; } if (master == true) { transaction.masterMode = true; transaction.slaveAddress = slaveAddr; transaction.writeBuf = (Ptr)masterTxBuffer; transaction.readBuf = (Ptr)addrMasterRxBuf; } else { transaction.masterMode = false; transaction.slaveAddress = 0; transaction.writeBuf = (Ptr)slaveTxBuffer; transaction.readBuf = (Ptr)addrSlaveRxBuf; if (rdLen != 0) { /* for restart transfer, slave sends the data in callback mode */ transaction.writeCount = 0; } } /* Initiate I2C transfer */ transferOK = I2C_transfer(i2c, &transaction); if(transferOK) { if (cbMode) { if (I2C_osalPendLock(cbSem, timeout) != SemaphoreP_OK) { goto Err; } } if (master == true) { /* master mode, verify master recieved data match with slave sent data */ if (I2C_verify_data(masterRxBuffer, slaveTxBuffer, rdLen) == false) { goto Err; } /* Print contents of master receive buffer */ I2C_log("Master: %s\n", masterRxBuffer); } else { /* slave mode, verify slave recieved data match with master sent data */ if (I2C_verify_data(slaveRxBuffer, masterTxBuffer, rdLen) == false) { goto Err; } /* Print contents of slave receive buffer */ I2C_log("Slave: %s\n", slaveRxBuffer); } } else { I2C_log("Unsuccessful slave I2C transfer"); goto Err; } ret = true; Err: return (ret); } static bool I2C_test_master_slave(void *arg) { I2C_Handle i2c; I2C_Params i2cParams; uint32_t instance, i; I2C_XferLen *xferLen; uint32_t testNum; bool ret = false; I2C_Tests *test = (I2C_Tests *)arg; bool master = test->master; bool cbMode = test->cbMode; if (cbMode == true) { /* Create call back semaphore */ I2C_osalSemParamsInit(&cbSemParams); cbSemParams.mode = SemaphoreP_Mode_BINARY; cbSem = I2C_osalCreateBlockingLock(0, &cbSemParams); } /* Soc configuration structures indexing starts from 0. If the IP * instances start with 1, to address proper Configuration * structure index, I2C Instance should be substracted with 1 */ if (master == true) { instance = BOARD_I2C_MASTER_INSTANCE; } else { instance = BOARD_I2C_SLAVE_INSTANCE; } I2C_initConfig(instance, test); /* Initialize I2C handle */ I2C_Params_init(&i2cParams); i2cParams.bitRate =I2C_400kHz; if (cbMode == true) { i2cParams.transferMode = I2C_MODE_CALLBACK; if (master == true) { i2cParams.transferCallbackFxn = I2C_callbackMaster; } else { i2cParams.transferCallbackFxn = I2C_callbackSlave; } } i2c = I2C_open(instance, &i2cParams); if (i2c == NULL) { I2C_log("Error initializing I2C\n"); goto Err; } else { I2C_log("I2C initialized\n"); } if (cbMode == true) { testNum = I2C_NUM_XFERS; } else { /* do not test restart transfer in non-callback mode */ testNum = I2C_NUM_XFERS - 2; } if (master == true) { xferLen = &masterXferLen[1]; } else { xferLen = &slaveXferLen[1]; } if (I2C_test_mst_slv_xfer(i2c, test, xferLen->wrLen, xferLen->rdLen) == false) { goto Err; } if (master == true) { /* * master sleep for 1 second after each transfer * to sync with slave transfer */ Task_sleep(1000); } ret = true; Err: if (i2c) { I2C_close(i2c); } if (cbSem) { I2C_osalDeleteBlockingLock(cbSem); cbSem = NULL; } return (ret); } void I2C_test_print_test_desc(I2C_Tests *test) { char testId[16] = {0, }; /* Print unit test ID */ sprintf(testId, "%d", test->testId); I2C_log("\r\n I2C UT %s\r\n", testId); /* Print test description */ I2C_log("\r\n %s\r\n", test->testDesc); } #ifdef I2C_DMA_ENABLE #define I2C_NUM_TESTS 4 #else #define I2C_NUM_TESTS 3 #endif I2C_Tests I2c_tests_master[I2C_NUM_TESTS] = { /* testFunc testID master pollMode cbMode dmaMode timeout testDesc */ #ifdef I2C_DMA_ENABLE {I2C_test_master_slave, I2C_TEST_ID_DMA, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n I2C master slave test master in dma mode"}, #endif {I2C_test_master_slave, I2C_TEST_ID_INT, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n I2C master slave test master in non-dma interrupt mode"}, {I2C_test_master_slave, I2C_TEST_ID_CB, true, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n I2C master slave test master in callback mode"}, {I2C_test_master_slave, I2C_TEST_ID_XA, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n I2C master slave test master 10-bit address mode"}, }; I2C_Tests I2c_tests_slave[I2C_NUM_TESTS] = { #ifdef I2C_DMA_ENABLE {I2C_test_master_slave, I2C_TEST_ID_DMA, false, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n I2C master slave test slave in dma mode"}, #endif {I2C_test_master_slave, I2C_TEST_ID_INT, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n I2C master slave test slave in non-dma interrupt mode"}, {I2C_test_master_slave, I2C_TEST_ID_CB, false, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n I2C master slave test slave in callback mode"}, {I2C_test_master_slave, I2C_TEST_ID_XA, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n I2C master slave test slave 10-bit address mode"}, }; /* * ======== slaveTaskFxn ======== * The task is part of separate slave example project. * To test slave mode example, slave task has to be * ready for master. Slave I2C sends a message to master * while receiving message from master. */ Void slaveTaskFxn (UArg arg0, UArg arg1) { uint32_t i; bool testFail = false; I2C_Tests *test; I2C_init(); // for (i = 0; i < I2C_NUM_TESTS; i++) // { test = &I2c_tests_slave[0]; I2C_test_print_test_desc(test); if (test->testFunc((void *)test) == true) { I2C_log("\r\n %s have passed\r\n", test->testDesc); } else { I2C_log("\r\n %s have failed\r\n", test->testDesc); testFail = true; // break; } // } if(testFail == true) { UART_printStatus("\n Some tests have failed. \n"); } else { UART_printStatus("\n All tests have passed. \n"); } I2C_log("Done\n"); Task_exit(); } /* * ======== masterTaskFxn ======== * This task is part of master example project. * Slave task has to ensure transaction ready. * Master I2C sends a message to slave and * receives message from slave. */ Void masterTaskFxn (UArg arg0, UArg arg1) { uint32_t i; bool testFail = false; I2C_Tests *test; I2C_init(); for (i = 0; i < I2C_NUM_TESTS; i++) { test = &I2c_tests_master[i]; I2C_test_print_test_desc(test); if (test->testFunc((void *)test) == true) { I2C_log("\r\n %s have passed\r\n", test->testDesc); } else { I2C_log("\r\n %s have failed\r\n", test->testDesc); testFail = true; break; } } if(testFail == true) { UART_printStatus("\n Some tests have failed. \n"); } else { UART_printStatus("\n All tests have passed. \n"); } I2C_log("Done\n"); Task_exit(); } /* * ======== main ======== */ int main(void) { /* Call board init functions */ Board_initCfg boardCfg; #if defined (evmK2G) I2C_HwAttrs i2c_cfg; uint8_t instance; Board_SoCInfo socInfo; #endif #if defined(SOC_AM335x) || defined (SOC_AM437x) Task_Handle task; Error_Block eb; Error_init(&eb); #if defined (I2C_SLAVE_TASK) task = Task_create(slaveTaskFxn, NULL, &eb); #elif defined (I2C_MASTER_TASK) task = Task_create(masterTaskFxn, NULL, &eb); #endif /* Task type */ if (task == NULL) { System_printf("Task_create() failed!\n"); BIOS_exit(0); } #endif /* Soc type */ boardCfg = BOARD_INIT_PINMUX_CONFIG | BOARD_INIT_MODULE_CLOCK | BOARD_INIT_UART_STDIO; Board_init(boardCfg); #if defined (evmK2G) /* Read the SoC info to get the System clock value */ Board_getSoCInfo(&socInfo); if(socInfo.sysClock != BOARD_SYS_CLK_DEFAULT) { for (instance = 0; instance < CSL_I2C_CNT; instance++) { /* Get the default I2C init configurations */ I2C_socGetInitCfg(instance, &i2c_cfg); /* Update the I2C functional clock based on CPU clock - 1G or 600MHz */ i2c_cfg.funcClk = socInfo.sysClock/I2C_MODULE_CLOCK_DIVIDER; /* Set the default I2C init configurations */ I2C_socSetInitCfg(instance, &i2c_cfg); } } #endif /* Start BIOS */ BIOS_start(); return (0); }
Hello,
Please ensure you have followed the hardware hookup indicated here: http://software-dl.ti.com/processor-sdk-rtos/esd/docs/latest/rtos/index_device_drv.html#id31
Can you also please share what changes you have made to the example?
Here are a couple of resources that may help resolve your issue:
Regards,
Sahin
Does I2C_Slave_lcdkOMAPL138_c674xTestProject project support I2C slave mode?
As in the example, the SCL, SDA, and GND hardware pins are connected, and the current counterpart, the master, sends the address.
However, since the NACK signal does not come, data is not transmitted later.
In the example code, proceed to I2C master slave test master in non-dma interrupt mode, and of course, the slave addresses matched each other.
Line 436, transferOK = I2C_transfer (i2c, & transaction);
The transfer function waits indefinitely. (The data is continuously transferred from the partner board.)
In the example project, except for the slave address, almost nothing has changed. What is the problem?
If you look at the 5.6 I2C Driver in the TI-RTOS 2.20 User's Guide guide, it says that it does not support I2C slave mode.
Does TMS320C6748 TI-RTOS support I2C slave mode?
Hello,
I replied to your other thread here: https://e2e.ti.com/support/tools/ccs/f/81/p/893481/3318682#3318682
Let us continue the discussion in that thread. I will close this one.
Regards,
Sahin