TI工程师你们好:
前几天研究C6638的SPI1通信时给希望能提供参考DOME,在你们的推荐下,我下载了K2_STK_DSP_v1.1的参考程序。经过整理删选得到的代码可以进行SPI的自环测试。可是配置成非自环模式,使用示波器的C6638的SPI1引脚时钟,输入,输出上都未发现输出信号。整理代码如下,查了两天也未发现那里的设置出现了问题。自环模式下数据可以接收到。
摘取的整体工程代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ti/csl/csl_mpu.h>
#include <ti/csl/cslr_mpu.h>
#include <ti/csl/tistdtypes.h>
#include <ti/csl/csl_bootcfgAux.h>
#include <ti/csl/csl_pscAux.h>
#include <ti/csl/cslr_chip.h>
#include <ti/csl/csl_edma3.h>
#include <ti/csl/CSL_msmc.h>
#include <ti/csl/CSL_msmcAux.h>
#include <c6x.h>
#include <stdint.h>
#include <ti/csl/tistdtypes.h>
#include <ti/csl/cslr_pllc.h>
#include <ti/csl/cslr_xmc.h>
#include <ti/csl/cslr_cgem.h>
#include <ti/csl/csl_cgemAux.h>
#include <ti/csl/cslr_bootcfg.h>
#include <ti/csl/cslr_tpcc.h>
#include <ti/csl/cslr_tptc.h>
#include <ti/csl/cslr_device.h>
#include <ti/csl/cslr_cpintc.h>
#include <ti/csl/cslr_tmr.h>
#include <ti/csl/cslr_srio.h>
#include <ti/csl/cslr_vusr.h>
#include <ti/csl/csl_psc.h>
#include <ti/csl/csl_tmr.h>
#include <ti/csl/csl_cache.h>
#include <ti/csl/csl_cacheAux.h>
#include <ti/csl/csl_xmcAux.h>
#include <ti/csl/cslr_msmc.h>
#include <ti/csl/csl_idma.h>
#include <ti/csl/cslr_mpu.h>
#include <ti/csl/cslr_gpio.h>
#include <ti/csl/cslr_emif4f.h>
#include <ti/csl/csl_device_interrupt.h>
#include <ti/csl/cslr_tetris_vbusp.h>
#include <ti/csl/cslr_spi.h>
#include <ti/sysbios/BIOS.h>
#define SPI_LOOPBACK_TEST 1
#define SPI_TIMEOUT_CYCLES ((1000)*8*100)
typedef enum {
SPI_CS_NO_HOLD= 0, /*NO hold between words*/
SPI_CS_ALWAYS_HOLD, /*always hold between words*/
SPI_CS_NO_LAST_HOLD /*no hold for last word, CS hold for previous words*/
}SPI_CS_Hold;
typedef enum {
SPI_MSB_SHIFT_FIRST= 0,
SPI_LSB_SHIFT_FIRST
}SPI_Shift_Direction;
typedef enum {
SPI_CLOCK_LOW_INACTIVE= 0,
SPI_CLOCK_HIGH_INACTIVE
}SPI_Clock_Polarity;
unsigned int gMain_Core_Speed_Hz= 1000000000; //Main core clock speed in Hz
/*FLASH, EEPROM size in bytes, speed in KHz*/
#define SPI_FLASH_SIZE_BYTES (16*1024*1024)
#define SPI_FLASH_SPEED_KHZ 54000
typedef struct {
/*Delay between transmissions in ns. Idle time that will be
applied at the end of the current transmission if the bit
WDEL is set in the current buffer*/
Uint32 delayBetweenTrans_ns;
SPI_Shift_Direction ShifDirection;
/*No C2TDELAY or T2CDELAY is inserted in the chip select timings.*/
Uint8 disable_CS_timing;
SPI_Clock_Polarity clockPolarity;
Uint8 clockPhase;
/*SPI external clock speed in KHz < 66,000KHz*/
Uint32 clockSpeedKHz;
/*SPI data word length. Legal values are 2h (data word length = 2 bit)
to 10h (data word length = 16).*/
Uint8 wordLength;
} SPI_Data_Format;
typedef struct {
Bool TX_interruptEnable;
Bool RX_interruptEnable;
Bool overrunInterruptEnable;
Bool bitErrorInterruptEnable;
Uint8 TX_INT_map;
Uint8 RX_INT_map;
Uint8 overrun_INT_map;
Uint8 bitError_INT_map;
} SPI_Interrupt_Config;
typedef struct {
SPI_Data_Format * dataFormat[4];
Bool loopBack;
Bool DMA_requestEnable;
SPI_Interrupt_Config * interruptCfg;
/*number of SPI pins defined as:
3: SPISIMO, SPISOMI, ***
4: SPISIMO, SPISOMI, ***, SPISCS0
5: SPISIMO, SPISOMI, ***, SPISCS0, SPISCS1
6: SPISIMO, SPISOMI, ***, SPISCS0, SPISCS1, SPISCS2
…… */
Uint8 number_SPI_pins;
/*Chip-select-active-to-transmit-start-delay. It defines a setup time
for the slave device that delays the data transmission from the chip
select active edge, in ns*/
Uint32 C2T_delay_ns;
/*Transmit-end-to-chip-select-inactive-delay. It defines a hold time
for the slave device that delays the chip select deactivation (in ns)
after the last bit is transferred*/
Uint32 T2C_delay_ns;
} SPI_Config;
SPI_Config ***;
SPI_Interrupt_Config spiIntCfg;
CSL_MpuRegs * gpMPU_regs[16]= {
(CSL_MpuRegs *)CSL_MPU_0_REGS,
(CSL_MpuRegs *)CSL_MPU_1_REGS,
(CSL_MpuRegs *)CSL_MPU_2_REGS,
#ifdef CSL_MPU_3_REGS //for K2H, K2K
(CSL_MpuRegs *)CSL_MPU_3_REGS,
#else
0,
#endif
#ifdef CSL_MPU_4_REGS //for K2H, K2K
(CSL_MpuRegs *)CSL_MPU_4_REGS,
#else
0,
#endif
(CSL_MpuRegs *)CSL_MPU_5_REGS,
#ifdef CSL_MPU_6_REGS //for K2H, K2K
(CSL_MpuRegs *)CSL_MPU_6_REGS,
#else
0,
#endif
(CSL_MpuRegs *)CSL_MPU_7_REGS,
(CSL_MpuRegs *)CSL_MPU_8_REGS,
(CSL_MpuRegs *)CSL_MPU_9_REGS,
(CSL_MpuRegs *)CSL_MPU_10_REGS,
(CSL_MpuRegs *)CSL_MPU_11_REGS,
(CSL_MpuRegs *)CSL_MPU_12_REGS,
(CSL_MpuRegs *)CSL_MPU_13_REGS,
(CSL_MpuRegs *)CSL_MPU_14_REGS
#ifdef CSL_MPU_15_REGS
,(CSL_MpuRegs *)CSL_MPU_15_REGS
#else
,0
#endif
};
/*data format for NOR FLASH test*/
SPI_Data_Format FlashDataFormat =
{
/*.delayBetweenTrans_ns=*/0,
/*.ShifDirection =*/SPI_MSB_SHIFT_FIRST,
/*.disable_CS_timing =*/0,
/*.clockPolarity =*/SPI_CLOCK_LOW_INACTIVE,
/*.clockPhase =*/1,
/*.clockSpeedKHz =*/SPI_FLASH_SPEED_KHZ,
/*.wordLength =*/8
};
SPI_Data_Format EdmaDataFormat =
{
/*.delayBetweenTrans_ns = */0,
/*.ShifDirection = */SPI_MSB_SHIFT_FIRST,
/*.disable_CS_timing = */1,
/*.clockPolarity = */SPI_CLOCK_LOW_INACTIVE,
/*.clockPhase = */0,
/*.clockSpeedKHz = */66000,
/*.wordLength = */16
};
CSL_SpiRegs * gpSPI_regs[]=
{
(CSL_SpiRegs *)CSL_SPI_0_SLV_REGS
#ifdef CSL_SPI_1_SLV_REGS
,(CSL_SpiRegs *)CSL_SPI_1_SLV_REGS
#endif
#ifdef CSL_SPI_2_SLV_REGS
,(CSL_SpiRegs *)CSL_SPI_2_SLV_REGS
#endif
};
#define SPI_LOOP_TEST_BUF_SIZE (24)
/*hold CS between multiple words*/
/*SPI transfer parameters*/
typedef struct {
Uint32 CS_select; /*Chip select number*/
Uint32 formatSelect; /*select one of the 4 formats*/
SPI_CS_Hold CS_hold; /*hold CS between multiple words*/
Bool delayEnable; /*Enable the delay counter at the end of the current transaction*/
Uint32 byteOfWord; /*number of bytes per SPI word*/
}SPI_Transfer_Param;
Uint16 spiRxBuf[SPI_LOOP_TEST_BUF_SIZE/2];
Uint16 spiTxBuf[SPI_LOOP_TEST_BUF_SIZE/2];
//SPI_Data_Format loopbackDataFormat;
SPI_Transfer_Param loopbackTransferParam;
/*data format for loopback test*/
SPI_Data_Format loopbackDataFormat =
{
/*.delayBetweenTrans_ns = */0,
/*.ShifDirection = */SPI_MSB_SHIFT_FIRST,
/*.disable_CS_timing = */1,
/*.clockPolarity = */SPI_CLOCK_LOW_INACTIVE,
/*.clockPhase = */0,
/*.clockSpeedKHz = */66000,
/*.wordLength = */16
};
SPI_Transfer_Param loopbackTransferParam =
{
0, /*Chip select number*/
1, /*select one of the 4 SPI formats*/
SPI_CS_NO_LAST_HOLD, /*hold CS between multiple words*/
FALSE, /*Enable the delay counter at the end of the current transaction*/
2 /*number of bytes per SPI word*/
};
void KeyStone_MPU_interrupt_enable(Uint32 uiMPU_num)
{
if(NULL==gpMPU_regs[uiMPU_num])
{
printf("Invalid MPU number %d\n", uiMPU_num);
return;
}
if((gpMPU_regs[uiMPU_num]->REVISION&0xFFFF0000)!=
(CSL_MPU_REVISION_RESETVAL&0xFFFF0000))
{
printf("Can't read MPU%d ID register, make sure corresponding power domain is enabled.\n", uiMPU_num);
return;
}
gpMPU_regs[uiMPU_num]->FAULT_CLEAR = 1;
gpMPU_regs[uiMPU_num]->INT_ENABLED_STATUS_CLEAR =
CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_ADDR_ERR_MASK
|CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_PROT_ERR_MASK;
gpMPU_regs[uiMPU_num]->INT_ENABLE = CSL_MPU_INT_ENABLE_ADDR_ERR_EN_MASK
|CSL_MPU_INT_ENABLE_PROT_ERR_EN_MASK;
}
void K2_common_device_init()
{
KeyStone_MPU_interrupt_enable(13); //for SPI1
}
static inline unsigned int SWAP_ENDIAN(unsigned int byte_index)
{
//此处的取值不确定牛邓
#ifdef _BIG_ENDIAN
return ((byte_index&0xFFFFFFFC)+(3-byte_index&3));
#else
return byte_index;
#endif
}
static inline void KeyStone_CIC_event_map(CSL_CPINTCRegs* cpIntcRegs,
int input_event_num, int out_num)
{
/*Map input event to output*/
cpIntcRegs->CH_MAP[SWAP_ENDIAN(input_event_num)]= out_num;
/*clear input interrupts events*/
cpIntcRegs->STATUS_CLR_INDEX_REG= input_event_num;
/*enable input interrupts events*/
cpIntcRegs->ENABLE_SET_INDEX_REG= input_event_num;
/*enable output*/
cpIntcRegs->HINT_ENABLE_SET_INDEX_REG= out_num;
}
/*enable interrupt to CPU: IER |= uiIER_en_mask; GIE=1*/
void CPU_interrupt_enable(Uint32 uiIER_en_mask)
{
IER |= uiIER_en_mask;
//enable GIE niudeng add
TSR = TSR|1;
}
int uiSPI_event_num = 0;
CSL_CPINTCRegs* gpCIC0_regs = (CSL_CPINTCRegs*)CSL_CIC_0_REGS;
CSL_CgemRegs * gpCGEM_regs = (CSL_CgemRegs *)CSL_C66X_COREPAC_REG_BASE_ADDRESS_REGS;
void SPI_Interrupts_Init(void)
{
/* Disable Global host interrupts. */
gpCIC0_regs->GLOBAL_ENABLE_HINT_REG= 0;
/* Map to CIC0 out0*/
uiSPI_event_num= 0;
/*map SPI Interrupt events (54 for SPI_INT0) to CIC0 out*/
KeyStone_CIC_event_map(gpCIC0_regs, CSL_CIC0_SPI_0_INT0, uiSPI_event_num);
#ifdef CSL_CIC0_SPI_1_INT0
KeyStone_CIC_event_map(gpCIC0_regs, CSL_CIC0_SPI_1_INT0, uiSPI_event_num);
#endif
#ifdef CSL_CIC0_SPI_2_INT0
KeyStone_CIC_event_map(gpCIC0_regs, CSL_CIC0_SPI_2_INT0, uiSPI_event_num);
#endif
/* Enable Global host interrupts. */
gpCIC0_regs->GLOBAL_ENABLE_HINT_REG= 1;
#ifdef CSL_C66X_COREPAC_CIC_OUT0
gpCGEM_regs->INTMUX1 = (CSL_C66X_COREPAC_CIC_OUT0<<CSL_CGEM_INTMUX1_INTSEL6_SHIFT);
#else
gpCGEM_regs->INTMUX1 = (CSL_C66X_COREPAC_CIC_0_OUT0<<CSL_CGEM_INTMUX1_INTSEL6_SHIFT);
#endif
//enable INT6
CPU_interrupt_enable((1<<6));
}
void K2_SPI_init(Uint32 SPI_idx, SPI_Config ****)
{
int i;
Uint8 clockPreScale;
Uint8 delayBetweenTrans_clocks;
Uint16 C2T_delay_clocks;
Uint16 T2C_delay_clocks;
SPI_Data_Format * datFmt;
SPI_Interrupt_Config * intCfg;
CSL_SpiRegs * spiRegs= gpSPI_regs[SPI_idx];
if(CSL_SPI_PER_CNT<=SPI_idx)
{
puts("Invalid SPI port number!");
return;
}
/*1. Reset the SPI by clearing the RESET bit in the SPI global control register 0
(SPIGCR0) to 0.*/
spiRegs->SPIGCR0 = 0;
/*2. Take the SPI out of reset by setting SPIGCR0.RESET to 1.*/
spiRegs->SPIGCR0 = 1;
/*3. Configure the SPI for master mode by configuring the CLKMOD and MASTER
bits in the SPI global control register 1 (SPIGCR1).*/
spiRegs->SPIGCR1 =
((***->loopBack<<CSL_SPI_SPIGCR1_LOOPBACK_SHIFT)&CSL_SPI_SPIGCR1_LOOPBACK_MASK)
|((1<<CSL_SPI_SPIGCR1_CLKMOD_SHIFT)&CSL_SPI_SPIGCR1_CLKMOD_MASK)
|((1<<CSL_SPI_SPIGCR1_MASTER_SHIFT)&CSL_SPI_SPIGCR1_MASTER_MASK);
/*4. Configure the SPI for 3-pin or 4-pin with chip select mode by configuring the SPI
pin control register 0 (SPIPC0).*/
spiRegs->SPIPC0 = CSL_SPI_SPIPC0_SOMIFUN_MASK
|CSL_SPI_SPIPC0_SIMOFUN_MASK|CSL_SPI_SPIPC0_CLKFUN_MASK;
if(***->number_SPI_pins>3)
spiRegs->SPIPC0 |= CSL_SPI_SPIPC0_SCS0FUN0_MASK;
if(***->number_SPI_pins>4)
spiRegs->SPIPC0 |= CSL_SPI_SPIPC0_SCS0FUN1_MASK;
if(***->number_SPI_pins>5)
spiRegs->SPIPC0 |= CSL_SPI_SPIPC0_SCS0FUN2_MASK;
if(***->number_SPI_pins>6)
spiRegs->SPIPC0 |= CSL_SPI_SPIPC0_SCS0FUN3_MASK;
/*6. Configure the SPI data rate, character length, shift direction, phase, polarity and
other format options using SPIFMTn selected in step 5.*/
for(i= 0; i<4; i++) /*4 possible formats*/
{
if(***->dataFormat[i])
{
datFmt= ***->dataFormat[i];
if(datFmt->clockSpeedKHz > 66000)
{
printf("ERROR: SPI format %d speed higher than 66 MHz!\n", i);
continue;
}
/*SPI internal input clock is (Main core clock)/6,
it should be Prescale to expected output clock speed*/
clockPreScale= gMain_Core_Speed_Hz/6/(1000*datFmt->clockSpeedKHz);
/*round up*/
if(clockPreScale*datFmt->clockSpeedKHz<gMain_Core_Speed_Hz/1000/6)
clockPreScale++;
delayBetweenTrans_clocks = datFmt->delayBetweenTrans_ns/
(1000000000/(gMain_Core_Speed_Hz/6));
if(delayBetweenTrans_clocks<2)
delayBetweenTrans_clocks=2;
if(delayBetweenTrans_clocks > 65)
{
puts("ERROR: delay between transmissions > 65*6 Main core clocks!");
continue;
}
spiRegs->SPIFMT[i]=
(((delayBetweenTrans_clocks-2)<<CSL_SPI_SPIFMT_WDELAY_SHIFT)&CSL_SPI_SPIFMT_WDELAY_MASK)
|((datFmt->ShifDirection<<CSL_SPI_SPIFMT_SHIFTDIR_SHIFT)&CSL_SPI_SPIFMT_SHIFTDIR_MASK)
|((datFmt->disable_CS_timing<<CSL_SPI_SPIFMT_DISCSTIMERS_SHIFT)&CSL_SPI_SPIFMT_DISCSTIMERS_MASK)
|((datFmt->clockPolarity<<CSL_SPI_SPIFMT_POLARITY_SHIFT)&CSL_SPI_SPIFMT_POLARITY_MASK)
|((datFmt->clockPhase<<CSL_SPI_SPIFMT_PHASE_SHIFT)&CSL_SPI_SPIFMT_PHASE_MASK)
|(((clockPreScale-1)<<CSL_SPI_SPIFMT_PRESCALE_SHIFT)&CSL_SPI_SPIFMT_PRESCALE_MASK)
|((datFmt->wordLength<<CSL_SPI_SPIFMT_CHARLEN_SHIFT)&CSL_SPI_SPIFMT_CHARLEN_MASK);
}
}
/*The timeing value is calculated as follows:
tC2TDELAY = (C2TDELAY + 2) × SPI module clock period
Note: If C2TDELAY = 0, then tC2TDELAY = 0.*/
C2T_delay_clocks = ***->C2T_delay_ns/(1000000000/(gMain_Core_Speed_Hz/6));
if(2==C2T_delay_clocks||3==C2T_delay_clocks)
C2T_delay_clocks= 1;
if(C2T_delay_clocks>4)
C2T_delay_clocks -= 2;
T2C_delay_clocks = ***->T2C_delay_ns/(1000000000/(gMain_Core_Speed_Hz/6));
if(2==T2C_delay_clocks||3==T2C_delay_clocks)
T2C_delay_clocks= 1;
if(T2C_delay_clocks>4)
T2C_delay_clocks -= 2;
if(C2T_delay_clocks > 255)
{
C2T_delay_clocks = 255;
puts("ERROR: Chip-select-active-to-transmit-start-delay > 257*6 Main core clocks");
}
if(T2C_delay_clocks > 255)
{
T2C_delay_clocks = 255;
puts("ERROR: Transmit-end-to-chip-select-inactive-delay > 257*6 Main core clocks");
}
/*7. In master mode, configure the master delay options using the SPI delay register
(SPIDELAY).*/
spiRegs->SPIDELAY= (C2T_delay_clocks<<CSL_SPI_SPIDELAY_C2TDELAY_SHIFT)
|(T2C_delay_clocks<<CSL_SPI_SPIDELAY_T2CDELAY_SHIFT);
/*the CS_polarity is defined as invert of the register field*/
//spiRegs->SPIDEF = !***->CS_polarity;
spiRegs->SPIDEF = 0xFF;
/*8. Select the error interrupt notifications by configuring the SPI interrupt register
(SPIINT0) and the SPI interrupt level register (SPILVL).*/
if(***->interruptCfg)
{
intCfg= ***->interruptCfg;
spiRegs->SPILVL =
((intCfg->TX_INT_map<<CSL_SPI_SPILVL_TXINTLVL_SHIFT)&CSL_SPI_SPILVL_TXINTLVL_MASK)
|((intCfg->RX_INT_map<<CSL_SPI_SPILVL_RXINTLVL_SHIFT)&CSL_SPI_SPILVL_RXINTLVL_MASK)
|((intCfg->overrun_INT_map<<CSL_SPI_SPILVL_OVRNINTLVL_SHIFT)&CSL_SPI_SPILVL_OVRNINTLVL_MASK)
|((intCfg->bitError_INT_map<<CSL_SPI_SPILVL_BITERRLVL_SHIFT)&CSL_SPI_SPILVL_BITERRLVL_MASK);
spiRegs->SPIINT0 =
((intCfg->TX_interruptEnable<<CSL_SPI_SPIINT0_TXINTENA_SHIFT)&CSL_SPI_SPIINT0_TXINTENA_MASK)
|((intCfg->RX_interruptEnable<<CSL_SPI_SPIINT0_RXINTENA_SHIFT)&CSL_SPI_SPIINT0_RXINTENA_MASK)
|((intCfg->overrunInterruptEnable<<CSL_SPI_SPIINT0_OVRNINTENA_SHIFT)&CSL_SPI_SPIINT0_OVRNINTENA_MASK)
|((intCfg->bitErrorInterruptEnable<<CSL_SPI_SPIINT0_BITERRENA_SHIFT)&CSL_SPI_SPIINT0_BITERRENA_MASK);
}
if(***->DMA_requestEnable)
{//when EDMA is enabled, CPU should not handle TX/RX interrupt
spiRegs->SPIINT0 &= ~(CSL_SPI_SPIINT0_TXINTENA_MASK|
CSL_SPI_SPIINT0_RXINTENA_MASK);
}
/*9. Enable the SPI communication by setting the SPIGCR1.ENABLE to 1.*/
spiRegs->SPIGCR1 |=
((1<<CSL_SPI_SPIGCR1_ENABLE_SHIFT)&CSL_SPI_SPIGCR1_ENABLE_MASK);
/*10. Setup and enable the DMA for SPI data handling and then enable the DMA
servicing for the SPI data requests by setting the SPIINT0.DMAREQEN to 1.*/
spiRegs->SPIINT0 |= (***->DMA_requestEnable<<CSL_SPI_SPIINT0_DMAREQEN_SHIFT);
}
void SPI_Init(Uint32 SPI_idx)
{
/*data format for NOR FLASH test*/
// ***.dataFormat[0]= &FlashDataFormat;
/*data format for loopback test*/
***.dataFormat[1]= &loopbackDataFormat;
/*data format for EDMA loopback test*/
// ***.dataFormat[2]= &EdmaDataFormat;
spiIntCfg.overrunInterruptEnable= TRUE;
spiIntCfg.bitErrorInterruptEnable= TRUE;
***.interruptCfg = &spiIntCfg;
***.number_SPI_pins = 4;
K2_SPI_init(SPI_idx, &***);
}
/*make the higher 16-bit of the SPIDAT1 register*/
#define SPI_TRANSMIT_FORMAT_MAKE(CS_hold_enable, delay_enable, formatSelect, CS_select)\
(Uint32)(\
CSL_FMKR(28,28,CS_hold_enable) \
|CSL_FMKR(26,26,delay_enable) \
|CSL_FMKR(25,24,formatSelect) \
|CSL_FMKR(23,16,~(1<<CS_select)))
/*construct data format: higher 16 bit of SPIDAT1.
"dataFormat" is for data except the last one,
"lastDataFormat" is for the last word.
input: transfer parameters structure pointer*/
void KeyStone_SPIDAT1_format(SPI_Transfer_Param * transfer,
Uint32 *dataFormat, Uint32 *lastDataFormat)
{
if(SPI_CS_NO_HOLD== transfer->CS_hold)
*dataFormat= SPI_TRANSMIT_FORMAT_MAKE(0, transfer->delayEnable,
transfer->formatSelect, transfer->CS_select);
else
*dataFormat= SPI_TRANSMIT_FORMAT_MAKE(1, transfer->delayEnable,
transfer->formatSelect, transfer->CS_select);
/*treat last word specially for CS hold*/
if(SPI_CS_ALWAYS_HOLD== transfer->CS_hold)
*lastDataFormat= SPI_TRANSMIT_FORMAT_MAKE(1, transfer->delayEnable,
transfer->formatSelect, transfer->CS_select);
else
*lastDataFormat= SPI_TRANSMIT_FORMAT_MAKE(0, transfer->delayEnable,
transfer->formatSelect, transfer->CS_select);
}
unsigned int cycle_measure_overhead=50;
/*wait a flag in SPIFLG,
retun 1 when the SPIFLG&flag_mask=expect, return 0 when timeout*/
#define TSC_getDelay(startTSC) ((unsigned int)((0xFFFFFFFFl+TSCL)- (unsigned long long)startTSC)+ 1)
#define TSC_count_cycle_from(startTSC) (TSC_getDelay(startTSC)- cycle_measure_overhead)
Int32 K2_SPI_wait_flag(Uint32 SPI_idx, Uint32 flag_mask, Uint32 expect)
{
Uint32 startTSC;
Uint32 delay;
volatile Uint32 flag;
CSL_SpiRegs * spiRegs= gpSPI_regs[SPI_idx];
if(CSL_SPI_PER_CNT<=SPI_idx)
{
puts("Invalid SPI port number!");
return 0;
}
startTSC= TSCL;
flag= spiRegs->SPIFLG&flag_mask;
/*Wait until SPI flag= expect value*/
while(flag!= expect)
{
/*if wait time is much larger than theoretical transfer time of
a byte, then it is looked as timeout.*/
delay= TSC_getDelay(startTSC);
if(delay> SPI_TIMEOUT_CYCLES)
{
printf("SPI port %d wait flag 0x%x timeout, SPIFLG=0x%x\n",
SPI_idx, flag_mask, spiRegs->SPIFLG);
return 0;
}
flag= spiRegs->SPIFLG&flag_mask;
};
return 1;
}
Uint32 K2_SPI_TxRx(Uint32 SPI_idx, Uint8 * txBuf, Uint32 firstTxByte,
Uint32 numTxByte, Uint8 * rxBuf, Uint32 firstRxByte, Uint32 numRxByte,
SPI_Transfer_Param * transfer)
{
Int32 i;
Int32 length;
Uint32 txData, rxData;
Uint32 byteOfWord, dataFormat, lastDataFormat;
CSL_SpiRegs * spiRegs;
if(CSL_SPI_PER_CNT<=SPI_idx)
{
puts("Invalid SPI port number!");
return 0;
};
spiRegs= gpSPI_regs[SPI_idx];
/*total transfer word length is the max of the lastRxWord and lastTxWord*/
if((firstTxByte+numTxByte)>(firstRxByte+numRxByte))
length= (firstTxByte+numTxByte);
else
length= (firstRxByte+numRxByte);
/*——data format: higher 16 bit of SPIDAT1——*/
KeyStone_SPIDAT1_format(transfer, &dataFormat, &lastDataFormat);
printf("transfer->byteOfWord=%x\n",transfer->byteOfWord);
byteOfWord= transfer->byteOfWord;
if(length==byteOfWord)
dataFormat= lastDataFormat;
/*——–write the first word——–*/
if((firstTxByte==0)&&(0<firstTxByte+numTxByte))
{/*only TX valid data from the "firstTxByte"*/
if(2==byteOfWord)
{/*two bytes*/
txData= *(Uint16 *)txBuf;
txBuf+=2;
}
else
{/*one byte*/
txData= *txBuf++;
}
}
else
txData= 0;
txData |= dataFormat;
/* Wait for room in TX buffer */
if(0==K2_SPI_wait_flag(SPI_idx, CSL_SPI_SPIFLG_TXINTFLG_MASK,
CSL_SPI_SPIFLG_TXINTFLG_MASK))
return 0;
/* Send the word */
spiRegs->SPIDAT1 = txData;
/*——–write the word n+1 while read word n——–*/
for( i=0; i<length-byteOfWord; i+= byteOfWord )
{
if((firstTxByte<=i+byteOfWord)&&(i+byteOfWord<firstTxByte+numTxByte))
{/*only TX valid data from the "firstTxByte"*/
if(2==byteOfWord)
{/*two bytes*/
txData= *(Uint16 *)txBuf;
txBuf+=2;
}
else
{/*one byte*/
txData= *txBuf++;
}
}
else
txData= 0;
if(i+byteOfWord==length-byteOfWord) /*the last word*/
txData |= lastDataFormat;
else
txData |= dataFormat;
/* Wait for room in TX buffer */
if(0==K2_SPI_wait_flag(SPI_idx, CSL_SPI_SPIFLG_TXINTFLG_MASK,
CSL_SPI_SPIFLG_TXINTFLG_MASK))
return i+byteOfWord; //等待上一包数据传输完成
/* Send the word */
spiRegs->SPIDAT1 = txData; //下发下一包数据
/* Wait for data in RX buffer */
if(0==K2_SPI_wait_flag(SPI_idx, CSL_SPI_SPIFLG_RXINTFLG_MASK,
CSL_SPI_SPIFLG_RXINTFLG_MASK)) //检查有没有收到数据
return i;
/* Read the next word */
rxData = spiRegs->SPIBUF&0xFFFF; //收到数据完成
if((firstRxByte<=i)&&(i<firstRxByte+numRxByte))
{/*only RX valid data from the "firstRxByte"*/
if(2==byteOfWord)
{/*two bytes*/
*(Uint16 *)rxBuf= rxData;
rxBuf+=2;
}
else
{/*one byte*/
*rxBuf++= rxData;
}
}
}
//程序执行到这里出现问题
/*——–read the last word——–*/
/* Wait for data in RX buffer */
if(0==K2_SPI_wait_flag(SPI_idx, CSL_SPI_SPIFLG_RXINTFLG_MASK,
CSL_SPI_SPIFLG_RXINTFLG_MASK))
return length-byteOfWord;
/* Read the next word */
rxData = spiRegs->SPIBUF&0xFFFF;
if((firstRxByte<=length-byteOfWord)&&(length-byteOfWord<firstRxByte+numRxByte))
{/*only RX valid data from the "firstRxByte"*/
if(2==byteOfWord)
{/*two bytes*/
*(Uint16 *)rxBuf= rxData;
rxBuf+=2;
}
else
{/*one byte*/
*rxBuf++= rxData;
}
}
return length;
}
int SPI_loopback_test_one_time(Uint32 SPI_idx, Uint16 dataPattern)
{
int i, iByteSuccess;
Uint32 startTSC, cycles, throughput;
for(i=0; i<SPI_LOOP_TEST_BUF_SIZE/2; i++)
{
spiTxBuf[i]= dataPattern;
//spiRxBuf[i]= ~dataPattern;
spiRxBuf[i]= 0x0000;
}
startTSC= TSCL;
iByteSuccess= K2_SPI_TxRx(SPI_idx, (Uint8 *) spiTxBuf, 0,
SPI_LOOP_TEST_BUF_SIZE, (Uint8 *) spiRxBuf, 0,
SPI_LOOP_TEST_BUF_SIZE, &loopbackTransferParam);
cycles= TSC_count_cycle_from(startTSC);
if(iByteSuccess!=SPI_LOOP_TEST_BUF_SIZE)
{
printf("SPI loopback test failed. TX %d bytes, RX %d bytes!\n",
SPI_LOOP_TEST_BUF_SIZE, iByteSuccess);
return iByteSuccess;
}
for(i=0; i<SPI_LOOP_TEST_BUF_SIZE/2; i++)
{
if(spiTxBuf[i]!=spiRxBuf[i])
{
printf("SPI loopback test failed at word %d: TX 0x%x, RX 0x%x\n",
i, spiTxBuf[i], spiRxBuf[i]);
return i;
}
}
throughput = (unsigned long long)SPI_LOOP_TEST_BUF_SIZE*8*gMain_Core_Speed_Hz/
((unsigned long long)cycles*1000000);
printf("SPI loopback test passed with data pattern 0x%x. Throughput= %dMbps\n",
dataPattern, throughput);
return SPI_LOOP_TEST_BUF_SIZE;
}
void SPI_loopback_test(Uint32 SPI_idx)
{
SPI_loopback_test_one_time(SPI_idx, 0x1234);
}
int main(void)
{
K2_common_device_init();
/*clear configuration structure to default values*/
memset(&***, 0, sizeof(***));
memset(&spiIntCfg, 0, sizeof(spiIntCfg));
SPI_Interrupts_Init();
//***.loopBack = TRUE;//配置成自环模式
***.loopBack = FALSE//配置成非自环模式 SPI1未发现有信号输出。
***.DMA_requestEnable= FALSE;
SPI_Init(CSL_SPI_1);
printf("\nSPI port %d internal loopback test at %dMHz…\n",
CSL_SPI_1, loopbackDataFormat.clockSpeedKHz/1000);
SPI_loopback_test(CSL_SPI_1);
BIOS_start();
}
不知道为何将自环模式修改成非自环模式,SPI1未有时钟和信号输出。请指教。。。。。
Nancy Wang:
有直接测试过软件包里的nor flash test吗?这个例程是非自环模式下的。
user5315971:
回复 Nancy Wang:
谢谢,我用那个nor flashtest测试了,发下数据可以正常处理,感谢。