Tool/software:
1. DUT: Device in use is the Jacinto J721e EVM carrier board with the GESI board extension.
2. Processor core: I'm developing on the mcu2_1 R5F core.
3. OS: I'm running RTOS for the OS.
4. SDK version: I am currently using only the SDK/PDK (ti-processor-sdk-rtos-j721e-evm-10_01_00_04) for my libraries and calls.
5. Hardware setup: I have SPI3 pins on the GESI board (J16 #13 - CLK; J5 #12 - D0, #4 - CS1) connected to an oscilloscope.
6. Software: I am attaching an example source code with which I can produce the problem. This has a .c file with the SPI setup and instructions; a CMakeLists.txt file is included to show you the build configuration.
Besides this running on mcu2_1 R5F, there's the sci server set up on mcu1_0.
#include <stdio.h> #include <string.h> #include <ti/osal/osal.h> #include <ti/drv/sciclient/sciclient.h> /* TI-RTOS Header files */ #include <ti/drv/spi/soc/SPI_soc.h> #include <ti/drv/spi/src/SPI_osal.h> #include <ti/drv/spi/SPI.h> #include <ti/board/src/j721e_evm/include/board_utils.h> #include <ti/csl/soc/j721e/src/cslr_soc_baseaddress.h> #include <ti/csl/soc/j721e/src/cslr_wkup_ctrl_mmr.h> /** \brief Application stack size */ #define APP_TSK_STACK_MAIN (0x4000U) /** \brief Task stack */ static uint8_t gAppTskStackMain[APP_TSK_STACK_MAIN] __attribute__((aligned(32))); /* Maximum # of channels per SPI instance */ #define MCSPI_MAX_NUM_CHN 4 /* SPI transfer message definitions */ #define SPI_MSG_LENGTH 8 #define SPI_WORD_SIZE_IN_BITS 8 #define SIZE_TOO_LARGE (0x1FFFU) #define MCSPI3_CONFIG_IDX (3U) #define MCSPI6_CONFIG_IDX (6U) #ifdef __cplusplus extern "C" { #endif //__cplusplus extern void UART_printf(const char *pcString, ...); #ifdef __cplusplus } #endif //__cplusplus /* Callback mode variables */ SemaphoreP_Params cbSemParams; SemaphoreP_Handle cbSem[MCSPI_MAX_NUM_CHN] = {NULL, NULL, NULL, NULL}; unsigned char masterRxBuffer[128] __attribute__ ((aligned (128))); unsigned char masterTxBuffer[128] __attribute__ ((aligned (128))); void MCSPI_initSciclient() { int32_t ret = CSL_PASS; Sciclient_ConfigPrms_t config; /* Now reinitialize it as default parameter */ ret = Sciclient_configPrmsInit(&config); if (CSL_PASS != ret) { UART_printf("Sciclient_configPrmsInit Failed\n"); } else if (CSL_PASS == ret) { ret = Sciclient_init(&config); if (CSL_PASS != ret) { UART_printf("Sciclient_init Failed\n"); } } } /* Callback mode functions */ // NOT CURRENTLY USED void SPI_callback(SPI_Handle handle, SPI_Transaction *transaction) { UART_printf("SPI callback data size: %d\n", transaction->count); if (transaction->count > SIZE_TOO_LARGE) { SemaphoreP_post(cbSem[0]); return; } // uint8_t numToCopy = transaction->count * (SPI_WORD_SIZE_IN_BITS / 8); // CircularBuffer_write(&g_rxbuffer, reinterpret_cast<uint8_t*>(transaction->rxBuf), numToCopy); SemaphoreP_post(cbSem[0]); } void spi_test_master(void *arg0, void *arg1) { UART_printf("Starting SPI Master test. \n"); TaskP_sleepInMsecs(1000); uint32_t terminateXfer = 1; SPI_init(); // == Set up the SPI test for receive == SPI_Handle spi; SPI_Params spiParams; // Note: master is false, pollmode is false, cbmode is true, timeout should be SemaphoreP_WAIT_FOREVER // Creates a callback semaphore SPI_osalSemParamsInit(&cbSemParams); cbSemParams.mode = SemaphoreP_Mode_BINARY; cbSem[0] = SPI_osalCreateBlockingLock(0, &cbSemParams); uint32_t instance = MCSPI3_CONFIG_IDX; //SPI_test_get_instance(2, false); uint32_t domain = SPI_MCSPI_DOMAIN_MAIN; //SPI_test_get_domain(2, false); // SPI_initConfig(domain, instance, test, MCSPI_TEST_CHN, BFALSE); --> expanded below MCSPI_socInit(); SPI_HWAttrs spi_cfg; SPI_socGetInitCfg(domain, instance, &spi_cfg); spi_cfg.enableIntr = BFALSE; // BTRUE; spi_cfg.edmaHandle = NULL; spi_cfg.dmaMode = BFALSE; /* Set the SPI init configurations */ spi_cfg.chNum = 1; spi_cfg.chnCfg[1].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_6; spi_cfg.chnCfg[1].tcs = MCSPI_CS_TCS_0PNT5_CLK; spi_cfg.chnCfg[1].trMode = MCSPI_TX_ONLY_MODE; //MCSPI_TX_RX_MODE; /* Set interrupt path */ if(CSL_PASS != MCSPI_configSocIntrPath(instance, &spi_cfg, BTRUE)) { UART_printf("\n Set interrupt path failed! Interrupt number %d\n", spi_cfg.intNum); } else { UART_printf("\n The interrupt path has been set with interrupt number %d\n", spi_cfg.intNum); } /* Set the SPI init configurations */ SPI_socSetInitCfg(domain, instance, &spi_cfg); /* Initialize SPI handle */ SPI_Params_init(&spiParams); spiParams.mode = SPI_MASTER; spiParams.transferMode = SPI_MODE_BLOCKING; // SPI_MODE_CALLBACK; // spiParams.transferCallbackFxn = SPI_callback; spiParams.transferTimeout = SemaphoreP_WAIT_FOREVER; spiParams.frameFormat = SPI_POL1_PHA0; spiParams.dataSize = 8U; // 8 bits spiParams.bitRate = 153600; // 153.6kHz spi = SPI_open(domain, instance, &spiParams); if (NULL == spi) { UART_printf("Error initializing SPI\n"); return; } uint32_t xfer_len = SPI_MSG_LENGTH; Osal_delay(500); // Attempt a transfer uintptr_t addrMasterTxBuf = (uintptr_t)masterTxBuffer; uintptr_t addrMasterRxBuf = (uintptr_t)masterRxBuffer; bool transferOK = true; memset(masterRxBuffer, 0, sizeof(masterRxBuffer)); memset(masterTxBuffer, 0, sizeof(masterTxBuffer)); memcpy(masterTxBuffer, "TEST1234", 8); while (1) { SPI_Transaction transaction; transaction.count = xfer_len; transaction.arg = (void *)&terminateXfer; transaction.txBuf = (void *)addrMasterTxBuf; transaction.rxBuf = (void *)addrMasterRxBuf; transferOK = SPI_transfer((SPI_Handle)spi, &transaction); if (!transferOK) { UART_printf("Error in SPI transfer\n"); } else { UART_printf("SPI transfer successful.\n"); } Osal_delay(1000); } } /* * ======== main ======== */ int main(void) { UART_printf("[UART] spi_test main()\n"); /* This should be called before any other OS calls (like Task creation, OS_start, etc..) */ OS_init(); /* Call board init functions */ Board_initCfg boardCfg; Board_STATUS boardStatus; /* Initialize the task params */ TaskP_Params taskParams; TaskP_Params_init(&taskParams); /* Set the task priority higher than the default priority (1) */ taskParams.priority = 2; taskParams.stack = gAppTskStackMain; taskParams.stacksize = sizeof (gAppTskStackMain); TaskP_Params taskDataProcess; TaskP_Params_init(&taskDataProcess); TaskP_create(&spi_test_master, &taskParams); // If we run on MCU1_0, we need to setup the SciServer // For now, we will set up for MCU2_0, which uses a sciclient MCSPI_initSciclient(); Board_PinmuxConfig_t boardPinmuxCfg; Board_pinmuxGetCfg(&boardPinmuxCfg); // boardPinmuxCfg.autoCfg = BOARD_PINMUX_AUTO; boardPinmuxCfg.gesiExp = BOARD_PINMUX_GESI_ICSSG; Board_pinmuxSetCfg(&boardPinmuxCfg); boardCfg = BOARD_INIT_PINMUX_CONFIG | BOARD_INIT_MODULE_CLOCK | BOARD_INIT_UART_STDIO | BOARD_INIT_MODULE_CLOCK_MAIN; boardStatus = Board_init(boardCfg); /* Unlock lock key registers for Partition 1 */ /* write Partition Lock Key 0 Register */ CSL_REG32_WR(CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_LOCK1_KICK0, 0x68EF3490); /* write Partition Lock Key 1 Register */ CSL_REG32_WR(CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_LOCK1_KICK1, 0xD172BC5A); /* Check for unlock */ uint32_t regVal = CSL_REG32_RD(CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_LOCK1_KICK0); while ((regVal & 0x1) != 0x1U) { regVal = CSL_REG32_RD(CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_LOCK1_KICK0); } /* Enable MCU_MCSPI1 and MCSPI3 independently pin out */ CSL_REG32_WR(CSL_MCU_CTRL_MMR0_CFG0_BASE + CSL_MCU_CTRL_MMR_CFG0_MCU_SPI1_CTRL, CSL_MCU_CTRL_MMR_CFG0_MCU_SPI1_CTRL_SPI1_LINKDIS_MASK); // *((uint32_t*)(0x40F04060)) = 1; // Creates a callback semaphore SemaphoreP_Params_init(&cbSemParams); cbSemParams.mode = SemaphoreP_Mode_BINARY; cbSem[0] = SemaphoreP_create(0, &cbSemParams); /* Start the scheduler to start the tasks executing. */ OS_start(); }
cmake_minimum_required(VERSION 3.24) # Set the project name and version project(spitx VERSION 1.0) # Use debug or release libs if(CMAKE_BUILD_TYPE STREQUAL "Release") set(BUILD_PROFILE "release") else() set(BUILD_PROFILE "debug") endif() if(NOT DEFINED BOARD) set(BOARD "j721e_evm") endif() # Set the target processor if(NOT DEFINED TARGET_PROCESSOR) set(TARGET_PROCESSOR "r5f") # Modify this according to your target processor (R5F or A72, etc.) elseif(NOT "${TARGET_PROCESSOR}" STREQUAL "r5f") message(FATAL_ERROR "TARGET_PROCESSOR=${TARGET_PROCESSOR} is not supported for this project.") endif() # Set the target core # mcu1_0 mcu1_1 are no longer supported set(SUPPORTED_CORES mcu2_0 mcu2_1) if(NOT DEFINED TARGET_CORE) set(TARGET_CORE "mcu2_1") elseif(NOT "${TARGET_CORE}" IN_LIST SUPPORTED_CORES) message(FATAL_ERROR "TARGET_CORE=${TARGET_CORE} not in supported core list.") endif() # Append to additional build options if("${TARGET_CORE}" STREQUAL "mcu2_0") set(ADDITIONAL_BUILD_OPTS "${ADDITIONAL_BUILD_OPTS} -DBUILD_MCU2_0 -DBUILD_MCU") elseif("${TARGET_CORE}" STREQUAL "mcu2_1") set(ADDITIONAL_BUILD_OPTS "${ADDITIONAL_BUILD_OPTS} -DBUILD_MCU2_1 -DBUILD_MCU") endif() # Specify the C compiler and flags set(CMAKE_C_COMPILER "$ENV{TI_TOOLCHAIN_PATH}/bin/tiarmclang") set(CMAKE_CXX_COMPILER "$ENV{TI_TOOLCHAIN_PATH}/bin/tiarmclang") set(CMAKE_LINKER "$ENV{TI_TOOLCHAIN_PATH}/bin/tiarmclang") set(LIBC_AR "$ENV{TI_TOOLCHAIN_PATH}/lib/libc.a") # Specify the C flags (e.g., optimization, architecture) set(CMAKE_C_FLAGS "-g -DMAKEFILE_BUILD -fno-strict-aliasing -EL -mfloat-abi=hard -mfpu=vfpv3-d16 -mcpu=cortex-r5 -mthumb -march=thumbv7r -DFREERTOS -DSOC_J721E -Dj721e_evm=j721e_evm ${ADDITIONAL_BUILD_OPTS}") set(CMAKE_CXX_FLAGS "-DMAKEFILE_BUILD -fno-strict-aliasing -EL -mfloat-abi=hard -mfpu=vfpv3-d16 -mcpu=cortex-r5 -mthumb -march=thumbv7r -DFREERTOS -DSOC_J721E -Dj721e_evm=j721e_evm ${ADDITIONAL_BUILD_OPTS}") # Set PDK_SOURCE_DIR if(NOT DEFINED PDK_SOURCE_DIR) set(PDK_SOURCE_DIR "$ENV{TI_SDK_PATH}/pdk_jacinto_10_01_00_25") endif() set(SPI_LIB "${CMAKE_SOURCE_DIR}/lib/${BUILD_PROFILE}/wx.spi.aer5f") # Add the include directories for Processor SDK and PDK include_directories( ${PDK_SOURCE_DIR}/packages ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/board/src/ ${CMAKE_SOURCE_DIR}/board/src/j721e_evm/include ${CMAKE_CURRENT_SOURCE_DIR}/src/ ${PDK_SOURCE_DIR}/packages/ti/csl/ ${PDK_SOURCE_DIR}/packages/ti/csl/arch/r5/ ${PDK_SOURCE_DIR}/packages/ti/csl/arch/r5/src/startup/ ${PDK_SOURCE_DIR}/packages/ti/kernel/freertos/config/j721e/r5f/ ) if("${TARGET_CORE}" STREQUAL "mcu2_0" OR "${TARGET_CORE}" STREQUAL "mcu2_1") set(ADDITIONAL_LIBS "${PDK_SOURCE_DIR}/packages/ti/build/j721e/linker_r5_freertos.lds" ) else() message(FATAL_ERROR "Core not yet supported.") endif() # Add the source files set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.c ) # Add the source to the executable add_executable(${PROJECT_NAME} ${SOURCES}) set(GROUPED_LIBS "${PDK_SOURCE_DIR}/packages/ti/csl/lib/j721e/${TARGET_PROCESSOR}/${BUILD_PROFILE}/ti.csl.aer5f" "${PDK_SOURCE_DIR}/packages/ti/drv/uart/lib/j721e/${TARGET_PROCESSOR}/${BUILD_PROFILE}/ti.drv.uart.aer5f" "${PDK_SOURCE_DIR}/packages/ti/drv/i2c/lib/j721e/${TARGET_PROCESSOR}/${BUILD_PROFILE}/ti.drv.i2c.aer5f" "${PDK_SOURCE_DIR}/packages/ti/drv/udma/lib/j721e/${TARGET_CORE}/${BUILD_PROFILE}/udma.aer5f" "${PDK_SOURCE_DIR}/packages/ti/drv/gpio/lib/j721e/${TARGET_PROCESSOR}/${BUILD_PROFILE}/ti.drv.gpio.aer5f" "${PDK_SOURCE_DIR}/packages/ti/drv/pmic/lib/j721e_evm/${TARGET_PROCESSOR}/${BUILD_PROFILE}/pmic.aer5f" "${PDK_SOURCE_DIR}/packages/ti/drv/pm/lib/j721e/${TARGET_PROCESSOR}/${BUILD_PROFILE}/pm_lib.aer5f" "${PDK_SOURCE_DIR}/packages/ti/board/lib/j721e_evm/${TARGET_PROCESSOR}/${BUILD_PROFILE}/ti.board.aer5f" "${PDK_SOURCE_DIR}/packages/ti/drv/sciclient/lib/j721e/${TARGET_CORE}/${BUILD_PROFILE}/sciclient.aer5f" "${PDK_SOURCE_DIR}/packages/ti/osal/lib/freertos/j721e/${TARGET_PROCESSOR}/${BUILD_PROFILE}/ti.osal.aer5f" "${PDK_SOURCE_DIR}/packages/ti/kernel/lib/j721e/${TARGET_CORE}/${BUILD_PROFILE}/ti.kernel.freertos.aer5f" "${PDK_SOURCE_DIR}/packages/ti/csl/lib/j721e/${TARGET_PROCESSOR}/${BUILD_PROFILE}/ti.csl.init.aer5f" "${PDK_SOURCE_DIR}/packages/ti/drv/spi/lib/j721e/r5f/${BUILD_PROFILE}/ti.drv.spi.aer5f" "${LIBC_AR}" ) # Link the necessary libraries (adjust paths to your SDK) target_link_libraries(${PROJECT_NAME} "${ADDITIONAL_LIBS}" $<LINK_GROUP:RESCAN, ${GROUPED_LIBS}> ) # Define the required linker flags (for linking in startup files, etc.) target_link_options(${PROJECT_NAME} PRIVATE -Werror -Wl,-q -Wl,-u,_c_int00 -Wl,--display_error_number -Wl,--use_memcpy=fast -Wl,--use_memset=fast -Wl,--diag_suppress=10063-D -Wl,--diag_suppress=10068-D -Wl,--diag_suppress=10083-D -Wl,-c -mcpu=cortex-r5 -march=armv7-r -Wl,--diag_suppress=10230-D -Wl,-x -Wl,--zero_init=on ) # Set the output directory set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin) # Set the post-build commands (e.g., copy binaries to specific folder) add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${EXECUTABLE_OUTPUT_PATH}/${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/bin/${BUILD_PROFILE}/${PROJECT_NAME}_${TARGET_PROCESSOR}_${TARGET_CORE}.xer5f )
7. Expected behavior: It should transmit the number of bytes that I pass to transaction.count.
8. What does happen: It does not. In this case, it's truncating the message by a byte. Other code elsewhere gets the last five or for longer messages, the last fifteen chopped off.
9. Other boards: I have not yet tested on other boards.
10. Frequency: Happens every time I load a new image.
11. Diagnosis/debugging: I've tried changing the size of the message, truncation happens at any size. Changing the transaction.count does increase it, but if I send a 64 byte message, seems silly to tell it that it really is a 65 byte. In other code, this (the size) isn't always as predictable (sending the entire buffer of 128 bytes resulted in 113 bytes only being sent).
12. Logs, etc.
O-Scope output for this:
SPI3 registers:
521177 13 R MCSPI3_CFG_MCSPI_HL_REV 0x0000000B 0x40301A0B R MCSPI3_CFG_MCSPI_HL_HWINFO 0x0000000B 0x00000009 R MCSPI3_CFG_MCSPI_HL_SYSCONFIG 0x0000000B 0x00000004 R MCSPI3_CFG_MCSPI_REVISION 0x0000000B 0x0000002B R MCSPI3_CFG_MCSPI_SYSCONFIG 0x0000000B 0x00000308 R MCSPI3_CFG_MCSPI_SYSSTATUS 0x0000000B 0x00000001 R MCSPI3_CFG_MCSPI_IRQSTATUS 0x0000000B 0x00000010 R MCSPI3_CFG_MCSPI_IRQENABLE 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_WAKEUPENABLE 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_SYST 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_MODULCTRL 0x0000000B 0x00000001 R MCSPI3_CFG_MCSPI_CHCONF_0 0x0000000B 0x00060000 R MCSPI3_CFG_MCSPI_CHSTAT_0 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_CHCTRL_0 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_TX_0 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_RX_0 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_CHCONF_1 0x0000000B 0x200623D0 R MCSPI3_CFG_MCSPI_CHSTAT_1 0x0000000B 0x00000004 R MCSPI3_CFG_MCSPI_CHCTRL_1 0x0000000B 0x00001401 R MCSPI3_CFG_MCSPI_TX_1 0x0000000B 0x00000034 R MCSPI3_CFG_MCSPI_RX_1 0x0000000B 0xFFFFFFFF R MCSPI3_CFG_MCSPI_CHCONF_2 0x0000000B 0x00060000 R MCSPI3_CFG_MCSPI_CHSTAT_2 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_CHCTRL_2 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_TX_2 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_RX_2 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_CHCONF_3 0x0000000B 0x00060000 R MCSPI3_CFG_MCSPI_CHSTAT_3 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_CHCTRL_3 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_TX_3 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_RX_3 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_XFERLEVEL 0x0000000B 0x00080007 R MCSPI3_CFG_MCSPI_DAFTX 0x0000000B 0x00000000 R MCSPI3_CFG_MCSPI_DAFRX 0x0000000B 0x00000000