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