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. Nothing custom as of yet.
5. Hardware setup: I've been testing with both SPI6 and SPI3 for our purposes, using a SPI simulator (Waveshare) to transmit messages. Let's start with the setup for SPI6: On the GESI Motor Control Header, SPI6_CLK is pin 18, SPI6_D0 is pin 14, SPI6_D1 is pin 36, and SPI6_CS1 is pin 30; the simulator is connected on the CLK, D0, D1, to their counterparts and CS0 to the SPI6_CS1. Occasionally, I will hook up digital oscilloscope to the lines to verify the message is being transmitted.
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.
#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 slaveRxBuffer[128] __attribute__ ((aligned (128))); unsigned char slaveTxBuffer[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 */ 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; } // Print out data received UART_printf("Received data: "); for (uint32_t i = 0; i < transaction->count; i++) { UART_printf("%02X ", ((uint8_t*)transaction->rxBuf)[i]); } UART_printf("\n"); // 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_slave(void *arg0, void *arg1) { UART_printf("Starting SPI Slave test. \n"); TaskP_sleepInMsecs(1000); uint32_t terminateXfer = 1; SPI_init(); // == Set up the SPI test for receive == SPI_Handle spi; SPI_Params spiParams; uint32_t instance = MCSPI6_CONFIG_IDX; uint32_t domain = SPI_MCSPI_DOMAIN_MAIN; MCSPI_socInit(); SPI_HWAttrs spi_cfg; SPI_socGetInitCfg(domain, instance, &spi_cfg); spi_cfg.enableIntr = BTRUE; spi_cfg.edmaHandle = NULL; spi_cfg.dmaMode = BFALSE; spi_cfg.pinMode = SPI_PINMODE_4_PIN; // Can use 3-pin mode for slave /* Set the SPI init configurations */ spi_cfg.chNum = 0; spi_cfg.chnCfg[0].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_1; spi_cfg.chnCfg[0].tcs = MCSPI_CS_TCS_0PNT5_CLK; spi_cfg.chnCfg[0].trMode = MCSPI_RX_ONLY_MODE; spi_cfg.chnCfg[0].enableFIFO = 1; // Enable FIFO for slave /* 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_SLAVE; spiParams.transferMode = 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; } McSPISetSlaveChipSel(spi_cfg.baseAddr, spi_cfg.chNum, 1); // USE CS1 uint32_t xfer_len = 8; //SPI_MSG_LENGTH; Osal_delay(500); // Attempt a transfer uintptr_t addrSlaveTxBuf = (uintptr_t)slaveTxBuffer; uintptr_t addrSlaveRxBuf = (uintptr_t)slaveRxBuffer; bool transferOK = true; memset(slaveRxBuffer, 0, sizeof(slaveRxBuffer)); memset(slaveTxBuffer, 0, sizeof(slaveTxBuffer)); memcpy(slaveTxBuffer, "TEST1234", 8); // Example data for slave TX while (1) { SPI_Transaction transaction; transaction.count = xfer_len; transaction.arg = (void *)&terminateXfer; transaction.txBuf = (void *)addrSlaveTxBuf; transaction.rxBuf = (void *)addrSlaveRxBuf; // UART_printf("Transferring...\n"); transferOK = SPI_transfer((SPI_Handle)spi, &transaction); if (!transferOK) { UART_printf("Error in SPI transfer\n"); } else { if (SPI_osalPendLock(cbSem[0], SemaphoreP_WAIT_FOREVER) != SemaphoreP_OK) { UART_printf("Error in SPI transfer - osalPendLock\n"); } } } } /* * ======== 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_slave, &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); //-- Enable this for MCSPI3 usage // UART_printf("Unlocking MCU_MCSPI1 from MCSPI3\n"); // /* Unlock lock key registers for MCU 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 */ // /* MCU_CTRL_MMR0.CTRLMMR_MCU_SPI1_CTRL.SPI1_LINKDIS */ // 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); // UART_printf("Unlocking CLK to MCSPI3.\n"); // /* Unlock lock key registers for MAIN Partition 2 */ // /* write Partition Lock Key 0 Register */ // CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_LOCK2_KICK0, 0x68EF3490); // /* write Partition Lock Key 1 Register */ // CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_LOCK2_KICK1, 0xD172BC5A); // /* Check for unlock */ // regVal = CSL_REG32_RD(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_LOCK2_KICK0); // while ((regVal & 0x1) != 0x1U) // { // regVal = CSL_REG32_RD(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_LOCK2_KICK0); // } // /* Set CTRLMMR_SPI3_CLKSEL */ // // 0x0010819C // CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_SPI3_CLKSEL, 0x10000); // CSL_REG32_WR(CSL_CTRL_MMR0_CFG0_BASE + CSL_MAIN_CTRL_MMR_CFG0_SPI6_CLKSEL, 0x10000); UART_printf("Done.\n"); // 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(spirx 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" # "${CMAKE_SOURCE_DIR}/../../lib/${BUILD_PROFILE}/j721e_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" # "${CMAKE_SOURCE_DIR}/../../lib/${BUILD_PROFILE}/wx.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 )
Some things of note in these:
- SPI6 is being used
- Interrupts are enabled; callback mode.
- I've tried both 3-pin mode and 4-pin mode; but currently I have 4-pin mode working again
- In order to get it working with CS1, McSPISetSlaveChipSel() is used to set the SPIENSLV register to the appropriate value.
- Channel 0 is being used, since TRM states that this is the only channel supported for RX
- dataLineCommMode is 1.
- dataSize is 8 bits, initial transfer length is 8 bytes.
- There's stuff also being done with a TxBuffer, which only comes into play if we're using TXRX mode
- Added some code to enable GESI board pinmuxing
- Optionally have some calls to disconnect MCSPI3 from MCU_SPI1 if we're using that SPI; don't need to get into that for this, as I think I have that figured out.
- All build options are pulled from the .mk files in the PDK.
- FIFO is being used.
7/8: Expected behavior/What is happening instead: I send a string of bytes from the simulator via SPI that is longer than 8 bytes. For example:
b'\x00\x00\x00\x00~\x10\xc1\x90\xa00\x98\x90\x0c\xd0\xa0\x00\x80\xb9\xe7~\x00\x00\x00\x00\x00\x00~\x10\xc1\x90\xa0\xb0\x98\x08th\xc0\x00\x80wR~\x00\x00\x00\x00\x00\x00\x00~\x10\xc1\x90\xa0p\x98\xd0\x18\x84\x80\x00\x80\x91w~\x00\x00\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
I would expect to get the entire byte string, but I do not. Currently with the attached code, I only get the first 8 bytes:
Starting SPI Slave test. The interrupt path has been set with interrupt number 384 SPI callback data size: 8 Received data: 00 00 00 00 7e 10 c1 90
I see that the callback does get called. However, for subsequent transmits, the callback doesn't get called, meaning there is no interrupt? I would expect that the entire first message gets through in 8-byte clumps, and subsequently any messages sent after that would also be sent.
9. Other boards: I have tested similar code on a TVA4VM EVM board, which seemed to work just fine--I was using SPI5 at the time and that board has a CS0 on it's main header.
10. Every boot: Yes, this happens every boot.
11. Diagnosis/Debug:
- 3-PIN vs. 4-PIN: With CS0 not available on the board, it seemed like the best way to go with what we were trying to do was to try 3-pin; initially, this helped us with getting some of the message through, but upon discovery of the SPIENSLV register, we were able to get CS1 to be the used chip select for 4-pin mode. Either way, we're observing the same thing: early-terminated messages and not receiving any after the first.
- FIFO enabled vs. disabled: Interestingly, if we disable FIFO usage, we get every interrupt, but none of the data gets through (all 0's). With FIFO enabled, only first 8 bytes as seen in the snippet above.
- Blocking (polling) vs. Callback: I've altered the attached code slightly to use blocking mode (don't use interrupt, etc.) and in that polling mode, it seems like I'm getting the entire message--which is a workaround, but I don't see it as a solution.
- Changing the transaction count: If I change this to 16, I get the first 16 bytes, 128 yields 128 bytes; however, the size of the incoming message is not going to be that predictable.
- Bitrate: Changing this to a faster bitrate does nothing.
- TX only vs. TX_RX mode: Not much of a difference here. I'm seeing the first message received, and on the simulator side, I get the first message and the contents of the second message; but on the J721e side, only the first message is received and the callback is never called again (no interrupt), so nothing else is sent.
- DMA vs no DMA: No observable differences. Not planning on using the DMA anyway.
12: Logs/etc.
No logs really, but I do have a register dump for the MCSPI6:
521177 13 R MCSPI6_CFG_MCSPI_HL_REV 0x0000000B 0x40301A0B R MCSPI6_CFG_MCSPI_HL_HWINFO 0x0000000B 0x00000009 R MCSPI6_CFG_MCSPI_HL_SYSCONFIG 0x0000000B 0x00000004 R MCSPI6_CFG_MCSPI_REVISION 0x0000000B 0x0000002B R MCSPI6_CFG_MCSPI_SYSCONFIG 0x0000000B 0x00000308 R MCSPI6_CFG_MCSPI_SYSSTATUS 0x0000000B 0x00000001 R MCSPI6_CFG_MCSPI_IRQSTATUS 0x0000000B 0x00010008 R MCSPI6_CFG_MCSPI_IRQENABLE 0x0000000B 0x00000004 R MCSPI6_CFG_MCSPI_WAKEUPENABLE 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_SYST 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_MODULCTRL 0x0000000B 0x00000004 R MCSPI6_CFG_MCSPI_CHCONF_0 0x0000000B 0x302113D0 R MCSPI6_CFG_MCSPI_CHSTAT_0 0x0000000B 0x00000043 R MCSPI6_CFG_MCSPI_CHCTRL_0 0x0000000B 0x00001401 R MCSPI6_CFG_MCSPI_TX_0 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_RX_0 0x0000000B 0x000000A0 R MCSPI6_CFG_MCSPI_CHCONF_1 0x0000000B 0x00060000 R MCSPI6_CFG_MCSPI_CHSTAT_1 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_CHCTRL_1 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_TX_1 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_RX_1 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_CHCONF_2 0x0000000B 0x00060000 R MCSPI6_CFG_MCSPI_CHSTAT_2 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_CHCTRL_2 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_TX_2 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_RX_2 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_CHCONF_3 0x0000000B 0x00060000 R MCSPI6_CFG_MCSPI_CHSTAT_3 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_CHCTRL_3 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_TX_3 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_RX_3 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_XFERLEVEL 0x0000000B 0x00080700 R MCSPI6_CFG_MCSPI_DAFTX 0x0000000B 0x00000000 R MCSPI6_CFG_MCSPI_DAFRX 0x0000000B 0x00000000
In summary: I expect repeated interrupts for long messages and reoccurring interrupts for subsequent messages, but I'm not seeing that happen. Is this a limitation of the EVM+GESI board we are using? Am I making a bad assumption in my code on how the SPI works?