Part Number: AM3358
Other Parts Discussed in Thread: SYSBIOS
(void)UART_osalPendLock(uart_stdio.sem, SemaphoreP_WAIT_FOREVER) crash when I use UART_printf. Thanks
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.
Hi Anping,
Can you please provide more details so that I can better assist you?
Thanks and regards,
Frank
Hi Frank
It happen on my beaglebone black. I use pdk_am335x_1_0_16. It occur in my own software.
/*
* ======== main.c ========
*/
#include "environment.h"
//#include "test_OSLayer.h"
/*
* ======== taskFxn ========
*/
Void taskFxn(UArg a0, UArg a1)
{
System_printf("enter taskFxn()\n");
Task_sleep(10);
UART_printf("\ntest_RTOS!\n");
// test_RTOS();
// test_TIMER();
// test_UART();
// test_SPI();
UART_init();
UART_HwAttrs uart_cfg;
/* Get the default UART init configurations */
UART_socGetInitCfg(BOARD_UART_INSTANCE, &uart_cfg);
uart_cfg.edmaHandle = NULL;
uart_cfg.dmaMode = FALSE;
uart_cfg.loopback = FALSE;
/* Set the DMA enabled UART init configurations */
UART_socSetInitCfg(BOARD_UART_INSTANCE, &uart_cfg);
UART_Params uartParams;
UART_Params_init(&uartParams);
UART_Handle uart = UART_open(BOARD_UART_INSTANCE, &uartParams);
if (uart == NULL)
{
UART_printf("\nBAE_UART_open() fail!\n");
}
System_printf("exit taskFxn()\n");
System_flush(); /* force SysMin output to console */
}
/*
* ======== main ========
*/
Int main()
{
Task_Handle task;
Error_Block eb;
System_printf("enter main()\n");
Error_init(&eb);
task = Task_create(taskFxn, NULL, &eb);
if (task == NULL) {
System_printf("Task_create() failed!\n");
BIOS_exit(0);
}
BIOS_start(); /* does not return */
return(0);
}
Hi Frank
/*
* ======== taskFxn ========
*/
Void taskFxn(UArg a0, UArg a1)
{
System_printf("enter taskFxn()\n");
Task_sleep(10);
UART_printf("\ntest_RTOS!\n");->(void)UART_osalPendLock(uart_stdio.sem, SemaphoreP_WAIT_FOREVER) crash
.....
}
Anping,
Have you stepped into the UART_printf() function to see what causes the crash?
Regards,
Frank
Hi Frank
UART_printf crash! When I step in it, (void)UART_osalPendLock(uart_stdio.sem, SemaphoreP_WAIT_FOREVER) crash. Thanks
Anping,
Have you tried stepping into UART_osalPendLock()? For this you may be useful to build the OSAL debug library & link this into your application.
To build the OSAL debug library :
> cd <PDK root>\packages
> pdksetupenv.bat
> gmake osal_lib LIMIT_SOCS="am335x" LIMIT_BOARDS="bbbAM335x" LIMIT_CORES="a8host" BUILD_PROFILE="debug"
To link the OSAL debug library into your application, add this to your .cfg file:
Osal.libProfile = "debug";
Regards,
Frank
Anping,
From <PDK>/packages/ti:
$ grep -rI -n -i --regexp="UART_osalPendLock" drv/uart
drv/uart/src/UART_osal.h:85:#define UART_osalPendLock(X,Y) (SemaphoreP_pend((X),(Y)))
$ grep -rI -n -i --regexp="SemaphoreP_pend" --include "*.c" osal
osal/src/tirtos/SemaphoreP_tirtos.c:218: * ======== SemaphoreP_pend ========
osal/src/tirtos/SemaphoreP_tirtos.c:220:SemaphoreP_Status SemaphoreP_pend(SemaphoreP_Handle handle, uint32_t timeout)
So UART_osalPendLock is actually an OSAL function.
Regards,
Frank
Hi Frank
Our company policy don't allow me to share my code. So I use your example project MCSPI_SlaveMode_MasterExample_bbbAM335x_armExampleProject to repeat UART_printf crash!
1) replace line 1505
for (i = 0; ; i++)
by
for (i = 3; ; i++)
2) add UART_printf("\n SPI_osalPendLock!\n"); at line 837 like the following
if(transferOK)
{
if (cbMode)
{
if (SPI_osalPendLock(cbSem[0], timeout) != SemaphoreP_OK)
{
goto Err;
}
UART_printf("\n SPI_osalPendLock!\n");
}
3) add three lines at line 475 as the following
/* Callback mode functions */
void SPI_callback(SPI_Handle handle, SPI_Transaction *transaction)
{
UART_printf("\nSPI_callback!\n");
memcpy((void *)&local_data[0], transaction->rxBuf, transaction->count);
local_data_length = (uint32_t)transaction->count;
SPI_osalPostLock(cbSem[0]);
}
4) add two lines at 403
int local_data[32];
uint32_t local_data_length;
5)compile and run. it will crash at line 837
UART_printf("\n SPI_osalPendLock!\n");
Thanks
Anping,
Just to be sure I understand:
You can share information about the base code you used as a starting point, and about the modifications you made to the code, but you can't share any files containing your modifications?
Can you please confirm my understanding? If I understand this correctly, then I can try to reproduce the issue.
Thanks,
Frank
Hi Frank
My test project base on your McSPI and UART example projects. Your projects run on my Beaglebone Black without issue. My test project UART_printf crash. So I go back your example project and change SPI_callback to my test project one. I can repeat UART_printf crash. If I don't use callback, UART_printf works fine. Thanks
Hi Frank
My test project test the functionality which our application use. I do my best to fix my issue by following company policy. It look stupid, but please understand. After my test project pass, company can go ahead and put the order. Thanks
Anping,
I tried to reproduce the UART_printf() crash, but was unable to do so.
I generated the OOB example for PDK 1.0.15 as follows:
> cd R:\pdk_am335x_1_0_15\packages
> pdkprojectcreate AM335x bbbAM335x little spi all arm
For my .ccxml file, I have the following:
I have these hardware connections:
To build the example project:
To execute the code:
I see some tests fail, but I don't have two BBB's connected which is required for proper operation of all the tests.
I see the same log output for both the original OOB example and the code which I modified according to your instructions. I've attached the original (main_mcspi_slave_mode_org.c) and modified (main_mcspi_slave_mode.c) main example code source file. Please compare these files to see if I've correctly applied your modifications. BTW I noticed the line numbers you provided in your previous post don't match those in the original source file, so I'm not sure what code you're using.
Regards,
Frank
U-Boot SPL 2016.03-00001-gd12d09f (Mar 17 2016 - 16:16:15)
Trying to boot from MMC
bad magic
U-Boot 2016.03-00001-gd12d09f (Mar 17 2016 - 16:16:15 -0500), Build: jenkins-github_Bootloader-Builder-351
Watchdog enabled
I2C: ready
DRAM: 512 MiB
Reset Source: IcePick reset has occurred.
Reset Source: Power-on reset has occurred.
MMC: OMAP SD/MMC: 0, OMAP SD/MMC: 1
Using default environment
Net: <ethaddr> not set. Validating first E-fuse MAC
cpsw, usb_ether
Press SPACE to abort autoboot in 2 seconds
=>
CortxA8: Output: **** AM335x BeagleBlack Initialization is in progress .......... CortxA8: Output: **** AM335x ALL PLL Config for OPP == OPP100 is in progress ......... CortxA8: Output: Input Clock Read from SYSBOOT[15:14]: 24MHz CortxA8: Output: **** Going to Bypass... CortxA8: Output: **** Bypassed, changing values... CortxA8: Output: **** Locking ARM PLL CortxA8: Output: **** Core Bypassed CortxA8: Output: **** Now locking Core... CortxA8: Output: **** Core locked CortxA8: Output: **** DDR DPLL Bypassed CortxA8: Output: **** DDR DPLL Locked CortxA8: Output: **** PER DPLL Bypassed CortxA8: Output: **** PER DPLL Locked CortxA8: Output: **** DISP PLL Config is in progress .......... CortxA8: Output: **** DISP PLL Config is DONE .......... CortxA8: Output: **** AM335x ALL ADPLL Config for OPP == OPP100 is Done ......... CortxA8: Output: **** AM335x DDR3 EMIF and PHY configuration is in progress......... CortxA8: Output: EMIF PRCM is in progress ....... CortxA8: Output: EMIF PRCM Done CortxA8: Output: DDR PHY Configuration in progress CortxA8: Output: Waiting for VTP Ready ....... CortxA8: Output: VTP is Ready! CortxA8: Output: DDR PHY CMD0 Register configuration is in progress ....... CortxA8: Output: DDR PHY CMD1 Register configuration is in progress ....... CortxA8: Output: DDR PHY CMD2 Register configuration is in progress ....... CortxA8: Output: DDR PHY DATA0 Register configuration is in progress ....... CortxA8: Output: DDR PHY DATA1 Register configuration is in progress ....... CortxA8: Output: Setting IO control registers....... CortxA8: Output: EMIF Timing register configuration is in progress ....... CortxA8: Output: EMIF Timing register configuration is done ....... CortxA8: Output: PHY is READY!! CortxA8: Output: DDR PHY Configuration done CortxA8: Output: **** AM335x BeagleBlack Initialization is Done ******************
SPI UT 12 SPI master transfer error test in non-dma interrupt mode SPI master transfer error test in non-dma interrupt mode have passed SPI UT 13 SPI master phase polarity test in non-dma interrupt mode SPI initialized SPI master phase polarity test in non-dma interrupt mode have failed Some tests have failed. Done
/**
* \file main_mcspi_slave_mode.c
*
* \brief The application Demonstrate the MCSPI slave mode functionality.
* This application transmits data from master to slave and at the
* same instance data from slave will be 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:
* MasterSPI_SCLK----SlaveSPI_SCLK
* MasterSPI_D0------SlaveSPI_D1
* MasterSPI_D1------SlaveSPI_D0
* MasterSPI_CS------SlaveSPI_CS
*
* \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:
* SPI initialized
* Slave: PASS: Txd from master SPI
*
* At master end console:
* SPI initialized
* Master: PASS: Txd from slave SPI
* Done
*/
/*
* Copyright (C) 2016 - 2019 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>
#ifdef USE_BIOS
/* XDCtools Header files */
#include <xdc/std.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>
#endif /* #ifdef USE_BIOS */
/* 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/spi/soc/SPI_soc.h>
#include <ti/drv/spi/src/SPI_osal.h>
#include <ti/drv/spi/SPI.h>
#include "SPI_log.h"
#if defined(iceAMIC110)
#include <ti/drv/gpio/GPIO.h>
#include <ti/drv/gpio/soc/GPIO_soc.h>
#endif
#include <ti/board/board.h>
#ifdef SOC_AM65XX
#include <ti/csl/soc/am65xx/src/cslr_soc_baseaddress.h>
#include <ti/csl/soc/am65xx/src/cslr_wkup_ctrl_mmr.h>
#elif defined(SOC_J721E)
#include <ti/csl/soc/j721e/src/cslr_soc_baseaddress.h>
#include <ti/csl/soc/j721e/src/cslr_wkup_ctrl_mmr.h>
#endif
#ifdef SPI_DMA_ENABLE
#include <ti/osal/CacheP.h>
#if defined (SOC_AM65XX) || defined(SOC_J721E)
#include <ti/drv/udma/udma.h>
#else
/* EDMA3 Header files */
#include <ti/sdo/edma3/drv/edma3_drv.h>
#include <ti/sdo/edma3/rm/edma3_rm.h>
#include <ti/sdo/edma3/rm/sample/bios6_edma3_rm_sample.h>
#if defined(evmK2G)
#include <ti/csl/soc.h>
#endif
static EDMA3_RM_Handle MCSPIApp_edmaInit(void);
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || \
defined(SOC_C6678) || defined(SOC_C6657)
extern EDMA3_RM_InstanceInitConfig sampleInstInitConfig[][EDMA3_MAX_REGIONS];
extern EDMA3_RM_GblConfigParams sampleEdma3GblCfgParams[];
#endif
#endif
#endif
/* Define the SPI test interface */
typedef struct SPI_Tests_s
{
bool (*testFunc)(void *);
int32_t testId;
bool master;
bool pollMode;
bool cbMode;
bool dmaMode;
uint32_t timeout;
char testDesc[80];
uint32_t param;
uint32_t trigLvl;
} SPI_Tests;
/**********************************************************************
************************** Macros ************************************
**********************************************************************/
#define SPI_TIMEOUT_VALUE 5000
/* SPI transfer message definitions */
#define SPI_MSG_LENGTH 26
#define SPI_MSG_LENGTH2 78
#define SPI_NUM_XFERS 2
uint32_t spi_test_xfer_len[SPI_NUM_XFERS] =
{
SPI_MSG_LENGTH,
SPI_MSG_LENGTH2
};
/* Maximum # of channels per SPI instance */
#define MCSPI_MAX_NUM_CHN 4
/* Test channel # */
#define MCSPI_TEST_CHN 0
/* SPI Test definitions */
/* Unit test IDs */
#define SPI_TEST_ID_DMA 0 /* Single-channel DMA mode test */
#define SPI_TEST_ID_INT 1 /* Single-channel interrupt mode test */
#define SPI_TEST_ID_POLL 2 /* Single-channel polling mode test */
#define SPI_TEST_ID_CB 3 /* Single-channel non-DMA callback mode test */
#define SPI_TEST_ID_DMA_CB 4 /* Single-channel DMA callback mode test */
#define SPI_TEST_ID_MC_DMA 5 /* Multi-channel DMA mode test */
#define SPI_TEST_ID_MC_INT 6 /* Multi-channel interrupt mode test */
#define SPI_TEST_ID_MC_POLL 7 /* Multie-channel polling mode test */
#define SPI_TEST_ID_MC_CB 8 /* Multi-channel non-DMA callback mode test */
#define SPI_TEST_ID_MC_DMA_CB 9 /* Multi-channel DMA callback mode test */
#define SPI_TEST_ID_TX_ONLY 10 /* Multi-channel TX only test */
#define SPI_TEST_ID_RX_ONLY 11 /* Multi-channel RX only test */
#define SPI_TEST_ID_XFER_ERR 12 /* Single-channel transfer error test */
#define SPI_TEST_ID_PHA_POL 13 /* Single-channel phase/polarity test */
#define SPI_TEST_ID_TIMEOUT 14 /* Single-channel Timeout test with interrupt enabled */
#define SPI_TEST_ID_TIMEOUT_POLL 15 /* Single-channel Timeout test with polling enabled */
/* Loopback tests */
#define SPI_TEST_ID_LOOPBACK 20
#define SPI_TEST_ID_WORD_LEN (SPI_TEST_ID_LOOPBACK) /* transfer data size test */
#define SPI_TEST_ID_TRIG_LVL (SPI_TEST_ID_LOOPBACK + 1) /* FIFO trigger level test */
#define SPI_TEST_ID_TCS (SPI_TEST_ID_LOOPBACK + 2) /* Multi-channel chip select time control test */
#define SPI_TEST_ID_INIT_DELAY (SPI_TEST_ID_LOOPBACK + 3) /* Multi-channel 1st transfer init delay test */
/* Transfer data size test parameter, in # of bits per SPI word */
#define SPI_TEST_DATA_SIZE_16 16
#define SPI_TEST_DATA_SIZE_32 32
#if defined(SOC_DRA78x) || defined(SOC_TDA3XX) || defined(SOC_TDA2XX) || defined(SOC_TDA2EX) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined(SOC_AM574x) || defined (SOC_AM572x) || defined (SOC_AM571x) || defined (SOC_AM437x) || defined (SOC_AM335x) || defined (SOC_AM65XX) || defined(SOC_J721E)
#define SPI_TEST_DATA_SIZE SPI_TEST_DATA_SIZE_32
#else
#define SPI_TEST_DATA_SIZE SPI_TEST_DATA_SIZE_16
#endif
#ifdef MCSPI_MULT_CHANNEL
/* Chip select time control test parameter */
#define SPI_TEST_TCS MCSPI_CH0CONF_TCS0_ONECYCLEDLY
/* 1st transfer init delay test parameter */
#define SPI_TEST_INIT_DELAY MCSPI_INITDLY_4
/* FIFO trigger level test parameter, in # of bytes */
#define SPI_TEST_TRIG_LVL 16
#endif
#if defined(SOC_AM65XX) || defined(SOC_J721E)
/* WKUP CTRL base address + offset to beginning of PAD CONFIG section */
#define WKUP_PINMUX_REG_BASE (CSL_WKUP_CTRL_MMR0_CFG0_BASE + \
CSL_WKUP_CTRL_MMR_CFG0_PADCONFIG0)
#define MCU_SPI0_CLK_PADCFG_OFFSET (0x90U)
#define MCU_SPI0_D1_PADCFG_OFFSET (0x98U)
#define PIN_MODE(mode) (mode)
/** \brief Active mode configurations */
/** \brief Resistor disable */
#define PIN_PULL_DISABLE (0x1U << 16U)
/** \brief Pull direction */
#define PIN_PULL_DIRECTION (0x1U << 17U)
/** \brief Receiver enable */
#define PIN_INPUT_ENABLE (0x1U << 18U)
/** \brief Driver disable */
#define PIN_OUTPUT_DISABLE (0x1U << 21U)
/** \brief Wakeup enable */
#define PIN_WAKEUP_ENABLE (0x1U << 29U)
#ifdef SPI_DMA_ENABLE
/*
* Ring parameters
*/
/** \brief Number of ring entries - we can prime this much memcpy operations */
#define UDMA_TEST_APP_RING_ENTRIES (1U)
/** \brief Size (in bytes) of each ring entry (Size of pointer - 64-bit) */
#define UDMA_TEST_APP_RING_ENTRY_SIZE (sizeof(uint64_t))
/** \brief Total ring memory */
#define UDMA_TEST_APP_RING_MEM_SIZE (UDMA_TEST_APP_RING_ENTRIES * \
UDMA_TEST_APP_RING_ENTRY_SIZE)
/**
* \brief UDMA host mode buffer descriptor memory size.
* Make it multiple of 128 byte alignment
*/
#define UDMA_TEST_APP_DESC_SIZE (sizeof(CSL_UdmapCppi5HMPD) + (128U - sizeof(CSL_UdmapCppi5HMPD)))
/*
* UDMA driver objects
*/
struct Udma_DrvObj gUdmaDrvObj;
struct Udma_ChObj gUdmaTxChObj;
struct Udma_ChObj gUdmaRxChObj;
struct Udma_EventObj gUdmaTxCqEventObj;
struct Udma_EventObj gUdmaRxCqEventObj;
Udma_DrvHandle gDrvHandle = NULL;
/*
* UDMA Memories
*/
static uint8_t gTxRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gTxCompRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gUdmaTxHpdMem[UDMA_TEST_APP_DESC_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gRxRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gRxCompRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gUdmaRxHpdMem[UDMA_TEST_APP_DESC_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static SPI_dmaInfo gUdmaInfo;
Udma_DrvHandle MCSPIApp_udmaInit(SPI_v1_HWAttrs *cfg)
{
int32_t retVal = UDMA_SOK;
Udma_InitPrms initPrms;
uint32_t instId;
if (gDrvHandle == NULL)
{
/* UDMA driver init */
#if defined (__aarch64__)
instId = UDMA_INST_ID_MAIN_0;
#else
instId = UDMA_INST_ID_MCU_0;
#endif
UdmaInitPrms_init(instId, &initPrms);
retVal = Udma_init(&gUdmaDrvObj, &initPrms);
if(UDMA_SOK == retVal)
{
gDrvHandle = &gUdmaDrvObj;
}
}
if(gDrvHandle != NULL)
{
gDrvHandle = &gUdmaDrvObj;
gUdmaInfo.txChHandle = (void *)&gUdmaTxChObj;
gUdmaInfo.rxChHandle = (void *)&gUdmaRxChObj;
gUdmaInfo.txRingMem = (void *)&gTxRingMem[0];
gUdmaInfo.cqTxRingMem = (void *)&gTxCompRingMem[0];
gUdmaInfo.rxRingMem = (void *)&gRxRingMem[0];
gUdmaInfo.cqRxRingMem = (void *)&gRxCompRingMem[0];
gUdmaInfo.txHpdMem = (void *)&gUdmaTxHpdMem[0];
gUdmaInfo.rxHpdMem = (void *)&gUdmaRxHpdMem[0];
gUdmaInfo.txEventHandle = (void *)&gUdmaTxCqEventObj;
gUdmaInfo.rxEventHandle = (void *)&gUdmaRxCqEventObj;
cfg->dmaInfo = &gUdmaInfo;
}
return (gDrvHandle);
}
int32_t MCSPI_udma_deinit(void)
{
int32_t retVal = UDMA_SOK;
if (gDrvHandle != NULL)
{
retVal = Udma_deinit(gDrvHandle);
if(UDMA_SOK == retVal)
{
gDrvHandle = NULL;
}
}
return (retVal);
}
#endif
#endif /* #if defined(SOC_AM65XX) || defined(SOC_J721E) */
/**********************************************************************
************************** Global Variables **************************
**********************************************************************/
#if (defined(_TMS320C6X) || defined (__TI_ARM_V7M4__))
#pragma DATA_ALIGN (masterRxBuffer, 128)
unsigned char masterRxBuffer[128];
#pragma DATA_ALIGN (slaveRxBuffer, 128)
unsigned char slaveRxBuffer[128];
#else
unsigned char masterRxBuffer[128] __attribute__ ((aligned (128)));
unsigned char slaveRxBuffer[128] __attribute__ ((aligned (128)));
#endif
unsigned char masterTxBuffer[128] = "PASS: Txd from master SPI PASS: Txd from master SPI PASS: Txd from master SPI ";
unsigned char slaveTxBuffer[128] = "PASS: Txd from slave SPI PASS: Txd from slave SPI PASS: Txd from slave SPI ";
#if defined(iceAMIC110)
#define GPIO_BUS_SWITCH_ENABLE_OFFSET (0)
#define GPIO_PIN_VAL_LOW (0U)
#define GPIO_PIN_VAL_HIGH (1U)
#define GPIO_BUS_SWITCH_ENABLE_PIN_NUM (0x15)
#define GPIO_BUS_SWITCH_ENABLE_PORT_NUM (0x2)
/* GPIO Driver board specific pin configuration structure */
GPIO_PinConfig gpioPinConfigs[] = {
/* Boot switch enable pin to control the buffer for routing McSPI
* lines to Launchpad header on iceAMIC110 board */
GPIO_DEVICE_CONFIG((GPIO_BUS_SWITCH_ENABLE_PORT_NUM + 1), GPIO_BUS_SWITCH_ENABLE_PIN_NUM) |
GPIO_CFG_IN_INT_NONE | GPIO_CFG_OUTPUT,
};
/* GPIO Driver call back functions */
GPIO_CallbackFxn gpioCallbackFunctions[] = {
NULL
};
/* GPIO Driver configuration structure */
GPIO_v1_Config GPIO_v1_config = {
gpioPinConfigs,
gpioCallbackFunctions,
sizeof(gpioPinConfigs) / sizeof(GPIO_PinConfig),
sizeof(gpioCallbackFunctions) / sizeof(GPIO_CallbackFxn),
0x1U,
};
#endif /* #if defined(iceAMIC110) */
/* Transaction data */
SPI_Transaction transaction;
/* Callback mode variables */
SemaphoreP_Params cbSemParams;
SemaphoreP_Handle cbSem[MCSPI_MAX_NUM_CHN] = {NULL, NULL, NULL, NULL};
bool evmAM570x = false;
#ifdef SPI_DMA_ENABLE
#if !(defined (SOC_AM65XX) || defined(SOC_J721E))
EDMA3_RM_Handle gEdmaHandle = NULL;
/**
* \brief Function to initialize the edma driver and get the handle to the
* edma driver;
*/
static EDMA3_RM_Handle MCSPIApp_edmaInit(void)
{
EDMA3_DRV_Result edmaResult = EDMA3_DRV_E_INVALID_PARAM;
uint32_t edma3Id;
if (gEdmaHandle != NULL)
{
return (gEdmaHandle);
}
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || \
defined(SOC_C6678) || defined(SOC_C6657)
uint32_t edmaEvent[2], i, chnMapping, chnMappingIdx;
/* For Keystone devices, edm3Id is SPI instance and SoC specific */
SPI_getEdmaInfo(BOARD_MCSPI_MASTER_INSTANCE - 1, &edma3Id, edmaEvent);
/* Set the RX/TX ownDmaChannels and dmaChannelHwEvtMap */
for (i = 0; i < 2; i++)
{
chnMapping = edmaEvent[i];
if (chnMapping < 32)
chnMappingIdx = 0;
else
{
chnMapping -= 32;
chnMappingIdx = 1;
}
sampleInstInitConfig[edma3Id][0].ownDmaChannels[chnMappingIdx] |= (1 << chnMapping);
sampleInstInitConfig[edma3Id][0].ownTccs[chnMappingIdx] |= (1 << chnMapping);
sampleInstInitConfig[edma3Id][0].ownPaRAMSets[chnMappingIdx] |= (1 << chnMapping);
sampleEdma3GblCfgParams[edma3Id].dmaChannelHwEvtMap[chnMappingIdx] |= (1 << chnMapping);
}
#endif
#if defined(SOC_AM574x) || defined(SOC_AM572x)|| defined(SOC_AM571x) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined (SOC_DRA78x) || defined (SOC_AM335x) || defined (SOC_AM437x)
edma3Id = 0;
#endif
gEdmaHandle = (EDMA3_RM_Handle)edma3init(edma3Id, &edmaResult);
#ifdef USE_BIOS
if (edmaResult != EDMA3_DRV_SOK)
{
/* Report EDMA Error */
System_printf("\nEDMA driver initialization FAIL\n");
}
else
{
System_printf("\nEDMA driver initialization PASS.\n");
}
#endif
return(gEdmaHandle);
}
#endif
#endif
/* Callback mode functions */
void SPI_callback(SPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[0]);
}
#ifdef MCSPI_MULT_CHANNEL
void MCSPI_callback0(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[0]);
}
void MCSPI_callback1(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[1]);
}
void MCSPI_callback2(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[2]);
}
void MCSPI_callback3(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[3]);
}
#endif
#ifdef MCSPI_MULT_CHANNEL
/*
* ======== SPI init config ========
*/
static void SPI_initConfigDefault(SPI_HWAttrs *cfg, uint32_t chn)
{
cfg->chNum = chn;
cfg->chnCfg[chn].tcs = MCSPI_CS_TCS_0PNT5_CLK;
cfg->chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_6;
cfg->chnCfg[chn].trMode = MCSPI_TX_RX_MODE;
cfg->initDelay = MCSPI_INITDLY_0;
#if defined (SOC_AM335x)
cfg->rxTrigLvl = MCSPI_RX_TX_FIFO_SIZE / 2;
cfg->txTrigLvl = MCSPI_RX_TX_FIFO_SIZE / 2;
#else
cfg->rxTrigLvl = MCSPI_RX_TX_FIFO_SIZE;
cfg->txTrigLvl = MCSPI_RX_TX_FIFO_SIZE;
#endif
}
#endif
/*
* ======== SPI init config ========
*/
static void SPI_initConfig(uint32_t instance, SPI_Tests *test, uint32_t chn, bool multiChn)
{
SPI_HWAttrs spi_cfg;
int32_t testId = test->testId;
bool pollMode = test->pollMode;
#ifdef SPI_DMA_ENABLE
bool dmaMode = test->dmaMode;
#endif
/* Get the default SPI init configurations */
SPI_socGetInitCfg(instance, &spi_cfg);
#ifdef MCSPI_MULT_CHANNEL
SPI_initConfigDefault(&spi_cfg, chn);
#endif
/*
* Set blocking mode (dma mode or non-dma interrupt mode)
* or callback mode
*/
if (pollMode == true)
{
/* polling mode */
spi_cfg.enableIntr = false;
/* SPI DMA mode is not supported in polling mode */
spi_cfg.edmaHandle = NULL;
spi_cfg.dmaMode = FALSE;
}
else
{
/* interrupt enabled */
spi_cfg.enableIntr = true;
#if defined(SOC_DRA78x) || defined(SOC_TDA3XX) || defined(SOC_TDA2XX) || defined(SOC_TDA2PX) || defined(SOC_TDA2EX) || defined (SOC_DRA75x) || \
defined(SOC_AM574x) || defined (SOC_AM572x) || defined (SOC_AM571x) || defined (SOC_AM437x) || defined (SOC_AM335x) || \
defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || \
defined(SOC_C6678) || defined(SOC_C6657) || defined (SOC_AM65XX) || defined(SOC_J721E)
#ifdef SPI_DMA_ENABLE
if (dmaMode == true)
{
/* Set the DMA related init config */
#if defined (SOC_AM65XX) || defined(SOC_J721E)
spi_cfg.edmaHandle = (void *)MCSPIApp_udmaInit(&spi_cfg);
#else
spi_cfg.edmaHandle = MCSPIApp_edmaInit();
#endif
spi_cfg.dmaMode = TRUE;
spi_cfg.enableIntr = FALSE;
}
else
#endif
{
spi_cfg.edmaHandle = NULL;
spi_cfg.dmaMode = FALSE;
}
#endif
}
#ifdef MCSPI_MULT_CHANNEL
switch(testId)
{
case (SPI_TEST_ID_TX_ONLY):
spi_cfg.chnCfg[chn].trMode = MCSPI_TX_ONLY_MODE;
/* Data line 0 TX enabled, data line 1 RX enabled TX disabled */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_6;
break;
case (SPI_TEST_ID_RX_ONLY):
spi_cfg.chnCfg[chn].trMode = MCSPI_RX_ONLY_MODE;
/* Data line 0 TX disabled, data line 1 RX enabled TX disabled */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_7;
break;
case (SPI_TEST_ID_TRIG_LVL):
spi_cfg.rxTrigLvl = test->param;
spi_cfg.txTrigLvl = test->param;
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
break;
case (SPI_TEST_ID_TCS):
spi_cfg.chnCfg[chn].tcs = test->param;
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
break;
case (SPI_TEST_ID_INIT_DELAY):
spi_cfg.initDelay = test->param;
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
break;
default:
break;
}
#ifdef SPI_DMA_ENABLE
if (spi_cfg.txTrigLvl != 0)
{
test->trigLvl = spi_cfg.txTrigLvl;
}
else
{
test->trigLvl = 0;
}
if (spi_cfg.txTrigLvl < spi_cfg.rxTrigLvl)
{
test->trigLvl = spi_cfg.rxTrigLvl;
}
#endif
#endif
if (testId == SPI_TEST_ID_WORD_LEN)
{
#if defined(SOC_DRA78x) || defined(SOC_TDA3XX) || defined(SOC_TDA2XX) || defined(SOC_TDA2EX) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined (SOC_AM572x) || defined (SOC_AM571x) || defined (SOC_AM574x) || defined (SOC_AM437x) || defined (SOC_AM335x) || defined (SOC_AM65XX) || defined(SOC_J721E)
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
#else
/* enalbe loopback mode */
spi_cfg.loopback = 1;
#endif
}
/* Set the SPI init configurations */
SPI_socSetInitCfg(instance, &spi_cfg);
}
bool SPI_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 uintptr_t l2_global_address (uintptr_t addr)
{
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || defined(SOC_C6678) || defined(SOC_C6657)
#ifdef _TMS320C6X
uint32_t corenum;
/* Get the core number. */
corenum = CSL_chipReadReg (CSL_CHIP_DNUM);
/* Compute the global address. */
return (addr + (0x10000000 + (corenum * 0x1000000)));
#else
return addr;
#endif
#else
return addr;
#endif
}
static void SPI_test_xfer_ctrl(SPI_Handle spi, uint32_t xferEnable)
{
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2E) || defined(SOC_K2L) || defined(SOC_K2G) || defined(SOC_C6678) || defined(SOC_C6657)
uint32_t xferActivate = xferEnable;
SPI_control(spi, SPI_V0_CMD_XFER_ACTIVATE, (void *)&xferActivate);
#endif
}
static bool SPI_test_mst_slv_xfer(void *spi, SPI_Tests *test, uint32_t xferLen, bool multChn)
{
bool transferOK;
uintptr_t addrMasterRxBuf, addrMasterTxBuf, addrSlaveRxBuf, addrSlaveTxBuf;
bool ret = false;
uint32_t terminateXfer = 1;
int32_t testId = test->testId;
bool master = test->master;
bool cbMode = test->cbMode;
bool dmaMode = test->dmaMode;
uint32_t timeout = test->timeout;
uint32_t transCount, xferBytes, testLen;
unsigned char *srcPtr;
if (dmaMode)
{
addrMasterRxBuf = l2_global_address((uintptr_t)masterRxBuffer);
addrMasterTxBuf = l2_global_address((uintptr_t)masterTxBuffer);
addrSlaveRxBuf = l2_global_address((uintptr_t)slaveRxBuffer);
addrSlaveTxBuf = l2_global_address((uintptr_t)slaveTxBuffer);
}
else
{
addrMasterRxBuf = (uintptr_t)masterRxBuffer;
addrMasterTxBuf = (uintptr_t)masterTxBuffer;
addrSlaveRxBuf = (uintptr_t)slaveRxBuffer;
addrSlaveTxBuf = (uintptr_t)slaveTxBuffer;
}
memset(masterRxBuffer, 0, sizeof(masterRxBuffer));
memset(slaveRxBuffer, 0, sizeof(slaveRxBuffer));
#ifdef SPI_DMA_ENABLE
#if !defined (__aarch64__)
if (dmaMode)
{
CacheP_wbInv((void *)addrMasterRxBuf, (int32_t)sizeof(masterRxBuffer));
CacheP_wbInv((void *)addrSlaveRxBuf, (int32_t)sizeof(slaveRxBuffer));
}
#endif
#endif
testLen = xferLen;
#if defined(SOC_AM574x) || defined(SOC_AM572x)|| defined(SOC_AM571x) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined (SOC_DRA78x) || defined (SOC_AM335x) || defined (SOC_AM437x) || defined (SOC_AM65XX) || defined(SOC_J721E)
#ifdef SPI_DMA_ENABLE
if (dmaMode == true)
{
if (testLen > test->trigLvl)
{
/* always transfer data bytes of multiple trigger level */
testLen = (xferLen / test->trigLvl) * test->trigLvl;
}
else
{
/* transfer data bytes of 1 trigger level */
testLen = test->trigLvl;
}
}
#endif
#endif
if (testId == SPI_TEST_ID_WORD_LEN)
{
/*
* Word length can be 8/16/32 bits,
* calculate the SPI word count
*/
transCount = testLen / (test->param / 8);
xferBytes = transCount * (test->param / 8);
}
else
{
/* Default word length is 8-bit */
transCount = testLen;
xferBytes = testLen;
}
/* Initialize slave SPI transaction structure */
transaction.count = transCount;
transaction.arg = (void *)&terminateXfer;
if (master == true)
{
transaction.txBuf = (void *)addrMasterTxBuf;
transaction.rxBuf = (void *)addrMasterRxBuf;
}
else
{
transaction.txBuf = (void *)addrSlaveTxBuf;
transaction.rxBuf = (void *)addrSlaveRxBuf;
}
/* Initiate SPI transfer */
SPI_test_xfer_ctrl(spi, 1);
#ifdef MCSPI_MULT_CHANNEL
if (multChn == true)
{
transferOK = MCSPI_transfer((MCSPI_Handle)spi, &transaction);
}
else
#endif
{
transferOK = SPI_transfer((SPI_Handle)spi, &transaction);
}
if(transferOK)
{
if (cbMode)
{
if (SPI_osalPendLock(cbSem[0], timeout) != SemaphoreP_OK)
{
goto Err;
}
}
SPI_test_xfer_ctrl(spi, 0);
/* Get the actual transfer bytes */
if (testId == SPI_TEST_ID_WORD_LEN)
{
xferBytes = transaction.count * (test->param / 8);
}
else
{
xferBytes = transaction.count;
}
if (testId != SPI_TEST_ID_TX_ONLY)
{
if (master == true)
{
if (testId >= SPI_TEST_ID_LOOPBACK)
{
srcPtr = masterTxBuffer;
}
else
{
srcPtr = slaveTxBuffer;
}
/* master mode, verify master recieved data match with slave sent data */
if (SPI_verify_data(masterRxBuffer, srcPtr, xferBytes) == false)
{
goto Err;
}
/* Print contents of master receive buffer */
SPI_log("Master: %s\n", masterRxBuffer);
}
else
{
/* slave mode, verify slave recieved data match with master sent data */
if (SPI_verify_data(slaveRxBuffer, masterTxBuffer, xferBytes) == false)
{
goto Err;
}
/* Print contents of slave receive buffer */
SPI_log("Slave: %s\n", slaveRxBuffer);
}
}
}
else
{
if ((testId == SPI_TEST_ID_TIMEOUT) || (testId == SPI_TEST_ID_TIMEOUT_POLL))
{
if (transaction.status == SPI_TRANSFER_TIMEOUT)
{
SPI_log("SPI Slave transfer Timed out for transfer length %d\n", xferLen);
}
else
{
SPI_log("Unsuccessful slave SPI transfer");
goto Err;
}
}
else
{
SPI_log("Unsuccessful slave SPI transfer");
goto Err;
}
}
ret = true;
Err:
return (ret);
}
static bool SPI_test_single_channel(void *arg)
{
SPI_Handle spi;
SPI_Params spiParams;
uint32_t instance, i, modeIndex, SPI_modeIndex;
bool ret = false;
SPI_Tests *test = (SPI_Tests *)arg;
int32_t testId = test->testId;
bool master = test->master;
bool cbMode = test->cbMode;
uint32_t timeout = test->timeout;
SPI_FrameFormat frameFormat[]=
{
SPI_POL0_PHA0, /*!< SPI mode Polarity 0 Phase 0 */
SPI_POL0_PHA1, /*!< SPI mode Polarity 0 Phase 1 */
SPI_POL1_PHA0, /*!< SPI mode Polarity 1 Phase 0 */
SPI_POL1_PHA1, /*!< SPI mode Polarity 1 Phase 1 */
};
if (cbMode == true)
{
/* Create call back semaphore */
SPI_osalSemParamsInit(&cbSemParams);
cbSemParams.mode = SemaphoreP_Mode_BINARY;
cbSem[0] = SPI_osalCreateBlockingLock(0, &cbSemParams);
}
if ((testId == SPI_TEST_ID_WORD_LEN) && (test->dmaMode == false))
{
SPI_modeIndex = 4;
}
else
{
SPI_modeIndex = 1;
}
/* In case of SPI_TEST_ID_PHA_POL all SPI modes need to be tested */
for (modeIndex = 0; modeIndex < SPI_modeIndex; modeIndex++)
{
ret = false;
/* Soc configuration structures indexing starts from 0. If the IP
* instances start with 1, to address proper Configuration
* structure index, McSPI Instance should be substracted with 1
*/
if (master == true)
{
instance = (uint32_t)BOARD_MCSPI_MASTER_INSTANCE - 1;
}
else
{
instance = (uint32_t)BOARD_MCSPI_SLAVE_INSTANCE - 1;
}
SPI_initConfig(instance, test, MCSPI_TEST_CHN, false);
/* Initialize SPI handle */
SPI_Params_init(&spiParams);
if (master == false)
{
spiParams.mode = SPI_SLAVE;
}
if (cbMode == true)
{
spiParams.transferMode = SPI_MODE_CALLBACK;
spiParams.transferCallbackFxn = SPI_callback;
}
spiParams.transferTimeout = timeout;
if (testId == SPI_TEST_ID_PHA_POL)
{
spiParams.frameFormat = (SPI_FrameFormat)(test->param);
}
if (testId == SPI_TEST_ID_WORD_LEN)
{
if(test->dmaMode == false)
{
spiParams.frameFormat = frameFormat[modeIndex];
SPI_log("\n%s with SPI Mode %d\n", test->testDesc, spiParams.frameFormat);
}
spiParams.dataSize = test->param;
}
spi = SPI_open(instance, &spiParams);
if (spi == NULL)
{
SPI_log("Error initializing SPI\n");
goto Err;
}
else
{
SPI_log("SPI initialized\n");
}
for (i = 0; i < SPI_NUM_XFERS; i++)
{
if (SPI_test_mst_slv_xfer((void *)spi, test, spi_test_xfer_len[i], false) == false)
{
goto Err;
}
if ((master == true) && (testId < SPI_TEST_ID_LOOPBACK))
{
/*
* master sleep for 1 second after each transfer
* to sync with slave transfer
*/
#ifdef USE_BIOS
Task_sleep(1000);
#else
#endif
}
}
ret = true;
if (testId == SPI_TEST_ID_WORD_LEN){
if (spi)
{
SPI_close(spi);
}
}
} /* End of for loop */
Err:
if (testId != SPI_TEST_ID_WORD_LEN){
if (spi)
{
SPI_close(spi);
}
}
if (cbSem[0])
{
SPI_osalDeleteBlockingLock(cbSem[0]);
cbSem[0] = NULL;
}
return (ret);
}
static bool SPI_test_xfer_error(void *arg)
{
bool ret;
#if defined(SOC_K2G)
SPI_Handle spi;
SPI_Params spiParams;
bool transferOK;
uint32_t instance;
SPI_Tests *test = (SPI_Tests *)arg;
bool master = test->master;
uint32_t timeout = test->timeout;
uint32_t terminateXfer = 1;
uint32_t xferErr;
if (master == true)
{
ret = false;
instance = 2;
SPI_initConfig(instance, test, MCSPI_TEST_CHN, false);
/* Initialize SPI handle */
SPI_Params_init(&spiParams);
spiParams.transferTimeout = timeout;
spi = SPI_open(instance, &spiParams);
if (spi == NULL)
{
SPI_log("Error initializing SPI\n");
goto Err;
}
else
{
SPI_log("SPI initialized\n");
}
/* Initialize slave SPI transaction structure */
transaction.count = 10;
transaction.arg = (void *)&terminateXfer;
transaction.txBuf = (void *)masterTxBuffer;
transaction.rxBuf = (void *)masterRxBuffer;
/* Initiate SPI transfer */
SPI_test_xfer_ctrl(spi, 1);
transferOK = SPI_transfer((SPI_Handle)spi, &transaction);
if(transferOK)
{
SPI_test_xfer_ctrl(spi, 0);
SPI_control(spi, SPI_V0_CMD_GET_XFER_ERR, (void *)&xferErr);
if (xferErr == SPI_XFER_ERR_RXOR)
{
SPI_log("Receive overrun error detected\n");
}
else if (xferErr == SPI_XFER_ERR_BE)
{
SPI_log("Bit error detected\n");
}
else
{
SPI_log("No error detected\n");
}
ret = true;
}
/*
* master sleep for 1 second after each transfer
* to sync with slave transfer
*/
#ifdef USE_BIOS
Task_sleep(1000);
#else
#endif
Err:
if (spi)
{
SPI_close(spi);
}
}
else
{
/* slave do nothing for xfer error test */
ret = true;
}
#else
ret = true;
#endif
return (ret);
}
#ifdef MCSPI_MULT_CHANNEL
static bool SPI_test_multi_channel(void *arg)
{
MCSPI_Handle spi[MCSPI_MAX_NUM_CHN];
MCSPI_Params spiParams;
uint32_t instance, i;
bool ret = false;
uint32_t chn, maxNumChn, testChn;
MCSPI_CallbackFxn cbFxn[MCSPI_MAX_NUM_CHN] = {MCSPI_callback0, MCSPI_callback1, MCSPI_callback2, MCSPI_callback3};
SPI_Tests *test = (SPI_Tests *)arg;
int32_t testId = test->testId;
bool master = test->master;
bool cbMode = test->cbMode;
uint32_t timeout = test->timeout;
if (cbMode == true)
{
/* Create call back semaphore */
SPI_osalSemParamsInit(&cbSemParams);
cbSemParams.mode = SemaphoreP_Mode_BINARY;
}
/* Soc configuration structures indexing starts from 0. If the IP
* instances start with 1, to address proper Configuration
* structure index, McSPI Instance should be substracted with 1
*/
if (master == true)
{
instance = (uint32_t)BOARD_MCSPI_MASTER_INSTANCE - 1;
}
else
{
instance = (uint32_t)BOARD_MCSPI_SLAVE_INSTANCE - 1;
}
testChn = MCSPI_TEST_CHN;
SPI_initConfig(instance, test, testChn, false);
/* Initialize SPI handle */
MCSPI_Params_init(&spiParams);
if (master == false)
{
spiParams.mode = SPI_SLAVE;
}
if (cbMode == true)
{
spiParams.transferMode = SPI_MODE_CALLBACK;
}
spiParams.transferTimeout = timeout;
if (testId == SPI_TEST_ID_WORD_LEN)
{
spiParams.dataSize = test->param;
}
if (master == true)
{
maxNumChn = MCSPI_MAX_NUM_CHN;
}
else
{
/* Only 1 channel supported in slave mode */
maxNumChn = 1;
}
for (i = 0; i < maxNumChn; i++)
{
if (master == true)
{
chn = i;
}
else
{
chn = testChn;
}
if (cbMode == true)
{
cbSem[chn] = SPI_osalCreateBlockingLock(0, &cbSemParams);
spiParams.transferCallbackFxn = cbFxn[chn];;
}
spi[chn] = MCSPI_open(instance, chn, &spiParams);
if (spi[chn] == NULL)
{
SPI_log("Error initializing SPI instance %d channel %d\n",
instance, chn);
goto Err;
}
else
{
SPI_log("SPI instance %d channel %d\n",
instance, chn);
}
}
for (i = 0; i < SPI_NUM_XFERS; i++)
{
if (SPI_test_mst_slv_xfer((void *)(spi[testChn]), test, spi_test_xfer_len[i], true) == false)
{
goto Err;
}
if ((master == true) && (testId < SPI_TEST_ID_LOOPBACK))
{
/*
* master sleep for 1 second after each transfer
* to sync with slave transfer
*/
#ifdef USE_BIOS
Task_sleep(1000);
#else
#endif
}
}
ret = true;
Err:
for (i = 0; i < maxNumChn; i++)
{
if (master == true)
{
chn = i;
}
else
{
chn = testChn;
}
if (spi[chn])
{
MCSPI_close(spi[chn]);
}
if (cbSem[chn])
{
SPI_osalDeleteBlockingLock(cbSem[chn]);
cbSem[chn] = NULL;
}
}
return (ret);
}
#endif
void SPI_test_print_test_desc(SPI_Tests *test)
{
char testId[16] = {0, };
/* Print unit test ID */
sprintf(testId, "%d", test->testId);
SPI_log("\r\n SPI UT %s\r\n", testId);
/* Print test description */
SPI_log("\r\n %s\r\n", test->testDesc);
}
SPI_Tests Spi_tests_master[] =
{
/* testFunc testID master pollMode cbMode dmaMode timeout testDesc */
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in dma mode", },
#endif
{SPI_test_single_channel, SPI_TEST_ID_INT, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_POLL, true, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in polling mode"},
{SPI_test_single_channel, SPI_TEST_ID_CB, true, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA_CB, true, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in dma callback mode", },
#endif
{SPI_test_xfer_error, SPI_TEST_ID_XFER_ERR, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master transfer error test in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_PHA_POL, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master phase polarity test in non-dma interrupt mode", 1, },
#ifdef MCSPI_MULT_CHANNEL
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in dma mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_MC_INT, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in non-dma interrupt mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_POLL, true, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in polling mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_CB, true, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA_CB, true, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in dma callback mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_TX_ONLY, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel TX_ONLY test", 0, },
#endif
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_WORD_LEN, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master data size test in loopback dma mode", SPI_TEST_DATA_SIZE, },
#endif
{SPI_test_single_channel, SPI_TEST_ID_WORD_LEN, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master data size test in loopback mode", SPI_TEST_DATA_SIZE, },
#ifdef MCSPI_MULT_CHANNEL
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_TRIG_LVL, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master multi channel FIFO trigger level test in loopback dma mode", SPI_TEST_TRIG_LVL, },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_TRIG_LVL, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master multi channel FIFO trigger level test in loopback mode", SPI_TEST_TRIG_LVL, },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_TCS, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel TCS test in dma mode", SPI_TEST_TCS, },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_TCS, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel TCS test", SPI_TEST_TCS, },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_INIT_DELAY, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel init delay test in dma mode", SPI_TEST_INIT_DELAY, },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_INIT_DELAY, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel init delay test", SPI_TEST_INIT_DELAY, },
#endif
/* NOTE: Timeout Test case should be executed as the final test, as this test requires no transaction on the data lines
* for the timeout to happen */
{SPI_test_single_channel, SPI_TEST_ID_TIMEOUT, false, false, false, false, SPI_TIMEOUT_VALUE, "\r\n SPI timeout test in interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_TIMEOUT_POLL, false, true, false, false, SPI_TIMEOUT_VALUE, "\r\n SPI timeout test in polling mode", },
{NULL, },
};
SPI_Tests Spi_tests_slave[] =
{
/* testFunc testID master pollMode cbMode dmaMode, timeout testDesc */
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA, false, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in dma mode", },
#endif
{SPI_test_single_channel, SPI_TEST_ID_INT, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_POLL, false, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in polling mode", },
{SPI_test_single_channel, SPI_TEST_ID_CB, false, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA_CB, false, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in dma callback mode", },
#endif
{SPI_test_xfer_error, SPI_TEST_ID_XFER_ERR, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI slave transfer error test in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_PHA_POL, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI slave phase polarity test in non-dma interrupt mode", 1, },
#ifdef MCSPI_MULT_CHANNEL
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA, false, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave multi channel in dma mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_MC_INT, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave multi channel in non-dma interrupt mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_POLL, false, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in polling mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_CB, false, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA_CB, false, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in dma callback mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_RX_ONLY, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave multi channel RX_ONLY test", 0, },
#endif
{NULL, },
};
/*
* ======== slaveTaskFxn ========
* The task is part of separate slave example project.
* To test slave mode example, slave task has to be
* ready for master. Slave SPI sends a message to master
* while receiving message from master.
*/
#ifdef USE_BIOS
Void slaveTaskFxn (UArg arg0, UArg arg1)
#else
void slaveTaskFxn()
#endif
{
uint32_t i;
bool testFail = false;
SPI_Tests *test;
SPI_init();
for (i = 0; ; i++)
{
if (evmAM570x == true)
{
/* Slave mode test not supported on AM570x EVM */
break;
}
test = &Spi_tests_slave[i];
if (test->testFunc == NULL)
break;
if (test->testId >= SPI_TEST_ID_LOOPBACK)
{
/* bypass the loopback test for slave task */
break;
}
SPI_test_print_test_desc(test);
if (test->testFunc((void *)test) == true)
{
SPI_log("\r\n %s have passed\r\n", test->testDesc);
}
else
{
SPI_log("\r\n %s have failed\r\n", test->testDesc);
testFail = true;
break;
}
}
if(testFail == true)
{
SPI_log("\n Some tests have failed. \n");
}
else
{
SPI_log("\n All tests have passed. \n");
}
SPI_log("Done\n");
while (true)
{
}
}
/*
* ======== masterTaskFxn ========
* This task is part of master example project.
* Slave task has to ensure transaction ready.
* Master SPI sends a message to slave and
* receives message from slave.
*/
#ifdef USE_BIOS
Void masterTaskFxn (UArg arg0, UArg arg1)
#else
void masterTaskFxn()
#endif
{
uint32_t i;
bool testFail = false;
SPI_Tests *test;
SPI_init();
for (i = 0; ; i++)
{
test = &Spi_tests_master[i];
if (test->testFunc == NULL)
break;
#if defined (SOC_AM65XX) || defined(SOC_J721E)
if ((test->testId < SPI_TEST_ID_LOOPBACK) &&
(test->testId != SPI_TEST_ID_TIMEOUT) &&
(test->testId != SPI_TEST_ID_TIMEOUT_POLL))
continue;
#endif
if (evmAM570x == true)
{
/* Only loopback test supported on AM570x EVM */
if ((test->testId < SPI_TEST_ID_LOOPBACK) &&
(test->testId != SPI_TEST_ID_TIMEOUT) &&
(test->testId != SPI_TEST_ID_TIMEOUT_POLL))
continue;
}
SPI_test_print_test_desc(test);
if (test->testFunc((void *)test) == true)
{
SPI_log("\r\n %s have passed\r\n", test->testDesc);
}
else
{
SPI_log("\r\n %s have failed\r\n", test->testDesc);
testFail = true;
break;
}
}
if(testFail == true)
{
SPI_log("\n Some tests have failed. \n");
}
else
{
SPI_log("\n All tests have passed. \n");
}
SPI_log("Done\n");
while (true)
{
}
}
/*
* ======== main ========
*/
int main(void)
{
/* Call board init functions */
Board_initCfg boardCfg;
Board_STATUS boardStatus;
#if defined (evmK2G)
SPI_v0_HWAttrs spi_cfg;
uint8_t instance;
Board_SoCInfo socInfo;
#endif
#if defined (idkAM571x)
Board_IDInfo id;
#endif
#ifdef USE_BIOS
#if defined(SOC_AM335x) || defined (SOC_AM437x) || defined (SOC_AM65XX) || defined(SOC_J721E)
Task_Handle task;
Error_Block eb;
Error_init(&eb);
#if defined (MCSPI_SLAVE_TASK)
task = Task_create(slaveTaskFxn, NULL, &eb);
#elif defined (MCSPI_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 */
#endif /* #ifdef USE_BIOS */
boardCfg = BOARD_INIT_PINMUX_CONFIG |
BOARD_INIT_MODULE_CLOCK |
BOARD_INIT_UART_STDIO;
boardStatus = Board_init(boardCfg);
if (boardStatus != BOARD_SOK)
{
return (0);
}
#if defined(SOC_AM65XX) || defined(SOC_J721E)
#if defined (__TI_ARM_V7R4__)
/* Configure the MCU SPI0_D1 pinmux, since it is not set by default in board */
HW_WR_REG32((WKUP_PINMUX_REG_BASE + MCU_SPI0_D1_PADCFG_OFFSET), PIN_MODE(0) | \
((PIN_PULL_DISABLE | PIN_INPUT_ENABLE) & (~PIN_PULL_DIRECTION)));
/* Configure the MCU SPI0_CLK pinmux to support loopback */
HW_WR_REG32((WKUP_PINMUX_REG_BASE + MCU_SPI0_CLK_PADCFG_OFFSET), PIN_MODE(0) | \
((PIN_PULL_DISABLE | PIN_INPUT_ENABLE) & (~PIN_PULL_DIRECTION)));
#endif
#endif
#if defined (idkAM571x)
boardStatus = Board_getIDInfo(&id);
if (boardStatus != BOARD_SOK)
{
return (0);
}
/* Check if is DRA (AM570x) SoC */
if ((id.boardName[0] == 'D') &&
(id.boardName[1] == 'R') &&
(id.boardName[2] == 'A'))
{
evmAM570x = true;
}
#endif
#if defined(iceAMIC110)
/* GPIO initialization */
GPIO_init();
/* Set BUS_Switch_ENABLE pin to low for enabling the switch */
GPIO_write((GPIO_BUS_SWITCH_ENABLE_OFFSET), GPIO_PIN_VAL_LOW);
#endif
#if defined (evmK2G)
/* Read the SoC info to get the System clock value */
Board_getSoCInfo(&socInfo);
if(socInfo.sysClock != BOARD_SYS_CLK_DEFAULT)
{
/* Since this is a generic SPI test,
* configure the input clock for all the available instances */
for (instance = 0; instance < CSL_SPI_CNT; instance++)
{
SPI_socGetInitCfg(instance, &spi_cfg);
/* Update the I2C functional clock based on CPU clock - 1G or 600MHz */
spi_cfg.inputClkFreq = socInfo.sysClock/SPI_MODULE_CLOCK_DIVIDER;
SPI_socSetInitCfg(instance, &spi_cfg);
}
}
#endif
#ifdef USE_BIOS
/* Start BIOS */
BIOS_start();
#else
#ifdef MCSPI_MASTER_TASK
masterTaskFxn();
#else
slaveTaskFxn();
#endif
#endif
return (0);
}
#if defined(BUILD_MPU) || defined (__C7100__)
extern void Osal_initMmuDefault(void);
void InitMmu(void)
{
Osal_initMmuDefault();
}
#endif
/*
* \file main_mcspi_slave_mode.c
*
* \brief The application Demonstrate the MCSPI slave mode functionality.
* This application transmits data from master to slave and at the
* same instance data from slave will be 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:
* MasterSPI_SCLK----SlaveSPI_SCLK
* MasterSPI_D0------SlaveSPI_D1
* MasterSPI_D1------SlaveSPI_D0
* MasterSPI_CS------SlaveSPI_CS
*
* \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:
* SPI initialized
* Slave: PASS: Txd from master SPI
*
* At master end console:
* SPI initialized
* Master: PASS: Txd from slave SPI
* Done
*/
/*
* Copyright (C) 2016 - 2019 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>
#ifdef USE_BIOS
/* XDCtools Header files */
#include <xdc/std.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>
#endif /* #ifdef USE_BIOS */
/* 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/spi/soc/SPI_soc.h>
#include <ti/drv/spi/src/SPI_osal.h>
#include <ti/drv/spi/SPI.h>
#include "SPI_log.h"
#if defined(iceAMIC110)
#include <ti/drv/gpio/GPIO.h>
#include <ti/drv/gpio/soc/GPIO_soc.h>
#endif
#include <ti/board/board.h>
#ifdef SOC_AM65XX
#include <ti/csl/soc/am65xx/src/cslr_soc_baseaddress.h>
#include <ti/csl/soc/am65xx/src/cslr_wkup_ctrl_mmr.h>
#elif defined(SOC_J721E)
#include <ti/csl/soc/j721e/src/cslr_soc_baseaddress.h>
#include <ti/csl/soc/j721e/src/cslr_wkup_ctrl_mmr.h>
#endif
#ifdef SPI_DMA_ENABLE
#include <ti/osal/CacheP.h>
#if defined (SOC_AM65XX) || defined(SOC_J721E)
#include <ti/drv/udma/udma.h>
#else
/* EDMA3 Header files */
#include <ti/sdo/edma3/drv/edma3_drv.h>
#include <ti/sdo/edma3/rm/edma3_rm.h>
#include <ti/sdo/edma3/rm/sample/bios6_edma3_rm_sample.h>
#if defined(evmK2G)
#include <ti/csl/soc.h>
#endif
static EDMA3_RM_Handle MCSPIApp_edmaInit(void);
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || \
defined(SOC_C6678) || defined(SOC_C6657)
extern EDMA3_RM_InstanceInitConfig sampleInstInitConfig[][EDMA3_MAX_REGIONS];
extern EDMA3_RM_GblConfigParams sampleEdma3GblCfgParams[];
#endif
#endif
#endif
/* Define the SPI test interface */
typedef struct SPI_Tests_s
{
bool (*testFunc)(void *);
int32_t testId;
bool master;
bool pollMode;
bool cbMode;
bool dmaMode;
uint32_t timeout;
char testDesc[80];
uint32_t param;
uint32_t trigLvl;
} SPI_Tests;
/**********************************************************************
************************** Macros ************************************
**********************************************************************/
#define SPI_TIMEOUT_VALUE 5000
/* SPI transfer message definitions */
#define SPI_MSG_LENGTH 26
#define SPI_MSG_LENGTH2 78
#define SPI_NUM_XFERS 2
uint32_t spi_test_xfer_len[SPI_NUM_XFERS] =
{
SPI_MSG_LENGTH,
SPI_MSG_LENGTH2
};
/* Maximum # of channels per SPI instance */
#define MCSPI_MAX_NUM_CHN 4
/* Test channel # */
#define MCSPI_TEST_CHN 0
/* SPI Test definitions */
/* Unit test IDs */
#define SPI_TEST_ID_DMA 0 /* Single-channel DMA mode test */
#define SPI_TEST_ID_INT 1 /* Single-channel interrupt mode test */
#define SPI_TEST_ID_POLL 2 /* Single-channel polling mode test */
#define SPI_TEST_ID_CB 3 /* Single-channel non-DMA callback mode test */
#define SPI_TEST_ID_DMA_CB 4 /* Single-channel DMA callback mode test */
#define SPI_TEST_ID_MC_DMA 5 /* Multi-channel DMA mode test */
#define SPI_TEST_ID_MC_INT 6 /* Multi-channel interrupt mode test */
#define SPI_TEST_ID_MC_POLL 7 /* Multie-channel polling mode test */
#define SPI_TEST_ID_MC_CB 8 /* Multi-channel non-DMA callback mode test */
#define SPI_TEST_ID_MC_DMA_CB 9 /* Multi-channel DMA callback mode test */
#define SPI_TEST_ID_TX_ONLY 10 /* Multi-channel TX only test */
#define SPI_TEST_ID_RX_ONLY 11 /* Multi-channel RX only test */
#define SPI_TEST_ID_XFER_ERR 12 /* Single-channel transfer error test */
#define SPI_TEST_ID_PHA_POL 13 /* Single-channel phase/polarity test */
#define SPI_TEST_ID_TIMEOUT 14 /* Single-channel Timeout test with interrupt enabled */
#define SPI_TEST_ID_TIMEOUT_POLL 15 /* Single-channel Timeout test with polling enabled */
/* Loopback tests */
#define SPI_TEST_ID_LOOPBACK 20
#define SPI_TEST_ID_WORD_LEN (SPI_TEST_ID_LOOPBACK) /* transfer data size test */
#define SPI_TEST_ID_TRIG_LVL (SPI_TEST_ID_LOOPBACK + 1) /* FIFO trigger level test */
#define SPI_TEST_ID_TCS (SPI_TEST_ID_LOOPBACK + 2) /* Multi-channel chip select time control test */
#define SPI_TEST_ID_INIT_DELAY (SPI_TEST_ID_LOOPBACK + 3) /* Multi-channel 1st transfer init delay test */
/* Transfer data size test parameter, in # of bits per SPI word */
#define SPI_TEST_DATA_SIZE_16 16
#define SPI_TEST_DATA_SIZE_32 32
#if defined(SOC_DRA78x) || defined(SOC_TDA3XX) || defined(SOC_TDA2XX) || defined(SOC_TDA2EX) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined(SOC_AM574x) || defined (SOC_AM572x) || defined (SOC_AM571x) || defined (SOC_AM437x) || defined (SOC_AM335x) || defined (SOC_AM65XX) || defined(SOC_J721E)
#define SPI_TEST_DATA_SIZE SPI_TEST_DATA_SIZE_32
#else
#define SPI_TEST_DATA_SIZE SPI_TEST_DATA_SIZE_16
#endif
#ifdef MCSPI_MULT_CHANNEL
/* Chip select time control test parameter */
#define SPI_TEST_TCS MCSPI_CH0CONF_TCS0_ONECYCLEDLY
/* 1st transfer init delay test parameter */
#define SPI_TEST_INIT_DELAY MCSPI_INITDLY_4
/* FIFO trigger level test parameter, in # of bytes */
#define SPI_TEST_TRIG_LVL 16
#endif
#if defined(SOC_AM65XX) || defined(SOC_J721E)
/* WKUP CTRL base address + offset to beginning of PAD CONFIG section */
#define WKUP_PINMUX_REG_BASE (CSL_WKUP_CTRL_MMR0_CFG0_BASE + \
CSL_WKUP_CTRL_MMR_CFG0_PADCONFIG0)
#define MCU_SPI0_CLK_PADCFG_OFFSET (0x90U)
#define MCU_SPI0_D1_PADCFG_OFFSET (0x98U)
#define PIN_MODE(mode) (mode)
/** \brief Active mode configurations */
/** \brief Resistor disable */
#define PIN_PULL_DISABLE (0x1U << 16U)
/** \brief Pull direction */
#define PIN_PULL_DIRECTION (0x1U << 17U)
/** \brief Receiver enable */
#define PIN_INPUT_ENABLE (0x1U << 18U)
/** \brief Driver disable */
#define PIN_OUTPUT_DISABLE (0x1U << 21U)
/** \brief Wakeup enable */
#define PIN_WAKEUP_ENABLE (0x1U << 29U)
#ifdef SPI_DMA_ENABLE
/*
* Ring parameters
*/
/** \brief Number of ring entries - we can prime this much memcpy operations */
#define UDMA_TEST_APP_RING_ENTRIES (1U)
/** \brief Size (in bytes) of each ring entry (Size of pointer - 64-bit) */
#define UDMA_TEST_APP_RING_ENTRY_SIZE (sizeof(uint64_t))
/** \brief Total ring memory */
#define UDMA_TEST_APP_RING_MEM_SIZE (UDMA_TEST_APP_RING_ENTRIES * \
UDMA_TEST_APP_RING_ENTRY_SIZE)
/**
* \brief UDMA host mode buffer descriptor memory size.
* Make it multiple of 128 byte alignment
*/
#define UDMA_TEST_APP_DESC_SIZE (sizeof(CSL_UdmapCppi5HMPD) + (128U - sizeof(CSL_UdmapCppi5HMPD)))
/*
* UDMA driver objects
*/
struct Udma_DrvObj gUdmaDrvObj;
struct Udma_ChObj gUdmaTxChObj;
struct Udma_ChObj gUdmaRxChObj;
struct Udma_EventObj gUdmaTxCqEventObj;
struct Udma_EventObj gUdmaRxCqEventObj;
Udma_DrvHandle gDrvHandle = NULL;
/*
* UDMA Memories
*/
static uint8_t gTxRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gTxCompRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gUdmaTxHpdMem[UDMA_TEST_APP_DESC_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gRxRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gRxCompRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gUdmaRxHpdMem[UDMA_TEST_APP_DESC_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static SPI_dmaInfo gUdmaInfo;
Udma_DrvHandle MCSPIApp_udmaInit(SPI_v1_HWAttrs *cfg)
{
int32_t retVal = UDMA_SOK;
Udma_InitPrms initPrms;
uint32_t instId;
if (gDrvHandle == NULL)
{
/* UDMA driver init */
#if defined (__aarch64__)
instId = UDMA_INST_ID_MAIN_0;
#else
instId = UDMA_INST_ID_MCU_0;
#endif
UdmaInitPrms_init(instId, &initPrms);
retVal = Udma_init(&gUdmaDrvObj, &initPrms);
if(UDMA_SOK == retVal)
{
gDrvHandle = &gUdmaDrvObj;
}
}
if(gDrvHandle != NULL)
{
gDrvHandle = &gUdmaDrvObj;
gUdmaInfo.txChHandle = (void *)&gUdmaTxChObj;
gUdmaInfo.rxChHandle = (void *)&gUdmaRxChObj;
gUdmaInfo.txRingMem = (void *)&gTxRingMem[0];
gUdmaInfo.cqTxRingMem = (void *)&gTxCompRingMem[0];
gUdmaInfo.rxRingMem = (void *)&gRxRingMem[0];
gUdmaInfo.cqRxRingMem = (void *)&gRxCompRingMem[0];
gUdmaInfo.txHpdMem = (void *)&gUdmaTxHpdMem[0];
gUdmaInfo.rxHpdMem = (void *)&gUdmaRxHpdMem[0];
gUdmaInfo.txEventHandle = (void *)&gUdmaTxCqEventObj;
gUdmaInfo.rxEventHandle = (void *)&gUdmaRxCqEventObj;
cfg->dmaInfo = &gUdmaInfo;
}
return (gDrvHandle);
}
int32_t MCSPI_udma_deinit(void)
{
int32_t retVal = UDMA_SOK;
if (gDrvHandle != NULL)
{
retVal = Udma_deinit(gDrvHandle);
if(UDMA_SOK == retVal)
{
gDrvHandle = NULL;
}
}
return (retVal);
}
#endif
#endif /* #if defined(SOC_AM65XX) || defined(SOC_J721E) */
/**********************************************************************
************************** Global Variables **************************
**********************************************************************/
#if (defined(_TMS320C6X) || defined (__TI_ARM_V7M4__))
#pragma DATA_ALIGN (masterRxBuffer, 128)
unsigned char masterRxBuffer[128];
#pragma DATA_ALIGN (slaveRxBuffer, 128)
unsigned char slaveRxBuffer[128];
#else
unsigned char masterRxBuffer[128] __attribute__ ((aligned (128)));
unsigned char slaveRxBuffer[128] __attribute__ ((aligned (128)));
#endif
unsigned char masterTxBuffer[128] = "PASS: Txd from master SPI PASS: Txd from master SPI PASS: Txd from master SPI ";
unsigned char slaveTxBuffer[128] = "PASS: Txd from slave SPI PASS: Txd from slave SPI PASS: Txd from slave SPI ";
#if defined(iceAMIC110)
#define GPIO_BUS_SWITCH_ENABLE_OFFSET (0)
#define GPIO_PIN_VAL_LOW (0U)
#define GPIO_PIN_VAL_HIGH (1U)
#define GPIO_BUS_SWITCH_ENABLE_PIN_NUM (0x15)
#define GPIO_BUS_SWITCH_ENABLE_PORT_NUM (0x2)
/* GPIO Driver board specific pin configuration structure */
GPIO_PinConfig gpioPinConfigs[] = {
/* Boot switch enable pin to control the buffer for routing McSPI
* lines to Launchpad header on iceAMIC110 board */
GPIO_DEVICE_CONFIG((GPIO_BUS_SWITCH_ENABLE_PORT_NUM + 1), GPIO_BUS_SWITCH_ENABLE_PIN_NUM) |
GPIO_CFG_IN_INT_NONE | GPIO_CFG_OUTPUT,
};
/* GPIO Driver call back functions */
GPIO_CallbackFxn gpioCallbackFunctions[] = {
NULL
};
/* GPIO Driver configuration structure */
GPIO_v1_Config GPIO_v1_config = {
gpioPinConfigs,
gpioCallbackFunctions,
sizeof(gpioPinConfigs) / sizeof(GPIO_PinConfig),
sizeof(gpioCallbackFunctions) / sizeof(GPIO_CallbackFxn),
0x1U,
};
#endif /* #if defined(iceAMIC110) */
/* Transaction data */
SPI_Transaction transaction;
/* Callback mode variables */
SemaphoreP_Params cbSemParams;
SemaphoreP_Handle cbSem[MCSPI_MAX_NUM_CHN] = {NULL, NULL, NULL, NULL};
bool evmAM570x = false;
#ifdef SPI_DMA_ENABLE
#if !(defined (SOC_AM65XX) || defined(SOC_J721E))
EDMA3_RM_Handle gEdmaHandle = NULL;
/**
* \brief Function to initialize the edma driver and get the handle to the
* edma driver;
*/
static EDMA3_RM_Handle MCSPIApp_edmaInit(void)
{
EDMA3_DRV_Result edmaResult = EDMA3_DRV_E_INVALID_PARAM;
uint32_t edma3Id;
if (gEdmaHandle != NULL)
{
return (gEdmaHandle);
}
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || \
defined(SOC_C6678) || defined(SOC_C6657)
uint32_t edmaEvent[2], i, chnMapping, chnMappingIdx;
/* For Keystone devices, edm3Id is SPI instance and SoC specific */
SPI_getEdmaInfo(BOARD_MCSPI_MASTER_INSTANCE - 1, &edma3Id, edmaEvent);
/* Set the RX/TX ownDmaChannels and dmaChannelHwEvtMap */
for (i = 0; i < 2; i++)
{
chnMapping = edmaEvent[i];
if (chnMapping < 32)
chnMappingIdx = 0;
else
{
chnMapping -= 32;
chnMappingIdx = 1;
}
sampleInstInitConfig[edma3Id][0].ownDmaChannels[chnMappingIdx] |= (1 << chnMapping);
sampleInstInitConfig[edma3Id][0].ownTccs[chnMappingIdx] |= (1 << chnMapping);
sampleInstInitConfig[edma3Id][0].ownPaRAMSets[chnMappingIdx] |= (1 << chnMapping);
sampleEdma3GblCfgParams[edma3Id].dmaChannelHwEvtMap[chnMappingIdx] |= (1 << chnMapping);
}
#endif
#if defined(SOC_AM574x) || defined(SOC_AM572x)|| defined(SOC_AM571x) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined (SOC_DRA78x) || defined (SOC_AM335x) || defined (SOC_AM437x)
edma3Id = 0;
#endif
gEdmaHandle = (EDMA3_RM_Handle)edma3init(edma3Id, &edmaResult);
#ifdef USE_BIOS
if (edmaResult != EDMA3_DRV_SOK)
{
/* Report EDMA Error */
System_printf("\nEDMA driver initialization FAIL\n");
}
else
{
System_printf("\nEDMA driver initialization PASS.\n");
}
#endif
return(gEdmaHandle);
}
#endif
#endif
// FL: #4: added lines from Anping
int local_data[32];
uint32_t local_data_length;
/* Callback mode functions */
void SPI_callback(SPI_Handle handle, SPI_Transaction *transaction)
{
// FL: #3: three lines from Anping
UART_printf("\nSPI_callback!\n");
memcpy((void *)&local_data[0], transaction->rxBuf, transaction->count);
local_data_length = (uint32_t)transaction->count;
SPI_osalPostLock(cbSem[0]);
}
#ifdef MCSPI_MULT_CHANNEL
void MCSPI_callback0(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[0]);
}
void MCSPI_callback1(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[1]);
}
void MCSPI_callback2(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[2]);
}
void MCSPI_callback3(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[3]);
}
#endif
#ifdef MCSPI_MULT_CHANNEL
/*
* ======== SPI init config ========
*/
static void SPI_initConfigDefault(SPI_HWAttrs *cfg, uint32_t chn)
{
cfg->chNum = chn;
cfg->chnCfg[chn].tcs = MCSPI_CS_TCS_0PNT5_CLK;
cfg->chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_6;
cfg->chnCfg[chn].trMode = MCSPI_TX_RX_MODE;
cfg->initDelay = MCSPI_INITDLY_0;
#if defined (SOC_AM335x)
cfg->rxTrigLvl = MCSPI_RX_TX_FIFO_SIZE / 2;
cfg->txTrigLvl = MCSPI_RX_TX_FIFO_SIZE / 2;
#else
cfg->rxTrigLvl = MCSPI_RX_TX_FIFO_SIZE;
cfg->txTrigLvl = MCSPI_RX_TX_FIFO_SIZE;
#endif
}
#endif
/*
* ======== SPI init config ========
*/
static void SPI_initConfig(uint32_t instance, SPI_Tests *test, uint32_t chn, bool multiChn)
{
SPI_HWAttrs spi_cfg;
int32_t testId = test->testId;
bool pollMode = test->pollMode;
#ifdef SPI_DMA_ENABLE
bool dmaMode = test->dmaMode;
#endif
/* Get the default SPI init configurations */
SPI_socGetInitCfg(instance, &spi_cfg);
#ifdef MCSPI_MULT_CHANNEL
SPI_initConfigDefault(&spi_cfg, chn);
#endif
/*
* Set blocking mode (dma mode or non-dma interrupt mode)
* or callback mode
*/
if (pollMode == true)
{
/* polling mode */
spi_cfg.enableIntr = false;
/* SPI DMA mode is not supported in polling mode */
spi_cfg.edmaHandle = NULL;
spi_cfg.dmaMode = FALSE;
}
else
{
/* interrupt enabled */
spi_cfg.enableIntr = true;
#if defined(SOC_DRA78x) || defined(SOC_TDA3XX) || defined(SOC_TDA2XX) || defined(SOC_TDA2PX) || defined(SOC_TDA2EX) || defined (SOC_DRA75x) || \
defined(SOC_AM574x) || defined (SOC_AM572x) || defined (SOC_AM571x) || defined (SOC_AM437x) || defined (SOC_AM335x) || \
defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || \
defined(SOC_C6678) || defined(SOC_C6657) || defined (SOC_AM65XX) || defined(SOC_J721E)
#ifdef SPI_DMA_ENABLE
if (dmaMode == true)
{
/* Set the DMA related init config */
#if defined (SOC_AM65XX) || defined(SOC_J721E)
spi_cfg.edmaHandle = (void *)MCSPIApp_udmaInit(&spi_cfg);
#else
spi_cfg.edmaHandle = MCSPIApp_edmaInit();
#endif
spi_cfg.dmaMode = TRUE;
spi_cfg.enableIntr = FALSE;
}
else
#endif
{
spi_cfg.edmaHandle = NULL;
spi_cfg.dmaMode = FALSE;
}
#endif
}
#ifdef MCSPI_MULT_CHANNEL
switch(testId)
{
case (SPI_TEST_ID_TX_ONLY):
spi_cfg.chnCfg[chn].trMode = MCSPI_TX_ONLY_MODE;
/* Data line 0 TX enabled, data line 1 RX enabled TX disabled */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_6;
break;
case (SPI_TEST_ID_RX_ONLY):
spi_cfg.chnCfg[chn].trMode = MCSPI_RX_ONLY_MODE;
/* Data line 0 TX disabled, data line 1 RX enabled TX disabled */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_7;
break;
case (SPI_TEST_ID_TRIG_LVL):
spi_cfg.rxTrigLvl = test->param;
spi_cfg.txTrigLvl = test->param;
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
break;
case (SPI_TEST_ID_TCS):
spi_cfg.chnCfg[chn].tcs = test->param;
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
break;
case (SPI_TEST_ID_INIT_DELAY):
spi_cfg.initDelay = test->param;
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
break;
default:
break;
}
#ifdef SPI_DMA_ENABLE
if (spi_cfg.txTrigLvl != 0)
{
test->trigLvl = spi_cfg.txTrigLvl;
}
else
{
test->trigLvl = 0;
}
if (spi_cfg.txTrigLvl < spi_cfg.rxTrigLvl)
{
test->trigLvl = spi_cfg.rxTrigLvl;
}
#endif
#endif
if (testId == SPI_TEST_ID_WORD_LEN)
{
#if defined(SOC_DRA78x) || defined(SOC_TDA3XX) || defined(SOC_TDA2XX) || defined(SOC_TDA2EX) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined (SOC_AM572x) || defined (SOC_AM571x) || defined (SOC_AM574x) || defined (SOC_AM437x) || defined (SOC_AM335x) || defined (SOC_AM65XX) || defined(SOC_J721E)
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
#else
/* enalbe loopback mode */
spi_cfg.loopback = 1;
#endif
}
/* Set the SPI init configurations */
SPI_socSetInitCfg(instance, &spi_cfg);
}
bool SPI_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 uintptr_t l2_global_address (uintptr_t addr)
{
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || defined(SOC_C6678) || defined(SOC_C6657)
#ifdef _TMS320C6X
uint32_t corenum;
/* Get the core number. */
corenum = CSL_chipReadReg (CSL_CHIP_DNUM);
/* Compute the global address. */
return (addr + (0x10000000 + (corenum * 0x1000000)));
#else
return addr;
#endif
#else
return addr;
#endif
}
static void SPI_test_xfer_ctrl(SPI_Handle spi, uint32_t xferEnable)
{
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2E) || defined(SOC_K2L) || defined(SOC_K2G) || defined(SOC_C6678) || defined(SOC_C6657)
uint32_t xferActivate = xferEnable;
SPI_control(spi, SPI_V0_CMD_XFER_ACTIVATE, (void *)&xferActivate);
#endif
}
static bool SPI_test_mst_slv_xfer(void *spi, SPI_Tests *test, uint32_t xferLen, bool multChn)
{
bool transferOK;
uintptr_t addrMasterRxBuf, addrMasterTxBuf, addrSlaveRxBuf, addrSlaveTxBuf;
bool ret = false;
uint32_t terminateXfer = 1;
int32_t testId = test->testId;
bool master = test->master;
bool cbMode = test->cbMode;
bool dmaMode = test->dmaMode;
uint32_t timeout = test->timeout;
uint32_t transCount, xferBytes, testLen;
unsigned char *srcPtr;
if (dmaMode)
{
addrMasterRxBuf = l2_global_address((uintptr_t)masterRxBuffer);
addrMasterTxBuf = l2_global_address((uintptr_t)masterTxBuffer);
addrSlaveRxBuf = l2_global_address((uintptr_t)slaveRxBuffer);
addrSlaveTxBuf = l2_global_address((uintptr_t)slaveTxBuffer);
}
else
{
addrMasterRxBuf = (uintptr_t)masterRxBuffer;
addrMasterTxBuf = (uintptr_t)masterTxBuffer;
addrSlaveRxBuf = (uintptr_t)slaveRxBuffer;
addrSlaveTxBuf = (uintptr_t)slaveTxBuffer;
}
memset(masterRxBuffer, 0, sizeof(masterRxBuffer));
memset(slaveRxBuffer, 0, sizeof(slaveRxBuffer));
#ifdef SPI_DMA_ENABLE
#if !defined (__aarch64__)
if (dmaMode)
{
CacheP_wbInv((void *)addrMasterRxBuf, (int32_t)sizeof(masterRxBuffer));
CacheP_wbInv((void *)addrSlaveRxBuf, (int32_t)sizeof(slaveRxBuffer));
}
#endif
#endif
testLen = xferLen;
#if defined(SOC_AM574x) || defined(SOC_AM572x)|| defined(SOC_AM571x) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined (SOC_DRA78x) || defined (SOC_AM335x) || defined (SOC_AM437x) || defined (SOC_AM65XX) || defined(SOC_J721E)
#ifdef SPI_DMA_ENABLE
if (dmaMode == true)
{
if (testLen > test->trigLvl)
{
/* always transfer data bytes of multiple trigger level */
testLen = (xferLen / test->trigLvl) * test->trigLvl;
}
else
{
/* transfer data bytes of 1 trigger level */
testLen = test->trigLvl;
}
}
#endif
#endif
if (testId == SPI_TEST_ID_WORD_LEN)
{
/*
* Word length can be 8/16/32 bits,
* calculate the SPI word count
*/
transCount = testLen / (test->param / 8);
xferBytes = transCount * (test->param / 8);
}
else
{
/* Default word length is 8-bit */
transCount = testLen;
xferBytes = testLen;
}
/* Initialize slave SPI transaction structure */
transaction.count = transCount;
transaction.arg = (void *)&terminateXfer;
if (master == true)
{
transaction.txBuf = (void *)addrMasterTxBuf;
transaction.rxBuf = (void *)addrMasterRxBuf;
}
else
{
transaction.txBuf = (void *)addrSlaveTxBuf;
transaction.rxBuf = (void *)addrSlaveRxBuf;
}
/* Initiate SPI transfer */
SPI_test_xfer_ctrl(spi, 1);
#ifdef MCSPI_MULT_CHANNEL
if (multChn == true)
{
transferOK = MCSPI_transfer((MCSPI_Handle)spi, &transaction);
}
else
#endif
{
transferOK = SPI_transfer((SPI_Handle)spi, &transaction);
}
if(transferOK)
{
if (cbMode)
{
if (SPI_osalPendLock(cbSem[0], timeout) != SemaphoreP_OK)
{
goto Err;
}
UART_printf("\n SPI_osalPendLock!\n"); // FL: #2: added line from Anping
}
SPI_test_xfer_ctrl(spi, 0);
/* Get the actual transfer bytes */
if (testId == SPI_TEST_ID_WORD_LEN)
{
xferBytes = transaction.count * (test->param / 8);
}
else
{
xferBytes = transaction.count;
}
if (testId != SPI_TEST_ID_TX_ONLY)
{
if (master == true)
{
if (testId >= SPI_TEST_ID_LOOPBACK)
{
srcPtr = masterTxBuffer;
}
else
{
srcPtr = slaveTxBuffer;
}
/* master mode, verify master recieved data match with slave sent data */
if (SPI_verify_data(masterRxBuffer, srcPtr, xferBytes) == false)
{
goto Err;
}
/* Print contents of master receive buffer */
SPI_log("Master: %s\n", masterRxBuffer);
}
else
{
/* slave mode, verify slave recieved data match with master sent data */
if (SPI_verify_data(slaveRxBuffer, masterTxBuffer, xferBytes) == false)
{
goto Err;
}
/* Print contents of slave receive buffer */
SPI_log("Slave: %s\n", slaveRxBuffer);
}
}
}
else
{
if ((testId == SPI_TEST_ID_TIMEOUT) || (testId == SPI_TEST_ID_TIMEOUT_POLL))
{
if (transaction.status == SPI_TRANSFER_TIMEOUT)
{
SPI_log("SPI Slave transfer Timed out for transfer length %d\n", xferLen);
}
else
{
SPI_log("Unsuccessful slave SPI transfer");
goto Err;
}
}
else
{
SPI_log("Unsuccessful slave SPI transfer");
goto Err;
}
}
ret = true;
Err:
return (ret);
}
static bool SPI_test_single_channel(void *arg)
{
SPI_Handle spi;
SPI_Params spiParams;
uint32_t instance, i, modeIndex, SPI_modeIndex;
bool ret = false;
SPI_Tests *test = (SPI_Tests *)arg;
int32_t testId = test->testId;
bool master = test->master;
bool cbMode = test->cbMode;
uint32_t timeout = test->timeout;
SPI_FrameFormat frameFormat[]=
{
SPI_POL0_PHA0, /*!< SPI mode Polarity 0 Phase 0 */
SPI_POL0_PHA1, /*!< SPI mode Polarity 0 Phase 1 */
SPI_POL1_PHA0, /*!< SPI mode Polarity 1 Phase 0 */
SPI_POL1_PHA1, /*!< SPI mode Polarity 1 Phase 1 */
};
if (cbMode == true)
{
/* Create call back semaphore */
SPI_osalSemParamsInit(&cbSemParams);
cbSemParams.mode = SemaphoreP_Mode_BINARY;
cbSem[0] = SPI_osalCreateBlockingLock(0, &cbSemParams);
}
if ((testId == SPI_TEST_ID_WORD_LEN) && (test->dmaMode == false))
{
SPI_modeIndex = 4;
}
else
{
SPI_modeIndex = 1;
}
/* In case of SPI_TEST_ID_PHA_POL all SPI modes need to be tested */
for (modeIndex = 0; modeIndex < SPI_modeIndex; modeIndex++)
{
ret = false;
/* Soc configuration structures indexing starts from 0. If the IP
* instances start with 1, to address proper Configuration
* structure index, McSPI Instance should be substracted with 1
*/
if (master == true)
{
instance = (uint32_t)BOARD_MCSPI_MASTER_INSTANCE - 1;
}
else
{
instance = (uint32_t)BOARD_MCSPI_SLAVE_INSTANCE - 1;
}
SPI_initConfig(instance, test, MCSPI_TEST_CHN, false);
/* Initialize SPI handle */
SPI_Params_init(&spiParams);
if (master == false)
{
spiParams.mode = SPI_SLAVE;
}
if (cbMode == true)
{
spiParams.transferMode = SPI_MODE_CALLBACK;
spiParams.transferCallbackFxn = SPI_callback;
}
spiParams.transferTimeout = timeout;
if (testId == SPI_TEST_ID_PHA_POL)
{
spiParams.frameFormat = (SPI_FrameFormat)(test->param);
}
if (testId == SPI_TEST_ID_WORD_LEN)
{
if(test->dmaMode == false)
{
spiParams.frameFormat = frameFormat[modeIndex];
SPI_log("\n%s with SPI Mode %d\n", test->testDesc, spiParams.frameFormat);
}
spiParams.dataSize = test->param;
}
spi = SPI_open(instance, &spiParams);
if (spi == NULL)
{
SPI_log("Error initializing SPI\n");
goto Err;
}
else
{
SPI_log("SPI initialized\n");
}
for (i = 0; i < SPI_NUM_XFERS; i++)
{
if (SPI_test_mst_slv_xfer((void *)spi, test, spi_test_xfer_len[i], false) == false)
{
goto Err;
}
if ((master == true) && (testId < SPI_TEST_ID_LOOPBACK))
{
/*
* master sleep for 1 second after each transfer
* to sync with slave transfer
*/
#ifdef USE_BIOS
Task_sleep(1000);
#else
#endif
}
}
ret = true;
if (testId == SPI_TEST_ID_WORD_LEN){
if (spi)
{
SPI_close(spi);
}
}
} /* End of for loop */
Err:
if (testId != SPI_TEST_ID_WORD_LEN){
if (spi)
{
SPI_close(spi);
}
}
if (cbSem[0])
{
SPI_osalDeleteBlockingLock(cbSem[0]);
cbSem[0] = NULL;
}
return (ret);
}
static bool SPI_test_xfer_error(void *arg)
{
bool ret;
#if defined(SOC_K2G)
SPI_Handle spi;
SPI_Params spiParams;
bool transferOK;
uint32_t instance;
SPI_Tests *test = (SPI_Tests *)arg;
bool master = test->master;
uint32_t timeout = test->timeout;
uint32_t terminateXfer = 1;
uint32_t xferErr;
if (master == true)
{
ret = false;
instance = 2;
SPI_initConfig(instance, test, MCSPI_TEST_CHN, false);
/* Initialize SPI handle */
SPI_Params_init(&spiParams);
spiParams.transferTimeout = timeout;
spi = SPI_open(instance, &spiParams);
if (spi == NULL)
{
SPI_log("Error initializing SPI\n");
goto Err;
}
else
{
SPI_log("SPI initialized\n");
}
/* Initialize slave SPI transaction structure */
transaction.count = 10;
transaction.arg = (void *)&terminateXfer;
transaction.txBuf = (void *)masterTxBuffer;
transaction.rxBuf = (void *)masterRxBuffer;
/* Initiate SPI transfer */
SPI_test_xfer_ctrl(spi, 1);
transferOK = SPI_transfer((SPI_Handle)spi, &transaction);
if(transferOK)
{
SPI_test_xfer_ctrl(spi, 0);
SPI_control(spi, SPI_V0_CMD_GET_XFER_ERR, (void *)&xferErr);
if (xferErr == SPI_XFER_ERR_RXOR)
{
SPI_log("Receive overrun error detected\n");
}
else if (xferErr == SPI_XFER_ERR_BE)
{
SPI_log("Bit error detected\n");
}
else
{
SPI_log("No error detected\n");
}
ret = true;
}
/*
* master sleep for 1 second after each transfer
* to sync with slave transfer
*/
#ifdef USE_BIOS
Task_sleep(1000);
#else
#endif
Err:
if (spi)
{
SPI_close(spi);
}
}
else
{
/* slave do nothing for xfer error test */
ret = true;
}
#else
ret = true;
#endif
return (ret);
}
#ifdef MCSPI_MULT_CHANNEL
static bool SPI_test_multi_channel(void *arg)
{
MCSPI_Handle spi[MCSPI_MAX_NUM_CHN];
MCSPI_Params spiParams;
uint32_t instance, i;
bool ret = false;
uint32_t chn, maxNumChn, testChn;
MCSPI_CallbackFxn cbFxn[MCSPI_MAX_NUM_CHN] = {MCSPI_callback0, MCSPI_callback1, MCSPI_callback2, MCSPI_callback3};
SPI_Tests *test = (SPI_Tests *)arg;
int32_t testId = test->testId;
bool master = test->master;
bool cbMode = test->cbMode;
uint32_t timeout = test->timeout;
if (cbMode == true)
{
/* Create call back semaphore */
SPI_osalSemParamsInit(&cbSemParams);
cbSemParams.mode = SemaphoreP_Mode_BINARY;
}
/* Soc configuration structures indexing starts from 0. If the IP
* instances start with 1, to address proper Configuration
* structure index, McSPI Instance should be substracted with 1
*/
if (master == true)
{
instance = (uint32_t)BOARD_MCSPI_MASTER_INSTANCE - 1;
}
else
{
instance = (uint32_t)BOARD_MCSPI_SLAVE_INSTANCE - 1;
}
testChn = MCSPI_TEST_CHN;
SPI_initConfig(instance, test, testChn, false);
/* Initialize SPI handle */
MCSPI_Params_init(&spiParams);
if (master == false)
{
spiParams.mode = SPI_SLAVE;
}
if (cbMode == true)
{
spiParams.transferMode = SPI_MODE_CALLBACK;
}
spiParams.transferTimeout = timeout;
if (testId == SPI_TEST_ID_WORD_LEN)
{
spiParams.dataSize = test->param;
}
if (master == true)
{
maxNumChn = MCSPI_MAX_NUM_CHN;
}
else
{
/* Only 1 channel supported in slave mode */
maxNumChn = 1;
}
for (i = 0; i < maxNumChn; i++)
{
if (master == true)
{
chn = i;
}
else
{
chn = testChn;
}
if (cbMode == true)
{
cbSem[chn] = SPI_osalCreateBlockingLock(0, &cbSemParams);
spiParams.transferCallbackFxn = cbFxn[chn];;
}
spi[chn] = MCSPI_open(instance, chn, &spiParams);
if (spi[chn] == NULL)
{
SPI_log("Error initializing SPI instance %d channel %d\n",
instance, chn);
goto Err;
}
else
{
SPI_log("SPI instance %d channel %d\n",
instance, chn);
}
}
for (i = 0; i < SPI_NUM_XFERS; i++)
{
if (SPI_test_mst_slv_xfer((void *)(spi[testChn]), test, spi_test_xfer_len[i], true) == false)
{
goto Err;
}
if ((master == true) && (testId < SPI_TEST_ID_LOOPBACK))
{
/*
* master sleep for 1 second after each transfer
* to sync with slave transfer
*/
#ifdef USE_BIOS
Task_sleep(1000);
#else
#endif
}
}
ret = true;
Err:
for (i = 0; i < maxNumChn; i++)
{
if (master == true)
{
chn = i;
}
else
{
chn = testChn;
}
if (spi[chn])
{
MCSPI_close(spi[chn]);
}
if (cbSem[chn])
{
SPI_osalDeleteBlockingLock(cbSem[chn]);
cbSem[chn] = NULL;
}
}
return (ret);
}
#endif
void SPI_test_print_test_desc(SPI_Tests *test)
{
char testId[16] = {0, };
/* Print unit test ID */
sprintf(testId, "%d", test->testId);
SPI_log("\r\n SPI UT %s\r\n", testId);
/* Print test description */
SPI_log("\r\n %s\r\n", test->testDesc);
}
SPI_Tests Spi_tests_master[] =
{
/* testFunc testID master pollMode cbMode dmaMode timeout testDesc */
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in dma mode", },
#endif
{SPI_test_single_channel, SPI_TEST_ID_INT, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_POLL, true, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in polling mode"},
{SPI_test_single_channel, SPI_TEST_ID_CB, true, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA_CB, true, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in dma callback mode", },
#endif
{SPI_test_xfer_error, SPI_TEST_ID_XFER_ERR, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master transfer error test in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_PHA_POL, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master phase polarity test in non-dma interrupt mode", 1, },
#ifdef MCSPI_MULT_CHANNEL
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in dma mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_MC_INT, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in non-dma interrupt mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_POLL, true, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in polling mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_CB, true, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA_CB, true, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in dma callback mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_TX_ONLY, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel TX_ONLY test", 0, },
#endif
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_WORD_LEN, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master data size test in loopback dma mode", SPI_TEST_DATA_SIZE, },
#endif
{SPI_test_single_channel, SPI_TEST_ID_WORD_LEN, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master data size test in loopback mode", SPI_TEST_DATA_SIZE, },
#ifdef MCSPI_MULT_CHANNEL
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_TRIG_LVL, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master multi channel FIFO trigger level test in loopback dma mode", SPI_TEST_TRIG_LVL, },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_TRIG_LVL, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master multi channel FIFO trigger level test in loopback mode", SPI_TEST_TRIG_LVL, },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_TCS, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel TCS test in dma mode", SPI_TEST_TCS, },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_TCS, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel TCS test", SPI_TEST_TCS, },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_INIT_DELAY, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel init delay test in dma mode", SPI_TEST_INIT_DELAY, },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_INIT_DELAY, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel init delay test", SPI_TEST_INIT_DELAY, },
#endif
/* NOTE: Timeout Test case should be executed as the final test, as this test requires no transaction on the data lines
* for the timeout to happen */
{SPI_test_single_channel, SPI_TEST_ID_TIMEOUT, false, false, false, false, SPI_TIMEOUT_VALUE, "\r\n SPI timeout test in interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_TIMEOUT_POLL, false, true, false, false, SPI_TIMEOUT_VALUE, "\r\n SPI timeout test in polling mode", },
{NULL, },
};
SPI_Tests Spi_tests_slave[] =
{
/* testFunc testID master pollMode cbMode dmaMode, timeout testDesc */
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA, false, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in dma mode", },
#endif
{SPI_test_single_channel, SPI_TEST_ID_INT, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_POLL, false, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in polling mode", },
{SPI_test_single_channel, SPI_TEST_ID_CB, false, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA_CB, false, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in dma callback mode", },
#endif
{SPI_test_xfer_error, SPI_TEST_ID_XFER_ERR, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI slave transfer error test in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_PHA_POL, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI slave phase polarity test in non-dma interrupt mode", 1, },
#ifdef MCSPI_MULT_CHANNEL
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA, false, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave multi channel in dma mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_MC_INT, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave multi channel in non-dma interrupt mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_POLL, false, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in polling mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_CB, false, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA_CB, false, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in dma callback mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_RX_ONLY, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave multi channel RX_ONLY test", 0, },
#endif
{NULL, },
};
/*
* ======== slaveTaskFxn ========
* The task is part of separate slave example project.
* To test slave mode example, slave task has to be
* ready for master. Slave SPI sends a message to master
* while receiving message from master.
*/
#ifdef USE_BIOS
Void slaveTaskFxn (UArg arg0, UArg arg1)
#else
void slaveTaskFxn()
#endif
{
uint32_t i;
bool testFail = false;
SPI_Tests *test;
SPI_init();
for (i = 0; ; i++)
{
if (evmAM570x == true)
{
/* Slave mode test not supported on AM570x EVM */
break;
}
test = &Spi_tests_slave[i];
if (test->testFunc == NULL)
break;
if (test->testId >= SPI_TEST_ID_LOOPBACK)
{
/* bypass the loopback test for slave task */
break;
}
SPI_test_print_test_desc(test);
if (test->testFunc((void *)test) == true)
{
SPI_log("\r\n %s have passed\r\n", test->testDesc);
}
else
{
SPI_log("\r\n %s have failed\r\n", test->testDesc);
testFail = true;
break;
}
}
if(testFail == true)
{
SPI_log("\n Some tests have failed. \n");
}
else
{
SPI_log("\n All tests have passed. \n");
}
SPI_log("Done\n");
while (true)
{
}
}
/*
* ======== masterTaskFxn ========
* This task is part of master example project.
* Slave task has to ensure transaction ready.
* Master SPI sends a message to slave and
* receives message from slave.
*/
#ifdef USE_BIOS
Void masterTaskFxn (UArg arg0, UArg arg1)
#else
void masterTaskFxn()
#endif
{
uint32_t i;
bool testFail = false;
SPI_Tests *test;
SPI_init();
//for (i = 0; ; i++)
for (i = 3; ; i++) // FL: #1: change for Anping
{
test = &Spi_tests_master[i];
if (test->testFunc == NULL)
break;
#if defined (SOC_AM65XX) || defined(SOC_J721E)
if ((test->testId < SPI_TEST_ID_LOOPBACK) &&
(test->testId != SPI_TEST_ID_TIMEOUT) &&
(test->testId != SPI_TEST_ID_TIMEOUT_POLL))
continue;
#endif
if (evmAM570x == true)
{
/* Only loopback test supported on AM570x EVM */
if ((test->testId < SPI_TEST_ID_LOOPBACK) &&
(test->testId != SPI_TEST_ID_TIMEOUT) &&
(test->testId != SPI_TEST_ID_TIMEOUT_POLL))
continue;
}
SPI_test_print_test_desc(test);
if (test->testFunc((void *)test) == true)
{
SPI_log("\r\n %s have passed\r\n", test->testDesc);
}
else
{
SPI_log("\r\n %s have failed\r\n", test->testDesc);
testFail = true;
break;
}
}
if(testFail == true)
{
SPI_log("\n Some tests have failed. \n");
}
else
{
SPI_log("\n All tests have passed. \n");
}
SPI_log("Done\n");
while (true)
{
}
}
/*
* ======== main ========
*/
int main(void)
{
/* Call board init functions */
Board_initCfg boardCfg;
Board_STATUS boardStatus;
#if defined (evmK2G)
SPI_v0_HWAttrs spi_cfg;
uint8_t instance;
Board_SoCInfo socInfo;
#endif
#if defined (idkAM571x)
Board_IDInfo id;
#endif
#ifdef USE_BIOS
#if defined(SOC_AM335x) || defined (SOC_AM437x) || defined (SOC_AM65XX) || defined(SOC_J721E)
Task_Handle task;
Error_Block eb;
Error_init(&eb);
#if defined (MCSPI_SLAVE_TASK)
task = Task_create(slaveTaskFxn, NULL, &eb);
#elif defined (MCSPI_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 */
#endif /* #ifdef USE_BIOS */
boardCfg = BOARD_INIT_PINMUX_CONFIG |
BOARD_INIT_MODULE_CLOCK |
BOARD_INIT_UART_STDIO;
boardStatus = Board_init(boardCfg);
if (boardStatus != BOARD_SOK)
{
return (0);
}
#if defined(SOC_AM65XX) || defined(SOC_J721E)
#if defined (__TI_ARM_V7R4__)
/* Configure the MCU SPI0_D1 pinmux, since it is not set by default in board */
HW_WR_REG32((WKUP_PINMUX_REG_BASE + MCU_SPI0_D1_PADCFG_OFFSET), PIN_MODE(0) | \
((PIN_PULL_DISABLE | PIN_INPUT_ENABLE) & (~PIN_PULL_DIRECTION)));
/* Configure the MCU SPI0_CLK pinmux to support loopback */
HW_WR_REG32((WKUP_PINMUX_REG_BASE + MCU_SPI0_CLK_PADCFG_OFFSET), PIN_MODE(0) | \
((PIN_PULL_DISABLE | PIN_INPUT_ENABLE) & (~PIN_PULL_DIRECTION)));
#endif
#endif
#if defined (idkAM571x)
boardStatus = Board_getIDInfo(&id);
if (boardStatus != BOARD_SOK)
{
return (0);
}
/* Check if is DRA (AM570x) SoC */
if ((id.boardName[0] == 'D') &&
(id.boardName[1] == 'R') &&
(id.boardName[2] == 'A'))
{
evmAM570x = true;
}
#endif
#if defined(iceAMIC110)
/* GPIO initialization */
GPIO_init();
/* Set BUS_Switch_ENABLE pin to low for enabling the switch */
GPIO_write((GPIO_BUS_SWITCH_ENABLE_OFFSET), GPIO_PIN_VAL_LOW);
#endif
#if defined (evmK2G)
/* Read the SoC info to get the System clock value */
Board_getSoCInfo(&socInfo);
if(socInfo.sysClock != BOARD_SYS_CLK_DEFAULT)
{
/* Since this is a generic SPI test,
* configure the input clock for all the available instances */
for (instance = 0; instance < CSL_SPI_CNT; instance++)
{
SPI_socGetInitCfg(instance, &spi_cfg);
/* Update the I2C functional clock based on CPU clock - 1G or 600MHz */
spi_cfg.inputClkFreq = socInfo.sysClock/SPI_MODULE_CLOCK_DIVIDER;
SPI_socSetInitCfg(instance, &spi_cfg);
}
}
#endif
#ifdef USE_BIOS
/* Start BIOS */
BIOS_start();
#else
#ifdef MCSPI_MASTER_TASK
masterTaskFxn();
#else
slaveTaskFxn();
#endif
#endif
return (0);
}
#if defined(BUILD_MPU) || defined (__C7100__)
extern void Osal_initMmuDefault(void);
void InitMmu(void)
{
Osal_initMmuDefault();
}
#endif
Anping,
Do you have the UART stdio initialization parameter set for your Board_init() function call?
boardCfg = BOARD_INIT_PINMUX_CONFIG |
BOARD_INIT_MODULE_CLOCK |
BOARD_INIT_UART_STDIO;
Anping,
Here's my understanding of the situation:
At this point I'm not sure what else I can do to help. I think the best path forward is if you try to debug the application on your own, or figure out a way to share a toy example with me that shows a problem with TI's software.
Regards,
Frank
Hi Frank
I found the root cause for UART_printf to crash. If you put UART_printf in both callback function and after SPI_transfer. It will crash to call UART_printf after SPI_transfer. I think there is a bug in UART_printf. I still have no clue about why UART_open return NULL because it treat as UART already open. Thanks
Hi Frank
I send you a zip file which include CCS project yesterday under AM3358: UART open base address. It show solved but not. Please see post there to know more detail. Thanks
Anping,
>> If you put UART_printf in both callback function and after SPI_transfer. It will crash to call UART_printf after SPI_transfer. I think there is a bug in UART_printf. I
Do you have a toy example which demonstrates the behavior?
Regards,
Frank
Hi Frank
I use C:\ti\pdk_am335x_1_0_16\packages\MyExampleProjects\MCSPI_SlaveMode_MasterExample_bbbAM335x_armExampleProject to repeat the issue. I add UART_printf in both callback function and after SPI_transfer. It will crash to call UART_printf after SPI_transfer. I don't have a toy example which demonstrates the behavior. Thanks
Anping,
Can you please send me your code which causes the crash? I understand you're saying I only need to modify a couple of lines of code, but I think it would eliminate any possibility of code mismatch if you could share an example.
Regards,
Frank
https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/791/MCSPI_5F00_SlaveMode_5F00_MasterExample_5F00_bbbAM335x_5F00_armExampleProject.7z
Hi Frank
I send you your modified example project. I add line 472
UART_printf("\nSPI_callback!\n");
line 832
UART_printf("\n SPI_osalPendLock!\n");
and line 1501
for (i = 3; ; i++)
It crash when it execute line 832. Thanks
Anping,
The .zip file only contains a CCS project. There aren't any source files.
I tried to modify the file according to your instructions. Can you please verify the file is correct?
/**
* \file main_mcspi_slave_mode.c
*
* \brief The application Demonstrate the MCSPI slave mode functionality.
* This application transmits data from master to slave and at the
* same instance data from slave will be 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:
* MasterSPI_SCLK----SlaveSPI_SCLK
* MasterSPI_D0------SlaveSPI_D1
* MasterSPI_D1------SlaveSPI_D0
* MasterSPI_CS------SlaveSPI_CS
*
* \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:
* SPI initialized
* Slave: PASS: Txd from master SPI
*
* At master end console:
* SPI initialized
* Master: PASS: Txd from slave SPI
* Done
*/
/*
* Copyright (C) 2016 - 2019 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>
#ifdef USE_BIOS
/* XDCtools Header files */
#include <xdc/std.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>
#endif /* #ifdef USE_BIOS */
/* 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/spi/soc/SPI_soc.h>
#include <ti/drv/spi/src/SPI_osal.h>
#include <ti/drv/spi/SPI.h>
#include "SPI_log.h"
#if defined(iceAMIC110)
#include <ti/drv/gpio/GPIO.h>
#include <ti/drv/gpio/soc/GPIO_soc.h>
#endif
#include <ti/board/board.h>
#ifdef SOC_AM65XX
#include <ti/csl/soc/am65xx/src/cslr_soc_baseaddress.h>
#include <ti/csl/soc/am65xx/src/cslr_wkup_ctrl_mmr.h>
#elif defined(SOC_J721E)
#include <ti/csl/soc/j721e/src/cslr_soc_baseaddress.h>
#include <ti/csl/soc/j721e/src/cslr_wkup_ctrl_mmr.h>
#endif
#ifdef SPI_DMA_ENABLE
#include <ti/osal/CacheP.h>
#if defined (SOC_AM65XX) || defined(SOC_J721E)
#include <ti/drv/udma/udma.h>
#else
/* EDMA3 Header files */
#include <ti/sdo/edma3/drv/edma3_drv.h>
#include <ti/sdo/edma3/rm/edma3_rm.h>
#include <ti/sdo/edma3/rm/sample/bios6_edma3_rm_sample.h>
#if defined(evmK2G)
#include <ti/csl/soc.h>
#endif
static EDMA3_RM_Handle MCSPIApp_edmaInit(void);
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || \
defined(SOC_C6678) || defined(SOC_C6657)
extern EDMA3_RM_InstanceInitConfig sampleInstInitConfig[][EDMA3_MAX_REGIONS];
extern EDMA3_RM_GblConfigParams sampleEdma3GblCfgParams[];
#endif
#endif
#endif
/* Define the SPI test interface */
typedef struct SPI_Tests_s
{
bool (*testFunc)(void *);
int32_t testId;
bool master;
bool pollMode;
bool cbMode;
bool dmaMode;
uint32_t timeout;
char testDesc[80];
uint32_t param;
uint32_t trigLvl;
} SPI_Tests;
/**********************************************************************
************************** Macros ************************************
**********************************************************************/
#define SPI_TIMEOUT_VALUE 5000
/* SPI transfer message definitions */
#define SPI_MSG_LENGTH 26
#define SPI_MSG_LENGTH2 78
#define SPI_NUM_XFERS 2
uint32_t spi_test_xfer_len[SPI_NUM_XFERS] =
{
SPI_MSG_LENGTH,
SPI_MSG_LENGTH2
};
/* Maximum # of channels per SPI instance */
#define MCSPI_MAX_NUM_CHN 4
/* Test channel # */
#define MCSPI_TEST_CHN 0
/* SPI Test definitions */
/* Unit test IDs */
#define SPI_TEST_ID_DMA 0 /* Single-channel DMA mode test */
#define SPI_TEST_ID_INT 1 /* Single-channel interrupt mode test */
#define SPI_TEST_ID_POLL 2 /* Single-channel polling mode test */
#define SPI_TEST_ID_CB 3 /* Single-channel non-DMA callback mode test */
#define SPI_TEST_ID_DMA_CB 4 /* Single-channel DMA callback mode test */
#define SPI_TEST_ID_MC_DMA 5 /* Multi-channel DMA mode test */
#define SPI_TEST_ID_MC_INT 6 /* Multi-channel interrupt mode test */
#define SPI_TEST_ID_MC_POLL 7 /* Multie-channel polling mode test */
#define SPI_TEST_ID_MC_CB 8 /* Multi-channel non-DMA callback mode test */
#define SPI_TEST_ID_MC_DMA_CB 9 /* Multi-channel DMA callback mode test */
#define SPI_TEST_ID_TX_ONLY 10 /* Multi-channel TX only test */
#define SPI_TEST_ID_RX_ONLY 11 /* Multi-channel RX only test */
#define SPI_TEST_ID_XFER_ERR 12 /* Single-channel transfer error test */
#define SPI_TEST_ID_PHA_POL 13 /* Single-channel phase/polarity test */
#define SPI_TEST_ID_TIMEOUT 14 /* Single-channel Timeout test with interrupt enabled */
#define SPI_TEST_ID_TIMEOUT_POLL 15 /* Single-channel Timeout test with polling enabled */
#define SPI_TEST_ID_DMA_CB_CANCEL 16
#define SPI_TEST_ID_CB_CANCEL 17
/* Loopback tests */
#define SPI_TEST_ID_LOOPBACK 20
#define SPI_TEST_ID_WORD_LEN (SPI_TEST_ID_LOOPBACK) /* transfer data size test */
#define SPI_TEST_ID_TRIG_LVL (SPI_TEST_ID_LOOPBACK + 1) /* FIFO trigger level test */
#define SPI_TEST_ID_TCS (SPI_TEST_ID_LOOPBACK + 2) /* Multi-channel chip select time control test */
#define SPI_TEST_ID_INIT_DELAY (SPI_TEST_ID_LOOPBACK + 3) /* Multi-channel 1st transfer init delay test */
/* Transfer data size test parameter, in # of bits per SPI word */
#define SPI_TEST_DATA_SIZE_16 16
#define SPI_TEST_DATA_SIZE_32 32
#if defined(SOC_DRA78x) || defined(SOC_TDA3XX) || defined(SOC_TDA2XX) || defined(SOC_TDA2EX) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined(SOC_AM574x) || defined (SOC_AM572x) || defined (SOC_AM571x) || defined (SOC_AM437x) || defined (SOC_AM335x) || defined (SOC_AM65XX) || defined(SOC_J721E)
#define SPI_TEST_DATA_SIZE SPI_TEST_DATA_SIZE_32
#else
#define SPI_TEST_DATA_SIZE SPI_TEST_DATA_SIZE_16
#endif
#ifdef MCSPI_MULT_CHANNEL
/* Chip select time control test parameter */
#define SPI_TEST_TCS MCSPI_CH0CONF_TCS0_ONECYCLEDLY
/* 1st transfer init delay test parameter */
#define SPI_TEST_INIT_DELAY MCSPI_INITDLY_4
/* FIFO trigger level test parameter, in # of bytes */
#define SPI_TEST_TRIG_LVL 16
#endif
#if defined(SOC_AM65XX) || defined(SOC_J721E)
/* WKUP CTRL base address + offset to beginning of PAD CONFIG section */
#define WKUP_PINMUX_REG_BASE (CSL_WKUP_CTRL_MMR0_CFG0_BASE + \
CSL_WKUP_CTRL_MMR_CFG0_PADCONFIG0)
#define MCU_SPI0_CLK_PADCFG_OFFSET (0x90U)
#define MCU_SPI0_D1_PADCFG_OFFSET (0x98U)
#define PIN_MODE(mode) (mode)
/** \brief Active mode configurations */
/** \brief Resistor disable */
#define PIN_PULL_DISABLE (0x1U << 16U)
/** \brief Pull direction */
#define PIN_PULL_DIRECTION (0x1U << 17U)
/** \brief Receiver enable */
#define PIN_INPUT_ENABLE (0x1U << 18U)
/** \brief Driver disable */
#define PIN_OUTPUT_DISABLE (0x1U << 21U)
/** \brief Wakeup enable */
#define PIN_WAKEUP_ENABLE (0x1U << 29U)
#ifdef SPI_DMA_ENABLE
/*
* Ring parameters
*/
/** \brief Number of ring entries - we can prime this much memcpy operations */
#define UDMA_TEST_APP_RING_ENTRIES (1U)
/** \brief Size (in bytes) of each ring entry (Size of pointer - 64-bit) */
#define UDMA_TEST_APP_RING_ENTRY_SIZE (sizeof(uint64_t))
/** \brief Total ring memory */
#define UDMA_TEST_APP_RING_MEM_SIZE (UDMA_TEST_APP_RING_ENTRIES * \
UDMA_TEST_APP_RING_ENTRY_SIZE)
/**
* \brief UDMA host mode buffer descriptor memory size.
* Make it multiple of 128 byte alignment
*/
#define UDMA_TEST_APP_DESC_SIZE (sizeof(CSL_UdmapCppi5HMPD) + (128U - sizeof(CSL_UdmapCppi5HMPD)))
/*
* UDMA driver objects
*/
struct Udma_DrvObj gUdmaDrvObj;
struct Udma_ChObj gUdmaTxChObj;
struct Udma_ChObj gUdmaRxChObj;
struct Udma_EventObj gUdmaTxCqEventObj;
struct Udma_EventObj gUdmaRxCqEventObj;
Udma_DrvHandle gDrvHandle = NULL;
/*
* UDMA Memories
*/
static uint8_t gTxRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gTxCompRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gUdmaTxHpdMem[UDMA_TEST_APP_DESC_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gRxRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gRxCompRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gUdmaRxHpdMem[UDMA_TEST_APP_DESC_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static SPI_dmaInfo gUdmaInfo;
Udma_DrvHandle MCSPIApp_udmaInit(SPI_v1_HWAttrs *cfg)
{
int32_t retVal = UDMA_SOK;
Udma_InitPrms initPrms;
uint32_t instId;
if (gDrvHandle == NULL)
{
/* UDMA driver init */
#if defined (__aarch64__)
instId = UDMA_INST_ID_MAIN_0;
#else
instId = UDMA_INST_ID_MCU_0;
#endif
UdmaInitPrms_init(instId, &initPrms);
retVal = Udma_init(&gUdmaDrvObj, &initPrms);
if(UDMA_SOK == retVal)
{
gDrvHandle = &gUdmaDrvObj;
}
}
if(gDrvHandle != NULL)
{
gDrvHandle = &gUdmaDrvObj;
gUdmaInfo.txChHandle = (void *)&gUdmaTxChObj;
gUdmaInfo.rxChHandle = (void *)&gUdmaRxChObj;
gUdmaInfo.txRingMem = (void *)&gTxRingMem[0];
gUdmaInfo.cqTxRingMem = (void *)&gTxCompRingMem[0];
gUdmaInfo.rxRingMem = (void *)&gRxRingMem[0];
gUdmaInfo.cqRxRingMem = (void *)&gRxCompRingMem[0];
gUdmaInfo.txHpdMem = (void *)&gUdmaTxHpdMem[0];
gUdmaInfo.rxHpdMem = (void *)&gUdmaRxHpdMem[0];
gUdmaInfo.txEventHandle = (void *)&gUdmaTxCqEventObj;
gUdmaInfo.rxEventHandle = (void *)&gUdmaRxCqEventObj;
cfg->dmaInfo = &gUdmaInfo;
}
return (gDrvHandle);
}
int32_t MCSPI_udma_deinit(void)
{
int32_t retVal = UDMA_SOK;
if (gDrvHandle != NULL)
{
retVal = Udma_deinit(gDrvHandle);
if(UDMA_SOK == retVal)
{
gDrvHandle = NULL;
}
}
return (retVal);
}
#endif
#endif /* #if defined(SOC_AM65XX) || defined(SOC_J721E) */
/**********************************************************************
************************** Global Variables **************************
**********************************************************************/
#if (defined(_TMS320C6X) || defined (__TI_ARM_V7M4__))
#pragma DATA_ALIGN (masterRxBuffer, 128)
unsigned char masterRxBuffer[128];
#pragma DATA_ALIGN (slaveRxBuffer, 128)
unsigned char slaveRxBuffer[128];
#else
unsigned char masterRxBuffer[128] __attribute__ ((aligned (128)));
unsigned char slaveRxBuffer[128] __attribute__ ((aligned (128)));
#endif
#define CANCEL_TX_LEN (1024)
unsigned char cancelTxBuff[CANCEL_TX_LEN];
unsigned char cancelRxBuff[CANCEL_TX_LEN];
unsigned char masterTxBuffer[128] = "PASS: Txd from master SPI PASS: Txd from master SPI PASS: Txd from master SPI ";
unsigned char slaveTxBuffer[128] = "PASS: Txd from slave SPI PASS: Txd from slave SPI PASS: Txd from slave SPI ";
#if defined(iceAMIC110)
#define GPIO_BUS_SWITCH_ENABLE_OFFSET (0)
#define GPIO_PIN_VAL_LOW (0U)
#define GPIO_PIN_VAL_HIGH (1U)
#define GPIO_BUS_SWITCH_ENABLE_PIN_NUM (0x15)
#define GPIO_BUS_SWITCH_ENABLE_PORT_NUM (0x2)
/* GPIO Driver board specific pin configuration structure */
GPIO_PinConfig gpioPinConfigs[] = {
/* Boot switch enable pin to control the buffer for routing McSPI
* lines to Launchpad header on iceAMIC110 board */
GPIO_DEVICE_CONFIG((GPIO_BUS_SWITCH_ENABLE_PORT_NUM + 1), GPIO_BUS_SWITCH_ENABLE_PIN_NUM) |
GPIO_CFG_IN_INT_NONE | GPIO_CFG_OUTPUT,
};
/* GPIO Driver call back functions */
GPIO_CallbackFxn gpioCallbackFunctions[] = {
NULL
};
/* GPIO Driver configuration structure */
GPIO_v1_Config GPIO_v1_config = {
gpioPinConfigs,
gpioCallbackFunctions,
sizeof(gpioPinConfigs) / sizeof(GPIO_PinConfig),
sizeof(gpioCallbackFunctions) / sizeof(GPIO_CallbackFxn),
0x1U,
};
#endif /* #if defined(iceAMIC110) */
/* Transaction data */
SPI_Transaction transaction;
/* Callback mode variables */
SemaphoreP_Params cbSemParams;
SemaphoreP_Handle cbSem[MCSPI_MAX_NUM_CHN] = {NULL, NULL, NULL, NULL};
bool evmAM570x = false;
#ifdef SPI_DMA_ENABLE
#if !(defined (SOC_AM65XX) || defined(SOC_J721E))
EDMA3_RM_Handle gEdmaHandle = NULL;
/**
* \brief Function to initialize the edma driver and get the handle to the
* edma driver;
*/
static EDMA3_RM_Handle MCSPIApp_edmaInit(void)
{
EDMA3_DRV_Result edmaResult = EDMA3_DRV_E_INVALID_PARAM;
uint32_t edma3Id;
if (gEdmaHandle != NULL)
{
return (gEdmaHandle);
}
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || \
defined(SOC_C6678) || defined(SOC_C6657)
uint32_t edmaEvent[2], i, chnMapping, chnMappingIdx;
/* For Keystone devices, edm3Id is SPI instance and SoC specific */
SPI_getEdmaInfo(BOARD_MCSPI_MASTER_INSTANCE - 1, &edma3Id, edmaEvent);
/* Set the RX/TX ownDmaChannels and dmaChannelHwEvtMap */
for (i = 0; i < 2; i++)
{
chnMapping = edmaEvent[i];
if (chnMapping < 32)
chnMappingIdx = 0;
else
{
chnMapping -= 32;
chnMappingIdx = 1;
}
sampleInstInitConfig[edma3Id][0].ownDmaChannels[chnMappingIdx] |= (1 << chnMapping);
sampleInstInitConfig[edma3Id][0].ownTccs[chnMappingIdx] |= (1 << chnMapping);
sampleInstInitConfig[edma3Id][0].ownPaRAMSets[chnMappingIdx] |= (1 << chnMapping);
sampleEdma3GblCfgParams[edma3Id].dmaChannelHwEvtMap[chnMappingIdx] |= (1 << chnMapping);
}
#endif
#if defined(SOC_AM574x) || defined(SOC_AM572x)|| defined(SOC_AM571x) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined (SOC_DRA78x) || defined (SOC_AM335x) || defined (SOC_AM437x)
edma3Id = 0;
#endif
gEdmaHandle = (EDMA3_RM_Handle)edma3init(edma3Id, &edmaResult);
#ifdef USE_BIOS
if (edmaResult != EDMA3_DRV_SOK)
{
/* Report EDMA Error */
System_printf("\nEDMA driver initialization FAIL\n");
}
else
{
System_printf("\nEDMA driver initialization PASS.\n");
}
#endif
return(gEdmaHandle);
}
#endif
#endif
/* Callback mode functions */
void SPI_callback(SPI_Handle handle, SPI_Transaction *transaction)
{
UART_printf("\nSPI_callback!\n"); // FL: Anping
SPI_osalPostLock(cbSem[0]);
}
#ifdef MCSPI_MULT_CHANNEL
void MCSPI_callback0(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[0]);
}
void MCSPI_callback1(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[1]);
}
void MCSPI_callback2(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[2]);
}
void MCSPI_callback3(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[3]);
}
#endif
#ifdef MCSPI_MULT_CHANNEL
/*
* ======== SPI init config ========
*/
static void SPI_initConfigDefault(SPI_HWAttrs *cfg, uint32_t chn)
{
cfg->chNum = chn;
cfg->chnCfg[chn].tcs = MCSPI_CS_TCS_0PNT5_CLK;
cfg->chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_6;
cfg->chnCfg[chn].trMode = MCSPI_TX_RX_MODE;
cfg->initDelay = MCSPI_INITDLY_0;
#if defined (SOC_AM335x)
cfg->rxTrigLvl = MCSPI_RX_TX_FIFO_SIZE / 2;
cfg->txTrigLvl = MCSPI_RX_TX_FIFO_SIZE / 2;
#else
cfg->rxTrigLvl = MCSPI_RX_TX_FIFO_SIZE;
cfg->txTrigLvl = MCSPI_RX_TX_FIFO_SIZE;
#endif
}
#endif
/*
* ======== SPI init config ========
*/
static void SPI_initConfig(uint32_t instance, SPI_Tests *test, uint32_t chn, bool multiChn)
{
SPI_HWAttrs spi_cfg;
int32_t testId = test->testId;
bool pollMode = test->pollMode;
#ifdef SPI_DMA_ENABLE
bool dmaMode = test->dmaMode;
#endif
/* Get the default SPI init configurations */
SPI_socGetInitCfg(instance, &spi_cfg);
#ifdef MCSPI_MULT_CHANNEL
SPI_initConfigDefault(&spi_cfg, chn);
#endif
/*
* Set blocking mode (dma mode or non-dma interrupt mode)
* or callback mode
*/
if (pollMode == true)
{
/* polling mode */
spi_cfg.enableIntr = false;
/* SPI DMA mode is not supported in polling mode */
spi_cfg.edmaHandle = NULL;
spi_cfg.dmaMode = FALSE;
}
else
{
/* interrupt enabled */
spi_cfg.enableIntr = true;
#if defined(SOC_DRA78x) || defined(SOC_TDA3XX) || defined(SOC_TDA2XX) || defined(SOC_TDA2PX) || defined(SOC_TDA2EX) || defined (SOC_DRA75x) || \
defined(SOC_AM574x) || defined (SOC_AM572x) || defined (SOC_AM571x) || defined (SOC_AM437x) || defined (SOC_AM335x) || \
defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || \
defined(SOC_C6678) || defined(SOC_C6657) || defined (SOC_AM65XX) || defined(SOC_J721E)
#ifdef SPI_DMA_ENABLE
if (dmaMode == true)
{
/* Set the DMA related init config */
#if defined (SOC_AM65XX) || defined(SOC_J721E)
spi_cfg.edmaHandle = (void *)MCSPIApp_udmaInit(&spi_cfg);
#else
spi_cfg.edmaHandle = MCSPIApp_edmaInit();
#endif
spi_cfg.dmaMode = TRUE;
spi_cfg.enableIntr = FALSE;
}
else
#endif
{
spi_cfg.edmaHandle = NULL;
spi_cfg.dmaMode = FALSE;
}
#endif
}
#ifdef MCSPI_MULT_CHANNEL
switch(testId)
{
case (SPI_TEST_ID_TX_ONLY):
spi_cfg.chnCfg[chn].trMode = MCSPI_TX_ONLY_MODE;
/* Data line 0 TX enabled, data line 1 RX enabled TX disabled */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_6;
break;
case (SPI_TEST_ID_RX_ONLY):
spi_cfg.chnCfg[chn].trMode = MCSPI_RX_ONLY_MODE;
/* Data line 0 TX disabled, data line 1 RX enabled TX disabled */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_7;
break;
case (SPI_TEST_ID_TRIG_LVL):
spi_cfg.rxTrigLvl = test->param;
spi_cfg.txTrigLvl = test->param;
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
break;
case (SPI_TEST_ID_TCS):
spi_cfg.chnCfg[chn].tcs = test->param;
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
break;
case (SPI_TEST_ID_INIT_DELAY):
spi_cfg.initDelay = test->param;
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
break;
default:
break;
}
#ifdef SPI_DMA_ENABLE
if (spi_cfg.txTrigLvl != 0)
{
test->trigLvl = spi_cfg.txTrigLvl;
}
else
{
test->trigLvl = 0;
}
if (spi_cfg.txTrigLvl < spi_cfg.rxTrigLvl)
{
test->trigLvl = spi_cfg.rxTrigLvl;
}
#endif
#endif
if ((testId == SPI_TEST_ID_WORD_LEN) || (testId == SPI_TEST_ID_CB_CANCEL) || (testId == SPI_TEST_ID_DMA_CB_CANCEL))
{
#if defined(SOC_DRA78x) || defined(SOC_TDA3XX) || defined(SOC_TDA2XX) || defined(SOC_TDA2EX) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined (SOC_AM572x) || defined (SOC_AM571x) || defined (SOC_AM574x) || defined (SOC_AM437x) || defined (SOC_AM335x) || defined (SOC_AM65XX) || defined(SOC_J721E)
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
#else
/* enalbe loopback mode */
spi_cfg.loopback = 1;
#endif
}
/* Set the SPI init configurations */
SPI_socSetInitCfg(instance, &spi_cfg);
}
bool SPI_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 uintptr_t l2_global_address (uintptr_t addr)
{
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || defined(SOC_C6678) || defined(SOC_C6657)
#ifdef _TMS320C6X
uint32_t corenum;
/* Get the core number. */
corenum = CSL_chipReadReg (CSL_CHIP_DNUM);
/* Compute the global address. */
return (addr + (0x10000000 + (corenum * 0x1000000)));
#else
return addr;
#endif
#else
return addr;
#endif
}
static void SPI_test_xfer_ctrl(SPI_Handle spi, uint32_t xferEnable)
{
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2E) || defined(SOC_K2L) || defined(SOC_K2G) || defined(SOC_C6678) || defined(SOC_C6657)
uint32_t xferActivate = xferEnable;
SPI_control(spi, SPI_V0_CMD_XFER_ACTIVATE, (void *)&xferActivate);
#endif
}
static bool SPI_test_mst_slv_xfer(void *spi, SPI_Tests *test, uint32_t xferLen, bool multChn)
{
bool transferOK;
uintptr_t addrMasterRxBuf, addrMasterTxBuf, addrSlaveRxBuf, addrSlaveTxBuf, addrCancelTxBuff, addrCancelRxBuff;
bool ret = false;
uint32_t terminateXfer = 1;
int32_t testId = test->testId;
bool master = test->master;
bool cbMode = test->cbMode;
bool dmaMode = test->dmaMode;
uint32_t timeout = test->timeout;
uint32_t transCount, xferBytes, testLen;
unsigned char *srcPtr;
if (dmaMode)
{
addrMasterRxBuf = l2_global_address((uintptr_t)masterRxBuffer);
addrMasterTxBuf = l2_global_address((uintptr_t)masterTxBuffer);
addrSlaveRxBuf = l2_global_address((uintptr_t)slaveRxBuffer);
addrSlaveTxBuf = l2_global_address((uintptr_t)slaveTxBuffer);
addrCancelTxBuff = l2_global_address((uintptr_t)cancelTxBuff);
addrCancelRxBuff = l2_global_address((uintptr_t)cancelRxBuff);
}
else
{
addrMasterRxBuf = (uintptr_t)masterRxBuffer;
addrMasterTxBuf = (uintptr_t)masterTxBuffer;
addrSlaveRxBuf = (uintptr_t)slaveRxBuffer;
addrSlaveTxBuf = (uintptr_t)slaveTxBuffer;
addrCancelTxBuff = (uintptr_t)cancelTxBuff;
addrCancelRxBuff = (uintptr_t)cancelRxBuff;
}
memset(cancelTxBuff, 0, sizeof(cancelTxBuff));
memset(cancelRxBuff, 0, sizeof(cancelRxBuff));
memset(masterRxBuffer, 0, sizeof(masterRxBuffer));
memset(slaveRxBuffer, 0, sizeof(slaveRxBuffer));
#ifdef SPI_DMA_ENABLE
#if !defined (__aarch64__)
if (dmaMode)
{
CacheP_wbInv((void *)addrMasterRxBuf, (int32_t)sizeof(masterRxBuffer));
CacheP_wbInv((void *)addrSlaveRxBuf, (int32_t)sizeof(slaveRxBuffer));
CacheP_wbInv((void *)addrCancelTxBuff, (int32_t)sizeof(cancelTxBuff));
CacheP_wbInv((void *)addrCancelRxBuff, (int32_t)sizeof(cancelRxBuff));
}
#endif
#endif
testLen = xferLen;
#if defined(SOC_AM574x) || defined(SOC_AM572x)|| defined(SOC_AM571x) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined (SOC_DRA78x) || defined (SOC_AM335x) || defined (SOC_AM437x) || defined (SOC_AM65XX) || defined(SOC_J721E)
#ifdef SPI_DMA_ENABLE
if (dmaMode == true)
{
if (testLen > test->trigLvl)
{
/* always transfer data bytes of multiple trigger level */
testLen = (xferLen / test->trigLvl) * test->trigLvl;
}
else
{
/* transfer data bytes of 1 trigger level */
testLen = test->trigLvl;
}
}
#endif
#endif
if (testId == SPI_TEST_ID_WORD_LEN)
{
/*
* Word length can be 8/16/32 bits,
* calculate the SPI word count
*/
transCount = testLen / (test->param / 8);
xferBytes = transCount * (test->param / 8);
}
else
{
/* Default word length is 8-bit */
transCount = testLen;
xferBytes = testLen;
}
/* Initialize slave SPI transaction structure */
transaction.count = transCount;
transaction.arg = (void *)&terminateXfer;
if (master == true)
{
if ((testId == SPI_TEST_ID_CB_CANCEL) || (testId == SPI_TEST_ID_DMA_CB_CANCEL))
{
transaction.txBuf = (void *)addrCancelTxBuff;
transaction.rxBuf = (void *)addrCancelRxBuff;
}
else
{
transaction.txBuf = (void *)addrMasterTxBuf;
transaction.rxBuf = (void *)addrMasterRxBuf;
}
}
else
{
transaction.txBuf = (void *)addrSlaveTxBuf;
transaction.rxBuf = (void *)addrSlaveRxBuf;
}
/* Initiate SPI transfer */
SPI_test_xfer_ctrl(spi, 1);
#ifdef MCSPI_MULT_CHANNEL
if (multChn == true)
{
transferOK = MCSPI_transfer((MCSPI_Handle)spi, &transaction);
}
else
#endif
{
transferOK = SPI_transfer((SPI_Handle)spi, &transaction);
if ((testId == SPI_TEST_ID_CB_CANCEL) || (testId == SPI_TEST_ID_DMA_CB_CANCEL))
{
SPI_transferCancel(spi);
}
}
if(transferOK)
{
if (cbMode)
{
if (SPI_osalPendLock(cbSem[0], timeout) != SemaphoreP_OK)
{
goto Err;
}
UART_printf("\n SPI_osalPendLock!\n"); // FL: Anping
}
SPI_test_xfer_ctrl(spi, 0);
/* Get the actual transfer bytes */
if (testId == SPI_TEST_ID_WORD_LEN)
{
xferBytes = transaction.count * (test->param / 8);
}
else
{
xferBytes = transaction.count;
}
if ((testId == SPI_TEST_ID_CB_CANCEL) || (testId == SPI_TEST_ID_DMA_CB_CANCEL))
{
if (transaction.status == SPI_TRANSFER_CANCELED)
{
SPI_log("\n SPI Transfer Canceled!\n");
}
else
{
SPI_log("\n SPI Transfer Cancel failed!\n");
goto Err;
}
}
else if (testId != SPI_TEST_ID_TX_ONLY)
{
if (master == true)
{
if (testId >= SPI_TEST_ID_LOOPBACK)
{
srcPtr = masterTxBuffer;
}
else
{
srcPtr = slaveTxBuffer;
}
/* master mode, verify master recieved data match with slave sent data */
if (SPI_verify_data(masterRxBuffer, srcPtr, xferBytes) == false)
{
goto Err;
}
/* Print contents of master receive buffer */
SPI_log("Master: %s\n", masterRxBuffer);
}
else
{
/* slave mode, verify slave recieved data match with master sent data */
if (SPI_verify_data(slaveRxBuffer, masterTxBuffer, xferBytes) == false)
{
goto Err;
}
/* Print contents of slave receive buffer */
SPI_log("Slave: %s\n", slaveRxBuffer);
}
}
}
else
{
if ((testId == SPI_TEST_ID_TIMEOUT) || (testId == SPI_TEST_ID_TIMEOUT_POLL))
{
if (transaction.status == SPI_TRANSFER_TIMEOUT)
{
SPI_log("SPI Slave transfer Timed out for transfer length %d\n", xferLen);
}
else
{
SPI_log("Unsuccessful slave SPI transfer");
goto Err;
}
}
else
{
SPI_log("Unsuccessful slave SPI transfer");
goto Err;
}
}
ret = true;
Err:
return (ret);
}
static bool SPI_test_single_channel(void *arg)
{
SPI_Handle spi;
SPI_Params spiParams;
uint32_t instance, i, modeIndex, SPI_modeIndex, xferLen, num_xfers;
bool ret = false;
SPI_Tests *test = (SPI_Tests *)arg;
int32_t testId = test->testId;
bool master = test->master;
bool cbMode = test->cbMode;
uint32_t timeout = test->timeout;
SPI_FrameFormat frameFormat[]=
{
SPI_POL0_PHA0, /*!< SPI mode Polarity 0 Phase 0 */
SPI_POL0_PHA1, /*!< SPI mode Polarity 0 Phase 1 */
SPI_POL1_PHA0, /*!< SPI mode Polarity 1 Phase 0 */
SPI_POL1_PHA1, /*!< SPI mode Polarity 1 Phase 1 */
};
if (cbMode == true)
{
/* Create call back semaphore */
SPI_osalSemParamsInit(&cbSemParams);
cbSemParams.mode = SemaphoreP_Mode_BINARY;
cbSem[0] = SPI_osalCreateBlockingLock(0, &cbSemParams);
}
if ((testId == SPI_TEST_ID_WORD_LEN) && (test->dmaMode == false))
{
SPI_modeIndex = 4;
}
else
{
SPI_modeIndex = 1;
}
/* In case of SPI_TEST_ID_PHA_POL all SPI modes need to be tested */
for (modeIndex = 0; modeIndex < SPI_modeIndex; modeIndex++)
{
ret = false;
/* Soc configuration structures indexing starts from 0. If the IP
* instances start with 1, to address proper Configuration
* structure index, McSPI Instance should be substracted with 1
*/
if (master == true)
{
instance = (uint32_t)BOARD_MCSPI_MASTER_INSTANCE - 1;
}
else
{
instance = (uint32_t)BOARD_MCSPI_SLAVE_INSTANCE - 1;
}
SPI_initConfig(instance, test, MCSPI_TEST_CHN, false);
/* Initialize SPI handle */
SPI_Params_init(&spiParams);
if (master == false)
{
spiParams.mode = SPI_SLAVE;
}
if (cbMode == true)
{
spiParams.transferMode = SPI_MODE_CALLBACK;
spiParams.transferCallbackFxn = SPI_callback;
}
spiParams.transferTimeout = timeout;
if (testId == SPI_TEST_ID_PHA_POL)
{
spiParams.frameFormat = (SPI_FrameFormat)(test->param);
}
if (testId == SPI_TEST_ID_WORD_LEN)
{
if(test->dmaMode == false)
{
spiParams.frameFormat = frameFormat[modeIndex];
SPI_log("\n%s with SPI Mode %d\n", test->testDesc, spiParams.frameFormat);
}
spiParams.dataSize = test->param;
}
spi = SPI_open(instance, &spiParams);
if (spi == NULL)
{
SPI_log("Error initializing SPI\n");
goto Err;
}
else
{
SPI_log("SPI initialized\n");
}
if ((testId == SPI_TEST_ID_CB_CANCEL) || (testId == SPI_TEST_ID_DMA_CB_CANCEL))
{
num_xfers = 1;
}
else
{
num_xfers = SPI_NUM_XFERS;
}
for (i = 0; i < num_xfers; i++)
{
if ((testId == SPI_TEST_ID_CB_CANCEL) || (testId == SPI_TEST_ID_DMA_CB_CANCEL))
{
xferLen = CANCEL_TX_LEN;
}
else
{
xferLen = spi_test_xfer_len[i];
}
if (SPI_test_mst_slv_xfer((void *)spi, test, xferLen, false) == false)
{
goto Err;
}
if ((testId == SPI_TEST_ID_CB_CANCEL) || (testId == SPI_TEST_ID_DMA_CB_CANCEL))
{
SPI_log("SPI Master Transfer Cancelled!!\n");
}
if ((master == true) && (testId < SPI_TEST_ID_LOOPBACK))
{
/*
* master sleep for 1 second after each transfer
* to sync with slave transfer
*/
#ifdef USE_BIOS
Task_sleep(1000);
#else
#endif
}
}
ret = true;
if (testId == SPI_TEST_ID_WORD_LEN){
if (spi)
{
SPI_close(spi);
}
}
} /* End of for loop */
Err:
if (testId != SPI_TEST_ID_WORD_LEN){
if (spi)
{
SPI_close(spi);
}
}
if (cbSem[0])
{
SPI_osalDeleteBlockingLock(cbSem[0]);
cbSem[0] = NULL;
}
return (ret);
}
static bool SPI_test_xfer_error(void *arg)
{
bool ret;
#if defined(SOC_K2G)
SPI_Handle spi;
SPI_Params spiParams;
bool transferOK;
uint32_t instance;
SPI_Tests *test = (SPI_Tests *)arg;
bool master = test->master;
uint32_t timeout = test->timeout;
uint32_t terminateXfer = 1;
uint32_t xferErr;
if (master == true)
{
ret = false;
instance = 2;
SPI_initConfig(instance, test, MCSPI_TEST_CHN, false);
/* Initialize SPI handle */
SPI_Params_init(&spiParams);
spiParams.transferTimeout = timeout;
spi = SPI_open(instance, &spiParams);
if (spi == NULL)
{
SPI_log("Error initializing SPI\n");
goto Err;
}
else
{
SPI_log("SPI initialized\n");
}
/* Initialize slave SPI transaction structure */
transaction.count = 10;
transaction.arg = (void *)&terminateXfer;
transaction.txBuf = (void *)masterTxBuffer;
transaction.rxBuf = (void *)masterRxBuffer;
/* Initiate SPI transfer */
SPI_test_xfer_ctrl(spi, 1);
transferOK = SPI_transfer((SPI_Handle)spi, &transaction);
if(transferOK)
{
SPI_test_xfer_ctrl(spi, 0);
SPI_control(spi, SPI_V0_CMD_GET_XFER_ERR, (void *)&xferErr);
if (xferErr == SPI_XFER_ERR_RXOR)
{
SPI_log("Receive overrun error detected\n");
}
else if (xferErr == SPI_XFER_ERR_BE)
{
SPI_log("Bit error detected\n");
}
else
{
SPI_log("No error detected\n");
}
ret = true;
}
/*
* master sleep for 1 second after each transfer
* to sync with slave transfer
*/
#ifdef USE_BIOS
Task_sleep(1000);
#else
#endif
Err:
if (spi)
{
SPI_close(spi);
}
}
else
{
/* slave do nothing for xfer error test */
ret = true;
}
#else
ret = true;
#endif
return (ret);
}
#ifdef MCSPI_MULT_CHANNEL
static bool SPI_test_multi_channel(void *arg)
{
MCSPI_Handle spi[MCSPI_MAX_NUM_CHN];
MCSPI_Params spiParams;
uint32_t instance, i;
bool ret = false;
uint32_t chn, maxNumChn, testChn;
MCSPI_CallbackFxn cbFxn[MCSPI_MAX_NUM_CHN] = {MCSPI_callback0, MCSPI_callback1, MCSPI_callback2, MCSPI_callback3};
SPI_Tests *test = (SPI_Tests *)arg;
int32_t testId = test->testId;
bool master = test->master;
bool cbMode = test->cbMode;
uint32_t timeout = test->timeout;
if (cbMode == true)
{
/* Create call back semaphore */
SPI_osalSemParamsInit(&cbSemParams);
cbSemParams.mode = SemaphoreP_Mode_BINARY;
}
/* Soc configuration structures indexing starts from 0. If the IP
* instances start with 1, to address proper Configuration
* structure index, McSPI Instance should be substracted with 1
*/
if (master == true)
{
instance = (uint32_t)BOARD_MCSPI_MASTER_INSTANCE - 1;
}
else
{
instance = (uint32_t)BOARD_MCSPI_SLAVE_INSTANCE - 1;
}
testChn = MCSPI_TEST_CHN;
SPI_initConfig(instance, test, testChn, false);
/* Initialize SPI handle */
MCSPI_Params_init(&spiParams);
if (master == false)
{
spiParams.mode = SPI_SLAVE;
}
if (cbMode == true)
{
spiParams.transferMode = SPI_MODE_CALLBACK;
}
spiParams.transferTimeout = timeout;
if (testId == SPI_TEST_ID_WORD_LEN)
{
spiParams.dataSize = test->param;
}
if (master == true)
{
maxNumChn = MCSPI_MAX_NUM_CHN;
}
else
{
/* Only 1 channel supported in slave mode */
maxNumChn = 1;
}
for (i = 0; i < maxNumChn; i++)
{
if (master == true)
{
chn = i;
}
else
{
chn = testChn;
}
if (cbMode == true)
{
cbSem[chn] = SPI_osalCreateBlockingLock(0, &cbSemParams);
spiParams.transferCallbackFxn = cbFxn[chn];;
}
spi[chn] = MCSPI_open(instance, chn, &spiParams);
if (spi[chn] == NULL)
{
SPI_log("Error initializing SPI instance %d channel %d\n",
instance, chn);
goto Err;
}
else
{
SPI_log("SPI instance %d channel %d\n",
instance, chn);
}
}
for (i = 0; i < SPI_NUM_XFERS; i++)
{
if (SPI_test_mst_slv_xfer((void *)(spi[testChn]), test, spi_test_xfer_len[i], true) == false)
{
goto Err;
}
if ((master == true) && (testId < SPI_TEST_ID_LOOPBACK))
{
/*
* master sleep for 1 second after each transfer
* to sync with slave transfer
*/
#ifdef USE_BIOS
Task_sleep(1000);
#else
#endif
}
}
ret = true;
Err:
for (i = 0; i < maxNumChn; i++)
{
if (master == true)
{
chn = i;
}
else
{
chn = testChn;
}
if (spi[chn])
{
MCSPI_close(spi[chn]);
}
if (cbSem[chn])
{
SPI_osalDeleteBlockingLock(cbSem[chn]);
cbSem[chn] = NULL;
}
}
return (ret);
}
#endif
void SPI_test_print_test_desc(SPI_Tests *test)
{
char testId[16] = {0, };
/* Print unit test ID */
sprintf(testId, "%d", test->testId);
SPI_log("\r\n SPI UT %s\r\n", testId);
/* Print test description */
SPI_log("\r\n %s\r\n", test->testDesc);
}
SPI_Tests Spi_tests_master[] =
{
#ifndef SPI_MASTERONLY_TESTS
/* testFunc testID master pollMode cbMode dmaMode timeout testDesc */
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in dma mode", },
#endif
{SPI_test_single_channel, SPI_TEST_ID_INT, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_POLL, true, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in polling mode"},
{SPI_test_single_channel, SPI_TEST_ID_CB, true, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA_CB, true, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in dma callback mode", },
#endif
{SPI_test_xfer_error, SPI_TEST_ID_XFER_ERR, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master transfer error test in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_PHA_POL, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master phase polarity test in non-dma interrupt mode", 1, },
#ifdef MCSPI_MULT_CHANNEL
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in dma mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_MC_INT, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in non-dma interrupt mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_POLL, true, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in polling mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_CB, true, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA_CB, true, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in dma callback mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_TX_ONLY, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel TX_ONLY test", 0, },
#endif
#endif
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_WORD_LEN, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master data size test in loopback dma mode", SPI_TEST_DATA_SIZE, },
#endif
{SPI_test_single_channel, SPI_TEST_ID_WORD_LEN, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master data size test in loopback mode", SPI_TEST_DATA_SIZE, },
#ifdef MCSPI_MULT_CHANNEL
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_TRIG_LVL, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master multi channel FIFO trigger level test in loopback dma mode", SPI_TEST_TRIG_LVL, },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_TRIG_LVL, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master multi channel FIFO trigger level test in loopback mode", SPI_TEST_TRIG_LVL, },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_TCS, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel TCS test in dma mode", SPI_TEST_TCS, },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_TCS, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel TCS test", SPI_TEST_TCS, },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_INIT_DELAY, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel init delay test in dma mode", SPI_TEST_INIT_DELAY, },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_INIT_DELAY, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel init delay test", SPI_TEST_INIT_DELAY, },
#endif
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA_CB_CANCEL, true, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master transmit cancel in dma callback mode", },
#endif
{SPI_test_single_channel, SPI_TEST_ID_CB_CANCEL, true, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master transmit cancel in non-dma callback mode", },
/* NOTE: Timeout Test case should be executed as the final test, as this test requires no transaction on the data lines
* for the timeout to happen */
{SPI_test_single_channel, SPI_TEST_ID_TIMEOUT, false, false, false, false, SPI_TIMEOUT_VALUE, "\r\n SPI timeout test in interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_TIMEOUT_POLL, false, true, false, false, SPI_TIMEOUT_VALUE, "\r\n SPI timeout test in polling mode", },
{NULL, },
};
SPI_Tests Spi_tests_slave[] =
{
#ifndef SPI_MASTERONLY_TESTS
/* testFunc testID master pollMode cbMode dmaMode, timeout testDesc */
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA, false, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in dma mode", },
#endif
{SPI_test_single_channel, SPI_TEST_ID_INT, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_POLL, false, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in polling mode", },
{SPI_test_single_channel, SPI_TEST_ID_CB, false, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA_CB, false, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in dma callback mode", },
#endif
{SPI_test_xfer_error, SPI_TEST_ID_XFER_ERR, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI slave transfer error test in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_PHA_POL, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI slave phase polarity test in non-dma interrupt mode", 1, },
#ifdef MCSPI_MULT_CHANNEL
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA, false, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave multi channel in dma mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_MC_INT, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave multi channel in non-dma interrupt mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_POLL, false, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in polling mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_CB, false, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA_CB, false, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in dma callback mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_RX_ONLY, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave multi channel RX_ONLY test", 0, },
#endif
#endif
{NULL, },
};
/*
* ======== slaveTaskFxn ========
* The task is part of separate slave example project.
* To test slave mode example, slave task has to be
* ready for master. Slave SPI sends a message to master
* while receiving message from master.
*/
#ifdef USE_BIOS
Void slaveTaskFxn (UArg arg0, UArg arg1)
#else
void slaveTaskFxn()
#endif
{
uint32_t i;
bool testFail = false;
SPI_Tests *test;
SPI_init();
for (i = 0; ; i++)
{
if (evmAM570x == true)
{
/* Slave mode test not supported on AM570x EVM */
break;
}
test = &Spi_tests_slave[i];
if (test->testFunc == NULL)
break;
if (test->testId >= SPI_TEST_ID_LOOPBACK)
{
/* bypass the loopback test for slave task */
break;
}
SPI_test_print_test_desc(test);
if (test->testFunc((void *)test) == true)
{
SPI_log("\r\n %s have passed\r\n", test->testDesc);
}
else
{
SPI_log("\r\n %s have failed\r\n", test->testDesc);
testFail = true;
break;
}
}
if(testFail == true)
{
SPI_log("\n Some tests have failed. \n");
}
else
{
SPI_log("\n All tests have passed. \n");
}
SPI_log("Done\n");
while (true)
{
}
}
/*
* ======== masterTaskFxn ========
* This task is part of master example project.
* Slave task has to ensure transaction ready.
* Master SPI sends a message to slave and
* receives message from slave.
*/
#ifdef USE_BIOS
Void masterTaskFxn (UArg arg0, UArg arg1)
#else
void masterTaskFxn()
#endif
{
uint32_t i;
bool testFail = false;
SPI_Tests *test;
SPI_init();
//for (i = 0; ; i++)
for (i = 3; ; i++) // FL: Anping
{
test = &Spi_tests_master[i];
if (test->testFunc == NULL)
break;
#if defined (SOC_AM65XX) || defined(SOC_J721E)
if ((test->testId < SPI_TEST_ID_LOOPBACK) &&
(test->testId != SPI_TEST_ID_TIMEOUT) &&
(test->testId != SPI_TEST_ID_TIMEOUT_POLL))
continue;
#endif
if (evmAM570x == true)
{
/* Only loopback test supported on AM570x EVM */
if ((test->testId < SPI_TEST_ID_LOOPBACK) &&
(test->testId != SPI_TEST_ID_TIMEOUT) &&
(test->testId != SPI_TEST_ID_TIMEOUT_POLL))
continue;
}
SPI_test_print_test_desc(test);
if (test->testFunc((void *)test) == true)
{
SPI_log("\r\n %s have passed\r\n", test->testDesc);
}
else
{
SPI_log("\r\n %s have failed\r\n", test->testDesc);
testFail = true;
break;
}
}
if(testFail == true)
{
SPI_log("\n Some tests have failed. \n");
}
else
{
SPI_log("\n All tests have passed. \n");
}
SPI_log("Done\n");
while (true)
{
}
}
/*
* ======== main ========
*/
int main(void)
{
/* Call board init functions */
Board_initCfg boardCfg;
Board_STATUS boardStatus;
#if defined (evmK2G)
SPI_v0_HWAttrs spi_cfg;
uint8_t instance;
Board_SoCInfo socInfo;
#endif
#if defined (idkAM571x)
Board_IDInfo id;
#endif
#ifdef USE_BIOS
#if defined(SOC_AM335x) || defined (SOC_AM437x) || defined (SOC_AM65XX) || defined(SOC_J721E)
Task_Handle task;
Error_Block eb;
Error_init(&eb);
#if defined (MCSPI_SLAVE_TASK)
task = Task_create(slaveTaskFxn, NULL, &eb);
#elif defined (MCSPI_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 */
#endif /* #ifdef USE_BIOS */
boardCfg = BOARD_INIT_PINMUX_CONFIG |
BOARD_INIT_MODULE_CLOCK |
BOARD_INIT_UART_STDIO;
boardStatus = Board_init(boardCfg);
if (boardStatus != BOARD_SOK)
{
return (0);
}
#if defined(SOC_AM65XX) || defined(SOC_J721E)
#if defined (__TI_ARM_V7R4__)
/* Configure the MCU SPI0_D1 pinmux, since it is not set by default in board */
HW_WR_REG32((WKUP_PINMUX_REG_BASE + MCU_SPI0_D1_PADCFG_OFFSET), PIN_MODE(0) | \
((PIN_PULL_DISABLE | PIN_INPUT_ENABLE) & (~PIN_PULL_DIRECTION)));
/* Configure the MCU SPI0_CLK pinmux to support loopback */
HW_WR_REG32((WKUP_PINMUX_REG_BASE + MCU_SPI0_CLK_PADCFG_OFFSET), PIN_MODE(0) | \
((PIN_PULL_DISABLE | PIN_INPUT_ENABLE) & (~PIN_PULL_DIRECTION)));
#endif
#endif
#if defined (idkAM571x)
boardStatus = Board_getIDInfo(&id);
if (boardStatus != BOARD_SOK)
{
return (0);
}
/* Check if is DRA (AM570x) SoC */
if ((id.boardName[0] == 'D') &&
(id.boardName[1] == 'R') &&
(id.boardName[2] == 'A'))
{
evmAM570x = true;
}
#endif
#if defined(iceAMIC110)
/* GPIO initialization */
GPIO_init();
/* Set BUS_Switch_ENABLE pin to low for enabling the switch */
GPIO_write((GPIO_BUS_SWITCH_ENABLE_OFFSET), GPIO_PIN_VAL_LOW);
#endif
#if defined (evmK2G)
/* Read the SoC info to get the System clock value */
Board_getSoCInfo(&socInfo);
if(socInfo.sysClock != BOARD_SYS_CLK_DEFAULT)
{
/* Since this is a generic SPI test,
* configure the input clock for all the available instances */
for (instance = 0; instance < CSL_SPI_CNT; instance++)
{
SPI_socGetInitCfg(instance, &spi_cfg);
/* Update the I2C functional clock based on CPU clock - 1G or 600MHz */
spi_cfg.inputClkFreq = socInfo.sysClock/SPI_MODULE_CLOCK_DIVIDER;
SPI_socSetInitCfg(instance, &spi_cfg);
}
}
#endif
#ifdef USE_BIOS
/* Start BIOS */
BIOS_start();
#else
#ifdef MCSPI_MASTER_TASK
masterTaskFxn();
#else
slaveTaskFxn();
#endif
#endif
return (0);
}
#if defined(BUILD_MPU) || defined (__C7100__)
extern void Osal_initMmuDefault(void);
void InitMmu(void)
{
Osal_initMmuDefault();
}
#endif
Anping,
I only reach UT 12 & 13 before failing the data verification step.
SPI UT 12
SPI master transfer error test in non-dma interrupt mode
SPI master transfer error test in non-dma interrupt mode have passed
SPI UT 13
SPI master phase polarity test in non-dma interrupt mode
SPI initialized
SPI master phase polarity test in non-dma interrupt mode have failed
Some tests have failed.
Done
Specifically, UT 13 fails on this line in SPI_test_mst_slv_xfer()
/* master mode, verify master recieved data match with slave sent data */
if (SPI_verify_data(masterRxBuffer, srcPtr, xferBytes) == false)
Further, I never reach line 832 since test->cbMode==0 for UT 12 & 13:
if (cbMode)
{
if (SPI_osalPendLock(cbSem[0], timeout) != SemaphoreP_OK)
{
goto Err;
}
UART_printf("\n SPI_osalPendLock!\n"); // FL: Anping, don't reach this
}
How is your hardware connected? Do you have two BBB's connected as described in the docs?
http://software-dl.ti.com/processor-sdk-rtos/esd/docs/06_01_00_08/rtos/index_device_drv.html#id31
BTW Have you tried debuggin this on your own by stepping into UART_printf() on Line 832?
Regards,
Frank
Hi Frank
Enclosed is
main_mcspi_slave_mode.c
which I change three lines. Thanks
/**
* \file main_mcspi_slave_mode.c
*
* \brief The application Demonstrate the MCSPI slave mode functionality.
* This application transmits data from master to slave and at the
* same instance data from slave will be 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:
* MasterSPI_SCLK----SlaveSPI_SCLK
* MasterSPI_D0------SlaveSPI_D1
* MasterSPI_D1------SlaveSPI_D0
* MasterSPI_CS------SlaveSPI_CS
*
* \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:
* SPI initialized
* Slave: PASS: Txd from master SPI
*
* At master end console:
* SPI initialized
* Master: PASS: Txd from slave SPI
* Done
*/
/*
* Copyright (C) 2016 - 2019 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>
#ifdef USE_BIOS
/* XDCtools Header files */
#include <xdc/std.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>
#endif /* #ifdef USE_BIOS */
/* 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/spi/soc/SPI_soc.h>
#include <ti/drv/spi/src/SPI_osal.h>
#include <ti/drv/spi/SPI.h>
#include "SPI_log.h"
#if defined(iceAMIC110)
#include <ti/drv/gpio/GPIO.h>
#include <ti/drv/gpio/soc/GPIO_soc.h>
#endif
#include <ti/board/board.h>
#ifdef SOC_AM65XX
#include <ti/csl/soc/am65xx/src/cslr_soc_baseaddress.h>
#include <ti/csl/soc/am65xx/src/cslr_wkup_ctrl_mmr.h>
#elif defined(SOC_J721E)
#include <ti/csl/soc/j721e/src/cslr_soc_baseaddress.h>
#include <ti/csl/soc/j721e/src/cslr_wkup_ctrl_mmr.h>
#endif
#ifdef SPI_DMA_ENABLE
#include <ti/osal/CacheP.h>
#if defined (SOC_AM65XX) || defined(SOC_J721E)
#include <ti/drv/udma/udma.h>
#else
/* EDMA3 Header files */
#include <ti/sdo/edma3/drv/edma3_drv.h>
#include <ti/sdo/edma3/rm/edma3_rm.h>
#include <ti/sdo/edma3/rm/sample/bios6_edma3_rm_sample.h>
#if defined(evmK2G)
#include <ti/csl/soc.h>
#endif
static EDMA3_RM_Handle MCSPIApp_edmaInit(void);
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || \
defined(SOC_C6678) || defined(SOC_C6657)
extern EDMA3_RM_InstanceInitConfig sampleInstInitConfig[][EDMA3_MAX_REGIONS];
extern EDMA3_RM_GblConfigParams sampleEdma3GblCfgParams[];
#endif
#endif
#endif
/* Define the SPI test interface */
typedef struct SPI_Tests_s
{
bool (*testFunc)(void *);
int32_t testId;
bool master;
bool pollMode;
bool cbMode;
bool dmaMode;
uint32_t timeout;
char testDesc[80];
uint32_t param;
uint32_t trigLvl;
} SPI_Tests;
/**********************************************************************
************************** Macros ************************************
**********************************************************************/
#define SPI_TIMEOUT_VALUE 5000
/* SPI transfer message definitions */
#define SPI_MSG_LENGTH 26
#define SPI_MSG_LENGTH2 78
#define SPI_NUM_XFERS 2
uint32_t spi_test_xfer_len[SPI_NUM_XFERS] =
{
SPI_MSG_LENGTH,
SPI_MSG_LENGTH2
};
/* Maximum # of channels per SPI instance */
#define MCSPI_MAX_NUM_CHN 4
/* Test channel # */
#define MCSPI_TEST_CHN 0
/* SPI Test definitions */
/* Unit test IDs */
#define SPI_TEST_ID_DMA 0 /* Single-channel DMA mode test */
#define SPI_TEST_ID_INT 1 /* Single-channel interrupt mode test */
#define SPI_TEST_ID_POLL 2 /* Single-channel polling mode test */
#define SPI_TEST_ID_CB 3 /* Single-channel non-DMA callback mode test */
#define SPI_TEST_ID_DMA_CB 4 /* Single-channel DMA callback mode test */
#define SPI_TEST_ID_MC_DMA 5 /* Multi-channel DMA mode test */
#define SPI_TEST_ID_MC_INT 6 /* Multi-channel interrupt mode test */
#define SPI_TEST_ID_MC_POLL 7 /* Multie-channel polling mode test */
#define SPI_TEST_ID_MC_CB 8 /* Multi-channel non-DMA callback mode test */
#define SPI_TEST_ID_MC_DMA_CB 9 /* Multi-channel DMA callback mode test */
#define SPI_TEST_ID_TX_ONLY 10 /* Multi-channel TX only test */
#define SPI_TEST_ID_RX_ONLY 11 /* Multi-channel RX only test */
#define SPI_TEST_ID_XFER_ERR 12 /* Single-channel transfer error test */
#define SPI_TEST_ID_PHA_POL 13 /* Single-channel phase/polarity test */
#define SPI_TEST_ID_TIMEOUT 14 /* Single-channel Timeout test with interrupt enabled */
#define SPI_TEST_ID_TIMEOUT_POLL 15 /* Single-channel Timeout test with polling enabled */
#define SPI_TEST_ID_DMA_CB_CANCEL 16
#define SPI_TEST_ID_CB_CANCEL 17
/* Loopback tests */
#define SPI_TEST_ID_LOOPBACK 20
#define SPI_TEST_ID_WORD_LEN (SPI_TEST_ID_LOOPBACK) /* transfer data size test */
#define SPI_TEST_ID_TRIG_LVL (SPI_TEST_ID_LOOPBACK + 1) /* FIFO trigger level test */
#define SPI_TEST_ID_TCS (SPI_TEST_ID_LOOPBACK + 2) /* Multi-channel chip select time control test */
#define SPI_TEST_ID_INIT_DELAY (SPI_TEST_ID_LOOPBACK + 3) /* Multi-channel 1st transfer init delay test */
/* Transfer data size test parameter, in # of bits per SPI word */
#define SPI_TEST_DATA_SIZE_16 16
#define SPI_TEST_DATA_SIZE_32 32
#if defined(SOC_DRA78x) || defined(SOC_TDA3XX) || defined(SOC_TDA2XX) || defined(SOC_TDA2EX) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined(SOC_AM574x) || defined (SOC_AM572x) || defined (SOC_AM571x) || defined (SOC_AM437x) || defined (SOC_AM335x) || defined (SOC_AM65XX) || defined(SOC_J721E)
#define SPI_TEST_DATA_SIZE SPI_TEST_DATA_SIZE_32
#else
#define SPI_TEST_DATA_SIZE SPI_TEST_DATA_SIZE_16
#endif
#ifdef MCSPI_MULT_CHANNEL
/* Chip select time control test parameter */
#define SPI_TEST_TCS MCSPI_CH0CONF_TCS0_ONECYCLEDLY
/* 1st transfer init delay test parameter */
#define SPI_TEST_INIT_DELAY MCSPI_INITDLY_4
/* FIFO trigger level test parameter, in # of bytes */
#define SPI_TEST_TRIG_LVL 16
#endif
#if defined(SOC_AM65XX) || defined(SOC_J721E)
/* WKUP CTRL base address + offset to beginning of PAD CONFIG section */
#define WKUP_PINMUX_REG_BASE (CSL_WKUP_CTRL_MMR0_CFG0_BASE + \
CSL_WKUP_CTRL_MMR_CFG0_PADCONFIG0)
#define MCU_SPI0_CLK_PADCFG_OFFSET (0x90U)
#define MCU_SPI0_D1_PADCFG_OFFSET (0x98U)
#define PIN_MODE(mode) (mode)
/** \brief Active mode configurations */
/** \brief Resistor disable */
#define PIN_PULL_DISABLE (0x1U << 16U)
/** \brief Pull direction */
#define PIN_PULL_DIRECTION (0x1U << 17U)
/** \brief Receiver enable */
#define PIN_INPUT_ENABLE (0x1U << 18U)
/** \brief Driver disable */
#define PIN_OUTPUT_DISABLE (0x1U << 21U)
/** \brief Wakeup enable */
#define PIN_WAKEUP_ENABLE (0x1U << 29U)
#ifdef SPI_DMA_ENABLE
/*
* Ring parameters
*/
/** \brief Number of ring entries - we can prime this much memcpy operations */
#define UDMA_TEST_APP_RING_ENTRIES (1U)
/** \brief Size (in bytes) of each ring entry (Size of pointer - 64-bit) */
#define UDMA_TEST_APP_RING_ENTRY_SIZE (sizeof(uint64_t))
/** \brief Total ring memory */
#define UDMA_TEST_APP_RING_MEM_SIZE (UDMA_TEST_APP_RING_ENTRIES * \
UDMA_TEST_APP_RING_ENTRY_SIZE)
/**
* \brief UDMA host mode buffer descriptor memory size.
* Make it multiple of 128 byte alignment
*/
#define UDMA_TEST_APP_DESC_SIZE (sizeof(CSL_UdmapCppi5HMPD) + (128U - sizeof(CSL_UdmapCppi5HMPD)))
/*
* UDMA driver objects
*/
struct Udma_DrvObj gUdmaDrvObj;
struct Udma_ChObj gUdmaTxChObj;
struct Udma_ChObj gUdmaRxChObj;
struct Udma_EventObj gUdmaTxCqEventObj;
struct Udma_EventObj gUdmaRxCqEventObj;
Udma_DrvHandle gDrvHandle = NULL;
/*
* UDMA Memories
*/
static uint8_t gTxRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gTxCompRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gUdmaTxHpdMem[UDMA_TEST_APP_DESC_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gRxRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gRxCompRingMem[UDMA_TEST_APP_RING_MEM_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gUdmaRxHpdMem[UDMA_TEST_APP_DESC_SIZE] __attribute__((aligned(UDMA_CACHELINE_ALIGNMENT)));
static SPI_dmaInfo gUdmaInfo;
Udma_DrvHandle MCSPIApp_udmaInit(SPI_v1_HWAttrs *cfg)
{
int32_t retVal = UDMA_SOK;
Udma_InitPrms initPrms;
uint32_t instId;
if (gDrvHandle == NULL)
{
/* UDMA driver init */
#if defined (__aarch64__)
instId = UDMA_INST_ID_MAIN_0;
#else
instId = UDMA_INST_ID_MCU_0;
#endif
UdmaInitPrms_init(instId, &initPrms);
retVal = Udma_init(&gUdmaDrvObj, &initPrms);
if(UDMA_SOK == retVal)
{
gDrvHandle = &gUdmaDrvObj;
}
}
if(gDrvHandle != NULL)
{
gDrvHandle = &gUdmaDrvObj;
gUdmaInfo.txChHandle = (void *)&gUdmaTxChObj;
gUdmaInfo.rxChHandle = (void *)&gUdmaRxChObj;
gUdmaInfo.txRingMem = (void *)&gTxRingMem[0];
gUdmaInfo.cqTxRingMem = (void *)&gTxCompRingMem[0];
gUdmaInfo.rxRingMem = (void *)&gRxRingMem[0];
gUdmaInfo.cqRxRingMem = (void *)&gRxCompRingMem[0];
gUdmaInfo.txHpdMem = (void *)&gUdmaTxHpdMem[0];
gUdmaInfo.rxHpdMem = (void *)&gUdmaRxHpdMem[0];
gUdmaInfo.txEventHandle = (void *)&gUdmaTxCqEventObj;
gUdmaInfo.rxEventHandle = (void *)&gUdmaRxCqEventObj;
cfg->dmaInfo = &gUdmaInfo;
}
return (gDrvHandle);
}
int32_t MCSPI_udma_deinit(void)
{
int32_t retVal = UDMA_SOK;
if (gDrvHandle != NULL)
{
retVal = Udma_deinit(gDrvHandle);
if(UDMA_SOK == retVal)
{
gDrvHandle = NULL;
}
}
return (retVal);
}
#endif
#endif /* #if defined(SOC_AM65XX) || defined(SOC_J721E) */
/**********************************************************************
************************** Global Variables **************************
**********************************************************************/
#if (defined(_TMS320C6X) || defined (__TI_ARM_V7M4__))
#pragma DATA_ALIGN (masterRxBuffer, 128)
unsigned char masterRxBuffer[128];
#pragma DATA_ALIGN (slaveRxBuffer, 128)
unsigned char slaveRxBuffer[128];
#else
unsigned char masterRxBuffer[128] __attribute__ ((aligned (128)));
unsigned char slaveRxBuffer[128] __attribute__ ((aligned (128)));
#endif
#define CANCEL_TX_LEN (1024)
unsigned char cancelTxBuff[CANCEL_TX_LEN];
unsigned char cancelRxBuff[CANCEL_TX_LEN];
unsigned char masterTxBuffer[128] = "PASS: Txd from master SPI PASS: Txd from master SPI PASS: Txd from master SPI ";
unsigned char slaveTxBuffer[128] = "PASS: Txd from slave SPI PASS: Txd from slave SPI PASS: Txd from slave SPI ";
#if defined(iceAMIC110)
#define GPIO_BUS_SWITCH_ENABLE_OFFSET (0)
#define GPIO_PIN_VAL_LOW (0U)
#define GPIO_PIN_VAL_HIGH (1U)
#define GPIO_BUS_SWITCH_ENABLE_PIN_NUM (0x15)
#define GPIO_BUS_SWITCH_ENABLE_PORT_NUM (0x2)
/* GPIO Driver board specific pin configuration structure */
GPIO_PinConfig gpioPinConfigs[] = {
/* Boot switch enable pin to control the buffer for routing McSPI
* lines to Launchpad header on iceAMIC110 board */
GPIO_DEVICE_CONFIG((GPIO_BUS_SWITCH_ENABLE_PORT_NUM + 1), GPIO_BUS_SWITCH_ENABLE_PIN_NUM) |
GPIO_CFG_IN_INT_NONE | GPIO_CFG_OUTPUT,
};
/* GPIO Driver call back functions */
GPIO_CallbackFxn gpioCallbackFunctions[] = {
NULL
};
/* GPIO Driver configuration structure */
GPIO_v1_Config GPIO_v1_config = {
gpioPinConfigs,
gpioCallbackFunctions,
sizeof(gpioPinConfigs) / sizeof(GPIO_PinConfig),
sizeof(gpioCallbackFunctions) / sizeof(GPIO_CallbackFxn),
0x1U,
};
#endif /* #if defined(iceAMIC110) */
/* Transaction data */
SPI_Transaction transaction;
/* Callback mode variables */
SemaphoreP_Params cbSemParams;
SemaphoreP_Handle cbSem[MCSPI_MAX_NUM_CHN] = {NULL, NULL, NULL, NULL};
bool evmAM570x = false;
#ifdef SPI_DMA_ENABLE
#if !(defined (SOC_AM65XX) || defined(SOC_J721E))
EDMA3_RM_Handle gEdmaHandle = NULL;
/**
* \brief Function to initialize the edma driver and get the handle to the
* edma driver;
*/
static EDMA3_RM_Handle MCSPIApp_edmaInit(void)
{
EDMA3_DRV_Result edmaResult = EDMA3_DRV_E_INVALID_PARAM;
uint32_t edma3Id;
if (gEdmaHandle != NULL)
{
return (gEdmaHandle);
}
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || \
defined(SOC_C6678) || defined(SOC_C6657)
uint32_t edmaEvent[2], i, chnMapping, chnMappingIdx;
/* For Keystone devices, edm3Id is SPI instance and SoC specific */
SPI_getEdmaInfo(BOARD_MCSPI_MASTER_INSTANCE - 1, &edma3Id, edmaEvent);
/* Set the RX/TX ownDmaChannels and dmaChannelHwEvtMap */
for (i = 0; i < 2; i++)
{
chnMapping = edmaEvent[i];
if (chnMapping < 32)
chnMappingIdx = 0;
else
{
chnMapping -= 32;
chnMappingIdx = 1;
}
sampleInstInitConfig[edma3Id][0].ownDmaChannels[chnMappingIdx] |= (1 << chnMapping);
sampleInstInitConfig[edma3Id][0].ownTccs[chnMappingIdx] |= (1 << chnMapping);
sampleInstInitConfig[edma3Id][0].ownPaRAMSets[chnMappingIdx] |= (1 << chnMapping);
sampleEdma3GblCfgParams[edma3Id].dmaChannelHwEvtMap[chnMappingIdx] |= (1 << chnMapping);
}
#endif
#if defined(SOC_AM574x) || defined(SOC_AM572x)|| defined(SOC_AM571x) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined (SOC_DRA78x) || defined (SOC_AM335x) || defined (SOC_AM437x)
edma3Id = 0;
#endif
gEdmaHandle = (EDMA3_RM_Handle)edma3init(edma3Id, &edmaResult);
#ifdef USE_BIOS
if (edmaResult != EDMA3_DRV_SOK)
{
/* Report EDMA Error */
System_printf("\nEDMA driver initialization FAIL\n");
}
else
{
System_printf("\nEDMA driver initialization PASS.\n");
}
#endif
return(gEdmaHandle);
}
#endif
#endif
/* Callback mode functions */
void SPI_callback(SPI_Handle handle, SPI_Transaction *transaction)
{
UART_printf("\nSPI_callback!\n");
SPI_osalPostLock(cbSem[0]);
}
#ifdef MCSPI_MULT_CHANNEL
void MCSPI_callback0(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[0]);
}
void MCSPI_callback1(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[1]);
}
void MCSPI_callback2(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[2]);
}
void MCSPI_callback3(MCSPI_Handle handle, SPI_Transaction *transaction)
{
SPI_osalPostLock(cbSem[3]);
}
#endif
#ifdef MCSPI_MULT_CHANNEL
/*
* ======== SPI init config ========
*/
static void SPI_initConfigDefault(SPI_HWAttrs *cfg, uint32_t chn)
{
cfg->chNum = chn;
cfg->chnCfg[chn].tcs = MCSPI_CS_TCS_0PNT5_CLK;
cfg->chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_6;
cfg->chnCfg[chn].trMode = MCSPI_TX_RX_MODE;
cfg->initDelay = MCSPI_INITDLY_0;
#if defined (SOC_AM335x)
cfg->rxTrigLvl = MCSPI_RX_TX_FIFO_SIZE / 2;
cfg->txTrigLvl = MCSPI_RX_TX_FIFO_SIZE / 2;
#else
cfg->rxTrigLvl = MCSPI_RX_TX_FIFO_SIZE;
cfg->txTrigLvl = MCSPI_RX_TX_FIFO_SIZE;
#endif
}
#endif
/*
* ======== SPI init config ========
*/
static void SPI_initConfig(uint32_t instance, SPI_Tests *test, uint32_t chn, bool multiChn)
{
SPI_HWAttrs spi_cfg;
int32_t testId = test->testId;
bool pollMode = test->pollMode;
#ifdef SPI_DMA_ENABLE
bool dmaMode = test->dmaMode;
#endif
/* Get the default SPI init configurations */
SPI_socGetInitCfg(instance, &spi_cfg);
#ifdef MCSPI_MULT_CHANNEL
SPI_initConfigDefault(&spi_cfg, chn);
#endif
/*
* Set blocking mode (dma mode or non-dma interrupt mode)
* or callback mode
*/
if (pollMode == true)
{
/* polling mode */
spi_cfg.enableIntr = false;
/* SPI DMA mode is not supported in polling mode */
spi_cfg.edmaHandle = NULL;
spi_cfg.dmaMode = FALSE;
}
else
{
/* interrupt enabled */
spi_cfg.enableIntr = true;
#if defined(SOC_DRA78x) || defined(SOC_TDA3XX) || defined(SOC_TDA2XX) || defined(SOC_TDA2PX) || defined(SOC_TDA2EX) || defined (SOC_DRA75x) || \
defined(SOC_AM574x) || defined (SOC_AM572x) || defined (SOC_AM571x) || defined (SOC_AM437x) || defined (SOC_AM335x) || \
defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || \
defined(SOC_C6678) || defined(SOC_C6657) || defined (SOC_AM65XX) || defined(SOC_J721E)
#ifdef SPI_DMA_ENABLE
if (dmaMode == true)
{
/* Set the DMA related init config */
#if defined (SOC_AM65XX) || defined(SOC_J721E)
spi_cfg.edmaHandle = (void *)MCSPIApp_udmaInit(&spi_cfg);
#else
spi_cfg.edmaHandle = MCSPIApp_edmaInit();
#endif
spi_cfg.dmaMode = TRUE;
spi_cfg.enableIntr = false;
}
else
#endif
{
spi_cfg.edmaHandle = NULL;
spi_cfg.dmaMode = FALSE;
}
#endif
}
#ifdef MCSPI_MULT_CHANNEL
switch(testId)
{
case (SPI_TEST_ID_TX_ONLY):
spi_cfg.chnCfg[chn].trMode = MCSPI_TX_ONLY_MODE;
/* Data line 0 TX enabled, data line 1 RX enabled TX disabled */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_6;
break;
case (SPI_TEST_ID_RX_ONLY):
spi_cfg.chnCfg[chn].trMode = MCSPI_RX_ONLY_MODE;
/* Data line 0 TX disabled, data line 1 RX enabled TX disabled */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_7;
break;
case (SPI_TEST_ID_TRIG_LVL):
spi_cfg.rxTrigLvl = test->param;
spi_cfg.txTrigLvl = test->param;
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
break;
case (SPI_TEST_ID_TCS):
spi_cfg.chnCfg[chn].tcs = test->param;
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
break;
case (SPI_TEST_ID_INIT_DELAY):
spi_cfg.initDelay = test->param;
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
break;
default:
break;
}
#ifdef SPI_DMA_ENABLE
if (spi_cfg.txTrigLvl != 0)
{
test->trigLvl = spi_cfg.txTrigLvl;
}
else
{
test->trigLvl = 0;
}
if (spi_cfg.txTrigLvl < spi_cfg.rxTrigLvl)
{
test->trigLvl = spi_cfg.rxTrigLvl;
}
#endif
#endif
if ((testId == SPI_TEST_ID_WORD_LEN) || (testId == SPI_TEST_ID_CB_CANCEL) || (testId == SPI_TEST_ID_DMA_CB_CANCEL))
{
#if defined(SOC_DRA78x) || defined(SOC_TDA3XX) || defined(SOC_TDA2XX) || defined(SOC_TDA2EX) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined (SOC_AM572x) || defined (SOC_AM571x) || defined (SOC_AM574x) || defined (SOC_AM437x) || defined (SOC_AM335x) || defined (SOC_AM65XX) || defined(SOC_J721E)
/* enalbe loopback mode */
spi_cfg.chnCfg[chn].dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
#else
/* enalbe loopback mode */
spi_cfg.loopback = 1;
#endif
}
/* Set the SPI init configurations */
SPI_socSetInitCfg(instance, &spi_cfg);
}
bool SPI_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 uintptr_t l2_global_address (uintptr_t addr)
{
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2L) || defined(SOC_K2E) || defined(SOC_K2G) || defined(SOC_C6678) || defined(SOC_C6657)
#ifdef _TMS320C6X
uint32_t corenum;
/* Get the core number. */
corenum = CSL_chipReadReg (CSL_CHIP_DNUM);
/* Compute the global address. */
return (addr + (0x10000000 + (corenum * 0x1000000)));
#else
return addr;
#endif
#else
return addr;
#endif
}
static void SPI_test_xfer_ctrl(SPI_Handle spi, uint32_t xferEnable)
{
#if defined(SOC_K2H) || defined(SOC_K2K) || defined(SOC_K2E) || defined(SOC_K2L) || defined(SOC_K2G) || defined(SOC_C6678) || defined(SOC_C6657)
uint32_t xferActivate = xferEnable;
SPI_control(spi, SPI_V0_CMD_XFER_ACTIVATE, (void *)&xferActivate);
#endif
}
static bool SPI_test_mst_slv_xfer(void *spi, SPI_Tests *test, uint32_t xferLen, bool multChn)
{
bool transferOK;
uintptr_t addrMasterRxBuf, addrMasterTxBuf, addrSlaveRxBuf, addrSlaveTxBuf, addrCancelTxBuff, addrCancelRxBuff;
bool ret = false;
uint32_t terminateXfer = 1;
int32_t testId = test->testId;
bool master = test->master;
bool cbMode = test->cbMode;
bool dmaMode = test->dmaMode;
uint32_t timeout = test->timeout;
uint32_t transCount, xferBytes, testLen;
unsigned char *srcPtr;
if (dmaMode)
{
addrMasterRxBuf = l2_global_address((uintptr_t)masterRxBuffer);
addrMasterTxBuf = l2_global_address((uintptr_t)masterTxBuffer);
addrSlaveRxBuf = l2_global_address((uintptr_t)slaveRxBuffer);
addrSlaveTxBuf = l2_global_address((uintptr_t)slaveTxBuffer);
addrCancelTxBuff = l2_global_address((uintptr_t)cancelTxBuff);
addrCancelRxBuff = l2_global_address((uintptr_t)cancelRxBuff);
}
else
{
addrMasterRxBuf = (uintptr_t)masterRxBuffer;
addrMasterTxBuf = (uintptr_t)masterTxBuffer;
addrSlaveRxBuf = (uintptr_t)slaveRxBuffer;
addrSlaveTxBuf = (uintptr_t)slaveTxBuffer;
addrCancelTxBuff = (uintptr_t)cancelTxBuff;
addrCancelRxBuff = (uintptr_t)cancelRxBuff;
}
memset(cancelTxBuff, 0, sizeof(cancelTxBuff));
memset(cancelRxBuff, 0, sizeof(cancelRxBuff));
memset(masterRxBuffer, 0, sizeof(masterRxBuffer));
memset(slaveRxBuffer, 0, sizeof(slaveRxBuffer));
#ifdef SPI_DMA_ENABLE
#if !defined (__aarch64__)
if (dmaMode)
{
CacheP_wbInv((void *)addrMasterRxBuf, (int32_t)sizeof(masterRxBuffer));
CacheP_wbInv((void *)addrSlaveRxBuf, (int32_t)sizeof(slaveRxBuffer));
CacheP_wbInv((void *)addrCancelTxBuff, (int32_t)sizeof(cancelTxBuff));
CacheP_wbInv((void *)addrCancelRxBuff, (int32_t)sizeof(cancelRxBuff));
}
#endif
#endif
testLen = xferLen;
#if defined(SOC_AM574x) || defined(SOC_AM572x)|| defined(SOC_AM571x) || defined (SOC_DRA72x) || defined (SOC_DRA75x) || defined (SOC_DRA78x) || defined (SOC_AM335x) || defined (SOC_AM437x) || defined (SOC_AM65XX) || defined(SOC_J721E)
#ifdef SPI_DMA_ENABLE
if (dmaMode == true)
{
if (testLen > test->trigLvl)
{
/* always transfer data bytes of multiple trigger level */
testLen = (xferLen / test->trigLvl) * test->trigLvl;
}
else
{
/* transfer data bytes of 1 trigger level */
testLen = test->trigLvl;
}
}
#endif
#endif
if (testId == SPI_TEST_ID_WORD_LEN)
{
/*
* Word length can be 8/16/32 bits,
* calculate the SPI word count
*/
transCount = testLen / (test->param / 8);
xferBytes = transCount * (test->param / 8);
}
else
{
/* Default word length is 8-bit */
transCount = testLen;
xferBytes = testLen;
}
/* Initialize slave SPI transaction structure */
transaction.count = transCount;
transaction.arg = (void *)&terminateXfer;
if (master == true)
{
if ((testId == SPI_TEST_ID_CB_CANCEL) || (testId == SPI_TEST_ID_DMA_CB_CANCEL))
{
transaction.txBuf = (void *)addrCancelTxBuff;
transaction.rxBuf = (void *)addrCancelRxBuff;
}
else
{
transaction.txBuf = (void *)addrMasterTxBuf;
transaction.rxBuf = (void *)addrMasterRxBuf;
}
}
else
{
transaction.txBuf = (void *)addrSlaveTxBuf;
transaction.rxBuf = (void *)addrSlaveRxBuf;
}
/* Initiate SPI transfer */
SPI_test_xfer_ctrl(spi, 1);
#ifdef MCSPI_MULT_CHANNEL
if (multChn == true)
{
transferOK = MCSPI_transfer((MCSPI_Handle)spi, &transaction);
}
else
#endif
{
transferOK = SPI_transfer((SPI_Handle)spi, &transaction);
if ((testId == SPI_TEST_ID_CB_CANCEL) || (testId == SPI_TEST_ID_DMA_CB_CANCEL))
{
SPI_transferCancel(spi);
}
}
if(transferOK)
{
if (cbMode)
{
if (SPI_osalPendLock(cbSem[0], timeout) != SemaphoreP_OK)
{
goto Err;
}
UART_printf("\n SPI_osalPendLock!\n");
}
SPI_test_xfer_ctrl(spi, 0);
/* Get the actual transfer bytes */
if (testId == SPI_TEST_ID_WORD_LEN)
{
xferBytes = transaction.count * (test->param / 8);
}
else
{
xferBytes = transaction.count;
}
if ((testId == SPI_TEST_ID_CB_CANCEL) || (testId == SPI_TEST_ID_DMA_CB_CANCEL))
{
if (transaction.status == SPI_TRANSFER_CANCELED)
{
SPI_log("\n SPI Transfer Canceled!\n");
}
else
{
SPI_log("\n SPI Transfer Cancel failed!\n");
goto Err;
}
}
else if (testId != SPI_TEST_ID_TX_ONLY)
{
if (master == true)
{
if (testId >= SPI_TEST_ID_LOOPBACK)
{
srcPtr = masterTxBuffer;
}
else
{
srcPtr = slaveTxBuffer;
}
/* master mode, verify master recieved data match with slave sent data */
if (SPI_verify_data(masterRxBuffer, srcPtr, xferBytes) == false)
{
goto Err;
}
/* Print contents of master receive buffer */
SPI_log("Master: %s\n", masterRxBuffer);
}
else
{
/* slave mode, verify slave recieved data match with master sent data */
if (SPI_verify_data(slaveRxBuffer, masterTxBuffer, xferBytes) == false)
{
goto Err;
}
/* Print contents of slave receive buffer */
SPI_log("Slave: %s\n", slaveRxBuffer);
}
}
}
else
{
if ((testId == SPI_TEST_ID_TIMEOUT) || (testId == SPI_TEST_ID_TIMEOUT_POLL))
{
if (transaction.status == SPI_TRANSFER_TIMEOUT)
{
SPI_log("SPI Slave transfer Timed out for transfer length %d\n", xferLen);
}
else
{
SPI_log("Unsuccessful slave SPI transfer");
goto Err;
}
}
else
{
SPI_log("Unsuccessful slave SPI transfer");
goto Err;
}
}
ret = true;
Err:
return (ret);
}
static bool SPI_test_single_channel(void *arg)
{
SPI_Handle spi = NULL;
SPI_Params spiParams;
uint32_t instance, i, modeIndex, SPI_modeIndex, xferLen, num_xfers;
bool ret = false;
SPI_Tests *test = (SPI_Tests *)arg;
int32_t testId = test->testId;
bool master = test->master;
bool cbMode = test->cbMode;
uint32_t timeout = test->timeout;
SPI_FrameFormat frameFormat[]=
{
SPI_POL0_PHA0, /*!< SPI mode Polarity 0 Phase 0 */
SPI_POL0_PHA1, /*!< SPI mode Polarity 0 Phase 1 */
SPI_POL1_PHA0, /*!< SPI mode Polarity 1 Phase 0 */
SPI_POL1_PHA1, /*!< SPI mode Polarity 1 Phase 1 */
};
if (cbMode == true)
{
/* Create call back semaphore */
SPI_osalSemParamsInit(&cbSemParams);
cbSemParams.mode = SemaphoreP_Mode_BINARY;
cbSem[0] = SPI_osalCreateBlockingLock(0, &cbSemParams);
}
if ((testId == SPI_TEST_ID_WORD_LEN) && (test->dmaMode == false))
{
SPI_modeIndex = 4;
}
else
{
SPI_modeIndex = 1;
}
/* In case of SPI_TEST_ID_PHA_POL all SPI modes need to be tested */
for (modeIndex = 0; modeIndex < SPI_modeIndex; modeIndex++)
{
ret = false;
/* Soc configuration structures indexing starts from 0. If the IP
* instances start with 1, to address proper Configuration
* structure index, McSPI Instance should be substracted with 1
*/
if (master == true)
{
instance = (uint32_t)BOARD_MCSPI_MASTER_INSTANCE - 1;
}
else
{
instance = (uint32_t)BOARD_MCSPI_SLAVE_INSTANCE - 1;
}
SPI_initConfig(instance, test, MCSPI_TEST_CHN, false);
/* Initialize SPI handle */
SPI_Params_init(&spiParams);
if (master == false)
{
spiParams.mode = SPI_SLAVE;
}
if (cbMode == true)
{
spiParams.transferMode = SPI_MODE_CALLBACK;
spiParams.transferCallbackFxn = SPI_callback;
}
spiParams.transferTimeout = timeout;
if (testId == SPI_TEST_ID_PHA_POL)
{
spiParams.frameFormat = (SPI_FrameFormat)(test->param);
}
if (testId == SPI_TEST_ID_WORD_LEN)
{
if(test->dmaMode == false)
{
spiParams.frameFormat = frameFormat[modeIndex];
SPI_log("\n%s with SPI Mode %d\n", test->testDesc, spiParams.frameFormat);
}
spiParams.dataSize = test->param;
}
spi = SPI_open(instance, &spiParams);
if (spi == NULL)
{
SPI_log("Error initializing SPI\n");
goto Err;
}
else
{
SPI_log("SPI initialized\n");
}
if ((testId == SPI_TEST_ID_CB_CANCEL) || (testId == SPI_TEST_ID_DMA_CB_CANCEL))
{
num_xfers = 1;
}
else
{
num_xfers = SPI_NUM_XFERS;
}
for (i = 0; i < num_xfers; i++)
{
if ((testId == SPI_TEST_ID_CB_CANCEL) || (testId == SPI_TEST_ID_DMA_CB_CANCEL))
{
xferLen = CANCEL_TX_LEN;
}
else
{
xferLen = spi_test_xfer_len[i];
}
if (SPI_test_mst_slv_xfer((void *)spi, test, xferLen, false) == false)
{
goto Err;
}
if ((testId == SPI_TEST_ID_CB_CANCEL) || (testId == SPI_TEST_ID_DMA_CB_CANCEL))
{
SPI_log("SPI Master Transfer Cancelled!!\n");
}
if ((master == true) && (testId < SPI_TEST_ID_LOOPBACK))
{
/*
* master sleep for 1 second after each transfer
* to sync with slave transfer
*/
#ifdef USE_BIOS
Task_sleep(1000);
#else
#endif
}
}
ret = true;
if (testId == SPI_TEST_ID_WORD_LEN){
if (spi)
{
SPI_close(spi);
}
}
} /* End of for loop */
Err:
if (testId != SPI_TEST_ID_WORD_LEN){
if (spi)
{
SPI_close(spi);
}
}
if (cbSem[0])
{
SPI_osalDeleteBlockingLock(cbSem[0]);
cbSem[0] = NULL;
}
return (ret);
}
static bool SPI_test_xfer_error(void *arg)
{
bool ret;
#if defined(SOC_K2G)
SPI_Handle spi;
SPI_Params spiParams;
bool transferOK;
uint32_t instance;
SPI_Tests *test = (SPI_Tests *)arg;
bool master = test->master;
uint32_t timeout = test->timeout;
uint32_t terminateXfer = 1;
uint32_t xferErr;
if (master == true)
{
ret = false;
instance = 2;
SPI_initConfig(instance, test, MCSPI_TEST_CHN, false);
/* Initialize SPI handle */
SPI_Params_init(&spiParams);
spiParams.transferTimeout = timeout;
spi = SPI_open(instance, &spiParams);
if (spi == NULL)
{
SPI_log("Error initializing SPI\n");
goto Err;
}
else
{
SPI_log("SPI initialized\n");
}
/* Initialize slave SPI transaction structure */
transaction.count = 10;
transaction.arg = (void *)&terminateXfer;
transaction.txBuf = (void *)masterTxBuffer;
transaction.rxBuf = (void *)masterRxBuffer;
/* Initiate SPI transfer */
SPI_test_xfer_ctrl(spi, 1);
transferOK = SPI_transfer((SPI_Handle)spi, &transaction);
if(transferOK)
{
SPI_test_xfer_ctrl(spi, 0);
SPI_control(spi, SPI_V0_CMD_GET_XFER_ERR, (void *)&xferErr);
if (xferErr == SPI_XFER_ERR_RXOR)
{
SPI_log("Receive overrun error detected\n");
}
else if (xferErr == SPI_XFER_ERR_BE)
{
SPI_log("Bit error detected\n");
}
else
{
SPI_log("No error detected\n");
}
ret = true;
}
/*
* master sleep for 1 second after each transfer
* to sync with slave transfer
*/
#ifdef USE_BIOS
Task_sleep(1000);
#else
#endif
Err:
if (spi)
{
SPI_close(spi);
}
}
else
{
/* slave do nothing for xfer error test */
ret = true;
}
#else
ret = true;
#endif
return (ret);
}
#ifdef MCSPI_MULT_CHANNEL
static bool SPI_test_multi_channel(void *arg)
{
MCSPI_Handle spi[MCSPI_MAX_NUM_CHN];
MCSPI_Params spiParams;
uint32_t instance, i;
bool ret = false;
uint32_t chn, maxNumChn, testChn;
MCSPI_CallbackFxn cbFxn[MCSPI_MAX_NUM_CHN] = {MCSPI_callback0, MCSPI_callback1, MCSPI_callback2, MCSPI_callback3};
SPI_Tests *test = (SPI_Tests *)arg;
int32_t testId = test->testId;
bool master = test->master;
bool cbMode = test->cbMode;
uint32_t timeout = test->timeout;
if (cbMode == true)
{
/* Create call back semaphore */
SPI_osalSemParamsInit(&cbSemParams);
cbSemParams.mode = SemaphoreP_Mode_BINARY;
}
/* Soc configuration structures indexing starts from 0. If the IP
* instances start with 1, to address proper Configuration
* structure index, McSPI Instance should be substracted with 1
*/
if (master == true)
{
instance = (uint32_t)BOARD_MCSPI_MASTER_INSTANCE - 1;
}
else
{
instance = (uint32_t)BOARD_MCSPI_SLAVE_INSTANCE - 1;
}
testChn = MCSPI_TEST_CHN;
SPI_initConfig(instance, test, testChn, false);
/* Initialize SPI handle */
MCSPI_Params_init(&spiParams);
if (master == false)
{
spiParams.mode = SPI_SLAVE;
}
if (cbMode == true)
{
spiParams.transferMode = SPI_MODE_CALLBACK;
}
spiParams.transferTimeout = timeout;
if (testId == SPI_TEST_ID_WORD_LEN)
{
spiParams.dataSize = test->param;
}
if (master == true)
{
maxNumChn = MCSPI_MAX_NUM_CHN;
}
else
{
/* Only 1 channel supported in slave mode */
maxNumChn = 1;
}
for (i = 0; i < maxNumChn; i++)
{
if (master == true)
{
chn = i;
}
else
{
chn = testChn;
}
if (cbMode == true)
{
cbSem[chn] = SPI_osalCreateBlockingLock(0, &cbSemParams);
spiParams.transferCallbackFxn = cbFxn[chn];;
}
spi[chn] = MCSPI_open(instance, chn, &spiParams);
if (spi[chn] == NULL)
{
SPI_log("Error initializing SPI instance %d channel %d\n",
instance, chn);
goto Err;
}
else
{
SPI_log("SPI instance %d channel %d\n",
instance, chn);
}
}
for (i = 0; i < SPI_NUM_XFERS; i++)
{
if (SPI_test_mst_slv_xfer((void *)(spi[testChn]), test, spi_test_xfer_len[i], true) == false)
{
goto Err;
}
if ((master == true) && (testId < SPI_TEST_ID_LOOPBACK))
{
/*
* master sleep for 1 second after each transfer
* to sync with slave transfer
*/
#ifdef USE_BIOS
Task_sleep(1000);
#else
#endif
}
}
ret = true;
Err:
for (i = 0; i < maxNumChn; i++)
{
if (master == true)
{
chn = i;
}
else
{
chn = testChn;
}
if (spi[chn])
{
MCSPI_close(spi[chn]);
}
if (cbSem[chn])
{
SPI_osalDeleteBlockingLock(cbSem[chn]);
cbSem[chn] = NULL;
}
}
return (ret);
}
#endif
void SPI_test_print_test_desc(SPI_Tests *test)
{
char testId[16] = {0, };
/* Print unit test ID */
sprintf(testId, "%d", (int)test->testId);
SPI_log("\r\n SPI UT %s\r\n", testId);
/* Print test description */
SPI_log("\r\n %s\r\n", test->testDesc);
}
SPI_Tests Spi_tests_master[] =
{
#ifndef SPI_MASTERONLY_TESTS
/* testFunc testID master pollMode cbMode dmaMode timeout testDesc */
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in dma mode", },
#endif
{SPI_test_single_channel, SPI_TEST_ID_INT, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_POLL, true, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in polling mode"},
{SPI_test_single_channel, SPI_TEST_ID_CB, true, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA_CB, true, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master in dma callback mode", },
#endif
{SPI_test_xfer_error, SPI_TEST_ID_XFER_ERR, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master transfer error test in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_PHA_POL, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master phase polarity test in non-dma interrupt mode", 1, },
#ifdef MCSPI_MULT_CHANNEL
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in dma mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_MC_INT, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in non-dma interrupt mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_POLL, true, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in polling mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_CB, true, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA_CB, true, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel in dma callback mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_TX_ONLY, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel TX_ONLY test", 0, },
#endif
#endif
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_WORD_LEN, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master data size test in loopback dma mode", SPI_TEST_DATA_SIZE, },
#endif
{SPI_test_single_channel, SPI_TEST_ID_WORD_LEN, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master data size test in loopback mode", SPI_TEST_DATA_SIZE, },
#ifdef MCSPI_MULT_CHANNEL
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_TRIG_LVL, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master multi channel FIFO trigger level test in loopback dma mode", SPI_TEST_TRIG_LVL, },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_TRIG_LVL, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master multi channel FIFO trigger level test in loopback mode", SPI_TEST_TRIG_LVL, },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_TCS, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel TCS test in dma mode", SPI_TEST_TCS, },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_TCS, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel TCS test", SPI_TEST_TCS, },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_INIT_DELAY, true, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel init delay test in dma mode", SPI_TEST_INIT_DELAY, },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_INIT_DELAY, true, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master multi channel init delay test", SPI_TEST_INIT_DELAY, },
#endif
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA_CB_CANCEL, true, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master transmit cancel in dma callback mode", },
#endif
{SPI_test_single_channel, SPI_TEST_ID_CB_CANCEL, true, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test master transmit cancel in non-dma callback mode", },
/* NOTE: Timeout Test case should be executed as the final test, as this test requires no transaction on the data lines
* for the timeout to happen */
{SPI_test_single_channel, SPI_TEST_ID_TIMEOUT, false, false, false, false, SPI_TIMEOUT_VALUE, "\r\n SPI timeout test in interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_TIMEOUT_POLL, false, true, false, false, SPI_TIMEOUT_VALUE, "\r\n SPI timeout test in polling mode", },
{NULL, },
};
SPI_Tests Spi_tests_slave[] =
{
#ifndef SPI_MASTERONLY_TESTS
/* testFunc testID master pollMode cbMode dmaMode, timeout testDesc */
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA, false, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in dma mode", },
#endif
{SPI_test_single_channel, SPI_TEST_ID_INT, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_POLL, false, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in polling mode", },
{SPI_test_single_channel, SPI_TEST_ID_CB, false, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_single_channel, SPI_TEST_ID_DMA_CB, false, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in dma callback mode", },
#endif
{SPI_test_xfer_error, SPI_TEST_ID_XFER_ERR, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI slave transfer error test in non-dma interrupt mode", },
{SPI_test_single_channel, SPI_TEST_ID_PHA_POL, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI slave phase polarity test in non-dma interrupt mode", 1, },
#ifdef MCSPI_MULT_CHANNEL
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA, false, false, false, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave multi channel in dma mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_MC_INT, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave multi channel in non-dma interrupt mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_POLL, false, true, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in polling mode", },
{SPI_test_multi_channel, SPI_TEST_ID_MC_CB, false, false, true, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in non-dma callback mode", },
#ifdef SPI_DMA_ENABLE
{SPI_test_multi_channel, SPI_TEST_ID_MC_DMA_CB, false, false, true, true, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave in dma callback mode", },
#endif
{SPI_test_multi_channel, SPI_TEST_ID_RX_ONLY, false, false, false, false, SemaphoreP_WAIT_FOREVER, "\r\n SPI master slave test slave multi channel RX_ONLY test", 0, },
#endif
#endif
{NULL, },
};
/*
* ======== slaveTaskFxn ========
* The task is part of separate slave example project.
* To test slave mode example, slave task has to be
* ready for master. Slave SPI sends a message to master
* while receiving message from master.
*/
#ifdef USE_BIOS
Void slaveTaskFxn (UArg arg0, UArg arg1)
#else
void slaveTaskFxn()
#endif
{
uint32_t i;
bool testFail = false;
SPI_Tests *test;
SPI_init();
for (i = 0; ; i++)
{
if (evmAM570x == true)
{
/* Slave mode test not supported on AM570x EVM */
break;
}
test = &Spi_tests_slave[i];
if (test->testFunc == NULL)
break;
if (test->testId >= SPI_TEST_ID_LOOPBACK)
{
/* bypass the loopback test for slave task */
break;
}
SPI_test_print_test_desc(test);
if (test->testFunc((void *)test) == true)
{
SPI_log("\r\n %s have passed\r\n", test->testDesc);
}
else
{
SPI_log("\r\n %s have failed\r\n", test->testDesc);
testFail = true;
break;
}
}
if(testFail == true)
{
SPI_log("\n Some tests have failed. \n");
}
else
{
SPI_log("\n All tests have passed. \n");
}
SPI_log("Done\n");
while (true)
{
}
}
/*
* ======== masterTaskFxn ========
* This task is part of master example project.
* Slave task has to ensure transaction ready.
* Master SPI sends a message to slave and
* receives message from slave.
*/
#ifdef USE_BIOS
Void masterTaskFxn (UArg arg0, UArg arg1)
#else
void masterTaskFxn()
#endif
{
uint32_t i;
bool testFail = false;
SPI_Tests *test;
SPI_init();
// for (i = 0; ; i++)
for (i = 3; ; i++)
{
test = &Spi_tests_master[i];
if (test->testFunc == NULL)
break;
#if defined (SOC_AM65XX) || defined(SOC_J721E)
if ((test->testId < SPI_TEST_ID_LOOPBACK) &&
(test->testId != SPI_TEST_ID_TIMEOUT) &&
(test->testId != SPI_TEST_ID_TIMEOUT_POLL))
continue;
#endif
if (evmAM570x == true)
{
/* Only loopback test supported on AM570x EVM */
if ((test->testId < SPI_TEST_ID_LOOPBACK) &&
(test->testId != SPI_TEST_ID_TIMEOUT) &&
(test->testId != SPI_TEST_ID_TIMEOUT_POLL))
continue;
}
SPI_test_print_test_desc(test);
if (test->testFunc((void *)test) == true)
{
SPI_log("\r\n %s have passed\r\n", test->testDesc);
}
else
{
SPI_log("\r\n %s have failed\r\n", test->testDesc);
testFail = true;
break;
}
}
if(testFail == true)
{
SPI_log("\n Some tests have failed. \n");
}
else
{
SPI_log("\n All tests have passed. \n");
}
SPI_log("Done\n");
while (true)
{
}
}
/*
* ======== main ========
*/
int main(void)
{
/* Call board init functions */
Board_initCfg boardCfg;
Board_STATUS boardStatus;
#if defined (evmK2G)
SPI_v0_HWAttrs spi_cfg;
uint8_t instance;
Board_SoCInfo socInfo;
#endif
#if defined (idkAM571x)
Board_IDInfo id;
#endif
#ifdef USE_BIOS
#if defined(SOC_AM335x) || defined (SOC_AM437x) || defined (SOC_AM65XX) || defined(SOC_J721E)
Task_Handle task;
Error_Block eb;
Error_init(&eb);
#if defined (MCSPI_SLAVE_TASK)
task = Task_create(slaveTaskFxn, NULL, &eb);
#elif defined (MCSPI_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 */
#endif /* #ifdef USE_BIOS */
boardCfg = BOARD_INIT_PINMUX_CONFIG |
BOARD_INIT_MODULE_CLOCK |
BOARD_INIT_UART_STDIO;
boardStatus = Board_init(boardCfg);
if (boardStatus != BOARD_SOK)
{
return (0);
}
#if defined(SOC_AM65XX) || defined(SOC_J721E)
#if defined (__TI_ARM_V7R4__)
/* Configure the MCU SPI0_D1 pinmux, since it is not set by default in board */
HW_WR_REG32((WKUP_PINMUX_REG_BASE + MCU_SPI0_D1_PADCFG_OFFSET), PIN_MODE(0) | \
((PIN_PULL_DISABLE | PIN_INPUT_ENABLE) & (~PIN_PULL_DIRECTION)));
/* Configure the MCU SPI0_CLK pinmux to support loopback */
HW_WR_REG32((WKUP_PINMUX_REG_BASE + MCU_SPI0_CLK_PADCFG_OFFSET), PIN_MODE(0) | \
((PIN_PULL_DISABLE | PIN_INPUT_ENABLE) & (~PIN_PULL_DIRECTION)));
#endif
#endif
#if defined (idkAM571x)
boardStatus = Board_getIDInfo(&id);
if (boardStatus != BOARD_SOK)
{
return (0);
}
/* Check if is DRA (AM570x) SoC */
if ((id.boardName[0] == 'D') &&
(id.boardName[1] == 'R') &&
(id.boardName[2] == 'A'))
{
evmAM570x = true;
}
#endif
#if defined(iceAMIC110)
/* GPIO initialization */
GPIO_init();
/* Set BUS_Switch_ENABLE pin to low for enabling the switch */
GPIO_write((GPIO_BUS_SWITCH_ENABLE_OFFSET), GPIO_PIN_VAL_LOW);
#endif
#if defined (evmK2G)
/* Read the SoC info to get the System clock value */
Board_getSoCInfo(&socInfo);
if(socInfo.sysClock != BOARD_SYS_CLK_DEFAULT)
{
/* Since this is a generic SPI test,
* configure the input clock for all the available instances */
for (instance = 0; instance < CSL_SPI_CNT; instance++)
{
SPI_socGetInitCfg(instance, &spi_cfg);
/* Update the I2C functional clock based on CPU clock - 1G or 600MHz */
spi_cfg.inputClkFreq = socInfo.sysClock/SPI_MODULE_CLOCK_DIVIDER;
SPI_socSetInitCfg(instance, &spi_cfg);
}
}
#endif
#ifdef USE_BIOS
/* Start BIOS */
BIOS_start();
#else
#ifdef MCSPI_MASTER_TASK
masterTaskFxn();
#else
slaveTaskFxn();
#endif
#endif
return (0);
}
#if defined(BUILD_MPU) || defined (__C7100__)
extern void Osal_initMmuDefault(void);
void InitMmu(void)
{
Osal_initMmuDefault();
}
#endif
Anping,
Thanks, I don't see any significant differences between your code and mine.
Can you please answer the other two questions:
>> How is your hardware connected? Do you have two BBB's connected as described in the docs?
>> BTW Have you tried debuggin this on your own by stepping into UART_printf() on Line 832?
Hi Frank
I load the code to my BBB. I debug on my own by step into UART_printf() on Line 832. It crash when it try to get semaphore. Please pay attention on callback function. In fact no matter SPI or UART callback test case in your example projects, If you add UART_printf() in callback function, it will crash in main thread UART_printf(). I remove all UART_printf() in callback function in my test project, it works fine. I learn a lot about TI RTOS from your reply. Thanks
Hi Frank
I replace for (i = 0; ; i++) by for (i = 3; ; i++) in order to run callback test case. So it will excute
if (cbMode)// Anping: Fank, cbMode is true for callback test case
{
if (SPI_osalPendLock(cbSem[0], timeout) != SemaphoreP_OK)
{
goto Err;
}
UART_printf("\n SPI_osalPendLock!\n");
}
Thanks
Anping,
I connected two BBBs per the instructions for the example. I rebuilt the Master and Slave example code using your modified main_mcspi_slave_mode.c. In this case, the Slave code crashes on one of the UART_printf() function calls you added:
832: UART_printf("\n SPI_osalPendLock!\n");
I debugged further and found the crash actually occurs in the HWI / callback function:
UART_v1_hwiIntFxn()
UART_v1_callback()
UART_osalPostLock(object->writeSem); // ARM exception occurs here
The crash is actually some type of ARM exception which occurs inside ti_sysbios_knl_Semaphore_post__E().
If I remove the UART_printf() from SPI_callback() then the exception doesn't occur.
Is this the behavior you observe?
Regards,
Frank
Hi Frank
yes. I saw the same
UART_osalPostLock(object->writeSem); // ARM exception occurs here
You just can't use UART_printf() in callback function no matter for SPI or UART. I think there is a bug in UART_printf(). Thanks
Anping,
Understood, I'll investigate this further.
Do you actually need UART_print() in your callback function for your application, or for debugging purposes? A workaround would be to simply add some type of counter or flag (e.g. a volatile global int) to indicate whether your code had arrived at the callback. You could also use System_printf() and check the results using ROV.
Regards,
Frank
Hi Frank
I use UART_print() to trace my code. Right now I just comment out UART_print() to avoid crash. Thank you for your help.