2
« on: March 22, 2021, 03:50:39 PM »
Hello All,
I've been trying to get SPI working between PIC32 on UBW32 and FT810 chip on VM81050A-D board. I have worked with SPI on PIC32 + MPLAB X IDE etc before this and never faced this issue.
Connections:
#define SPI_CSELECT_DIR TRISGbits.TRISG9 //SPI CS
#define SPI_CSELECT LATGbits.LATG9
#define SPI_SCLK_DIR TRISGbits.TRISG6 //SPI SCLK (SCK2)
#define SPI_SCLK PORTGbits.RG6
#define SPI_OUT_DIR TRISGbits.TRISG8 //SPI DATA (SD02)
#define SPI_OUT LATGbits.LATG8
#define SPI_IN_DIR TRISGbits.TRISG7 //SPI DATA (SDI2)
#define SPI_IN LATGbits.LATG7 //LATGbits.LATG7
#define SPI_PD_DIR TRISBbits.TRISB8 //SPI PD pin
#define SPI_PD LATBbits.LATB8
#define SPI_INT_DIR TRISBbits.TRISB5 //SPI INT pin
#define SPI_INT LATBbits.LATB5
ODCG = 0; //Turn OFF open-drain outputs on PORTG
RE1_LED_DIR = OUTPUT; //Debug LED RE1 present on MCU board
SPI_CSELECT_DIR = OUTPUT; //Chip select for SPI
SPI_SCLK_DIR = OUTPUT; //Serial Clock
SPI_OUT_DIR = OUTPUT; //Data byte MOSI
//0x200|0x80: Change Notice Enable for RG7 (CNEN9) and RB5 (CNEN7)
CNENSET = (_CNEN_CNEN9_MASK | _CNEN_CNEN7_MASK);
//0x200|0x80: Internal pull-up Enable for RG7 (CNPUE9) and RB5 (CNPUE7)
CNPUESET = (_CNPUE_CNPUE9_MASK | _CNPUE_CNPUE7_MASK);
SPI_IN_DIR = INPUT; //Data byte MISO
SPI_PD_DIR = OUTPUT; //Controls PD pin
SPI_INT_DIR = INPUT; //Comes from FT810
I am using the example project referenced in BRT_AN_006 by Bridgetek (it uses 8 bit PIC but I changed the config bits to use a PIC32 instead).
SD0 pin of PIC32 is connected to MOSI of FT810.
SDI pin of PIC32 is connected to MISO of FT810.
I am able to drive the MOSI pin with no issues(verified using a picoscope).
MISO pin is not being driven properly (Attached an image) - the signal is pulled down to the ground but it doesn't go back up to 3.3 V.
Any suggestions?
I tried adding a pullup resistor to the slave side (but SPI is not open drain but I still tried) but didn't help.
I tried SPI loopback test by connecting SDO pin to SDI pin and it works. So, I am assuming that my SPI configuration is correct.
SPI config:
SPI clk frequencies tried: 10 MHZ, 5 MHz
//Disable All SPI 2 Interrupts
IEC1CLR = _IEC1_SPI2TXIE_MASK | _IEC1_SPI2RXIE_MASK | _IEC1_SPI2EIE_MASK;
//Clear All SPI 2 Interrupt Flags
IFS1CLR = _IFS1_SPI2TXIF_MASK | _IFS1_SPI2RXIF_MASK | _IFS1_SPI2EIF_MASK;
//Stop and Reset the SPI Module by clearing the ON bit
SPI2CONbits.ON = 0; //Disable SPI 2
//Clear the SPI2 receive buffer
SPI2BUF = 0;
//SPI2 Interrupts --------------------------------------------------------
IPC7CLR = _IPC7_SPI2IP_MASK; //Clear Interrupt Priority
//Set SPI2 Priority to 1
IPC7SET = _IPC7_SPI2IP_MASK & ( SPI_Priority << _IPC7_SPI2IP_POSITION );
IPC7CLR = _IPC7_SPI2IS_MASK; //Clear Sub Priority
//Set SPI2 Sub-Priority to 0
IPC7SET = _IPC7_SPI2IS_MASK & ( SPI_Sub_Priority << _IPC7_SPI2IS_POSITION );
//Do not enable SPI2 interrupts here
//Clear All SPI 2 Interrupt Flags
IFS1CLR = _IFS1_SPI2TXIF_MASK | _IFS1_SPI2RXIF_MASK | _IFS1_SPI2EIF_MASK;
//SPI2 Interrupts --------------------------------------------------------
//SET Clock Frequency
SPI2BRG = SPI_SCK_FREQ; // 5 MHz
//Clear SPI receive buffer overflow indication bit
SPI2STATbits.SPIROV = 0;
//Bit 28 MSSEN: Master Mode Slave Select Enable bit
SPI2CONbits.MSSEN = 1; //(1=SS Pin Controlled by SPI Module)
//Bit 16 ENHBUF : Enhanced Buffer Enable bit
SPI2CONbits.ENHBUF = 1;
//Bit 12 DISSDO : Disable SDOx pin bit
SPI2CONbits.DISSDO = 0; //Pin controlled by SPI
//Bit 10-11 MODE <32,16> : 32/16-bit Communication Select bits
SPI2CONbits.MODE16 = 0; //8 - Bit Mode if Both Zeros
SPI2CONbits.MODE32 = 0; //8 - Bit Mode if Both Zeros
//Bit 8 CKE: SPI Clock Edge Select Bit
SPI2CONbits.CKE = 1; //(0=serial o/p data changes on clk trans from idle to active)
//Bit 6 CKP : Polarity Select bit
SPI2CONbits.CKP = 0; //(0=Idle State Low)
//Bit 5 MSTEN : Master Mode Enable bit
SPI2CONbits.MSTEN = 1; //(1=Master Mode)
//Bit 0-1 SRXISEL <1:0> : SPI Receive Buffer Full Interrupt Mode bits
SPI2CONbits.SRXISEL = 00;
Clock settings:
#ifdef MAIN_FREQ_80_MHZ
/****************************************************************************
* Physical SYS BCLK Freq = 8 MHZ
* Required SYS CLK Freq = 80 Mhz
* So, Req. SYS CLK Freq = (8 MHZ / 2 * 20 / 1) = 80 MHZ
****************************************************************************/
//DEVCFG2 - Clock Dividers
//Divides physical i/p SYS CLK frequency (8MHZ) by 2
#pragma config FPLLIDIV = DIV_2 // PLL Input Divider (2x Divider)
//Multiplies the i/p SYS CLK freq (8 MHZ/2 in prev line) by 20
#pragma config FPLLMUL = MUL_20 // PLL Multiplier (20x Multiplier)
//Divides the o/p SYS CLK freq from the prev steps by 1
#pragma config FPLLODIV = DIV_1 // System PLL Output Clock Divider (PLL Divide by 1)
#ifdef PB_FREQ_10_MHZ
#pragma config FPBDIV = DIV_8 //Peripheral Clock Divisor (Pb_Clk is Sys_Clk/8)
#endif
#endif
/*************************************************************************
* SPI 2
* if PB F = 10 MHZ, SPI REG = 0, SCK Freq. = 5 MHz
*************************************************************************/
#ifdef PB_FREQ_10_MHZ
#define SPI_SCK_FREQ 0 //PBF=10MHZ, divider of 2 to produce SCK = 5MHz
#endif
Config Bits:
//DEVCFG
#pragma config FSRSSEL = PRIORITY_7 // SRS Select (SRS Priority 7)
#pragma config FMIIEN = OFF // Ethernet RMII/MII Enable (RMII Enabled)
#pragma config FETHIO = OFF // Ethernet I/O Pin Select (Alternate Ethernet I/O)
#pragma config FCANIO = ON // CAN I/O Pin Select (Default CAN I/O)
#pragma config FUSBIDIO = OFF // USB USID Selection (Controlled by Port Function)
#pragma config FVBUSONIO = OFF // USB VBUS ON Selection (Controlled by Port Function)
//DEVCFG2
#pragma config UPLLIDIV = DIV_1 // USB PLL Input Divider (1x Divider)
#pragma config UPLLEN = OFF // USB PLL Enable (Disabled and Bypassed)
//DEVCFG1
#pragma config FNOSC = FRCPLL // Oscillator Selection Bits
#pragma config FSOSCEN = OFF // Secondary Oscillator Enable (Disabled)
#pragma config IESO = ON // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = EC // Primary Oscillator Configuration (External clock mode) EC = Clean oscillator signal
#pragma config OSCIOFNC = ON // CLKO Output Signal Active on the OSCO Pin (Enabled)
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)
#pragma config WDTPS = PS256 // Watchdog Timer Postscaler (1:256) i.e. WDT Period = 1 ms * 2^Prescaler = 256 mS
#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls)). It can be enabled in SW
//DEVCFG0
#pragma config DEBUG = OFF // Background Debugger Disable (Debugger is enabled)
#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select (ICE EMUC2/EMUD2 pins shared with PGC2/PGD2)
#pragma config PWP = OFF // Program Flash Write Protect (Disable)
#pragma config BWP = OFF // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF // Code Protect (Protection Disabled)
The power supply that I am using can support up to 2 A and so that is not causing the issue.
I've been sitting on this for weeks, I would be eternally grateful for any help or a direction to debug further. Thanks for tolerating my superlong post.
Also I already checked the following on my setup:
1) MISO pin is not shorted to ground.
2) MISO pin is not floating when idle. One thing I noticed is that with CKP = 0 OR 1 and CKE = 0, MOSI line is low when idle and goes high when sending data and MISO is held at 3.3 V when idle and pulled down when clock pulse starts to send data and it is not pulled back up properly. Does this give any clues that I am missing to catch?
3) PD_N pin is pulled high during operation (After turning ON SPI mode and before starting communication, I pulled PD low, waited 20 ms and back high, waited 20 ms as the example has a comment that says that this step is required), CS# is toggled as appropriate i.e., coincides with the clock pulses that the master sends as expected. I also played around with this delay duration and it doesn't make a difference.
4) I just verified - debug setting is OFF in the config bit settings.
5) I tried different combinations of CKE and CKP as well and the issue is still present.
And FT81x is supposed to be woken up by sending 0x00 0x00 0x00 first. I am not sure if this step doesn't wake up FT81x for some reason? I am not sure if I am missing something here...
This is my initialization sequence:
// ----------------------- Cycle PD pin to reset device --------------------
MCU_PDlow(); // PD low to reset device
delay_ms(20); //atleast 20 ms delay
MCU_PDhigh(); // PD high again
delay_ms(20); //atleast 20 ms delay
// ---------------------- Delay to allow start-up --------------------
//EVE_CmdWrite(0x00, 0x00);
EVE_CmdWrite(FT81x_ACTIVE, 0x00); // Sends 00 00 00 to wake FT8xx
delay_ms(500); // 500ms delay (EVE requires at least 300ms here)
// --------------- Check that FT8xx ready and SPI comms OK -----------------
while (EVE_MemRead8(REG_ID) != 0x7C) //Execution is stuck here as MISO pin looks like it is not driven properly
{
}
// Ensure CPUreset register reads 0 and so FT8xx is ready
while (EVE_MemRead8(REG_CPURESET) != 0x00)
{
}
Function definition:
extern void EVE_CmdWrite(Uint8 EVECmd, Uint8 Param) //Sends 0x00 0x00 0x00 to wake up FT81x
{
Uint8 dummyRead = 0;
MCU_CSlow(); // CS low begins the SPI transfer
dummyRead = SPI_Read_Write( (char) (EVECmd) ); // Send command
dummyRead = SPI_Read_Write( (char) (Param) ); // followed by parameter
dummyRead = SPI_Read_Write( 0x00 ); // and a dummy 00 byte
MCU_CShigh(); // CS high terminates the SPI transfer
}//End EVE_CmdWrite()
Thanks!
Madhu