Because of the holidays, TI E2E™ design support forum responses will be delayed from Dec. 25 through Jan. 2. Thank you for your patience.

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.

AM3358: SPI clock issues

Hi.

I am posting this question on behalf of the Attitude, Determination, and Control System Team (ADCS) for the MAXWELL CubeSat Project at the University of Colorado Boulder.

I am using the Beaglebone Black hardware (AM335x processor) with a custom bare metal operating system our team has designed to communicate between various subsystems on a 6U CubeSat that will be competing in the University Nanosat Program, Nanosat 9 competition.

I am currently working on setting up a bare metal SPI interface through the SPI1 module. I have been using the TI Starterware code and McSPI driver as a basis. While trying to test the SPI transmission using a logic analyzer (with and without connecting the slave device), I found that the clock does not seem to be routed to the module or to function as expected (clock signal was either missing or at times just jumped high for once and back to low again when evaluated for 20 sec period), and hence I am not getting any data transmission on the MOSI or MISO lines visible on the logic analyzer. I have attached code snippets and logic analyzer output.

In the code we have set the module mode of the CM_PER_SPI1_CLKCTRL Register to Enable (0x2) as well as the CM_PER_L4LS_CLKCTRL Register to Enable (0x2). We have set the SPI polarity as 0 and Phase as 1 in accordance with our slave device datasheet. We also tried setting the CLKACTIVITY_SPI_GCLK and CLKACTIVITY_L4LS_GCLK in CM_PER_L4LS_CLKSTCTRL register as these are mentioned to be the main clock domains of SPI in the AM355x processor datasheet and several other E2E posts. I am still unable to transmit anything over the SPI bus.

It would be much appreciated if someone on E2E could guide us in the right direction with regard to any important register settings required to use the SPI1 module. Eagerly awaiting your response.

  • Hi Tralicin,

    I will have a look on your question, but first I need some more details from you.

    Do you use BeagleBoneBlack or custom board that is based on BeagleBoneBlack?

    Do you use AM335x TI SDK or StarterWare?

    When you say that SPI clock is not functioning properly, do you mean the internal SPI clock that is coming from the device PRCM or external SPI clock on the pin?

    Regards,
    Pavel
  • TARALICIN DEKA said:
    We also tried setting the CLKACTIVITY_SPI_GCLK and CLKACTIVITY_L4LS_GCLK in CM_PER_L4LS_CLKSTCTRL register

    Those are readonly status bits used for power management debugging.

    TARALICIN DEKA said:
    It will be great if you can guide us in the right direction and point out to us the important settings that are mandatory in order to get SPI working with the Beagle Bone Black.

    Your problem description is too vague to even allow a guess of what might be the problem, but some general thoughts I can offer:

    1. Check pinmux configuratoin. Be sure that "received enabled" is set for the clock pin (and I think it might be required for the chip select too, but I'm not 100% sure of that).

    2. Check configuration of the spi channel. Make sure it is enabled. Keep things like the FIFO and DMA initially disabled to simplify debugging.

    3. Try to perform a single transfer (i.e. write a single word) and then check the MCSPI_CHxSTAT register. This information will help identifying at which point the transfer gets stuck.

  • Pavel,

    Thank you for your response. I am sorry that my question didnot contain information on your queries. I am new to this field of "deep hardware" tand I am learning in the process. So could not really frame everything clearly. But I am glad you got back to my problem.

    Here are my answers to your questions:

    Do you use BeagleBoneBlack or custom board that is based on BeagleBoneBlack?

    I am using Element 14 Beagle Bone Black Industrial. 

    Do you use AM335x TI SDK or StarterWare?

    I am using Starterware (not using an OS. I guess this is what defines the Starterware!).

    When you say that SPI clock is not functioning properly, do you mean the internal SPI clock that is coming from the device PRCM or external SPI clock on the pin?

    I used the logic analyzer to check the SPI clock on the pin 31 of Port 9 and it always stayed low.

    I have attached the logic analyzer output file with this response so that you can zoom in and look at the signals in case required. Or I have also attached a snipped image of the logic analyzer output to show you the output over 20 seconds. These readings are taken by connecting the logic analyzer to PORT 9 PIN 29 for MOSI, PIN 30 for MISO, PIN 31 for CLK, PORT 8 PIN 22  for Chip Select (SPI Enable as denoted in the Analyzer output).

    Also, here is the snippet of the code that I am using to set up the clocks. Please note that MAXWELL uses I2C for other communication purposes, so clocks related to I2C have also been initialized in the code:

    /* -- enable_interface_clocks --------------------------------------------
     * 
     * This function enables all interface clocks. These are the L3 and L4 
     * interface clocks.
     * -----------------------------------------------------------------------
     */

    static int32_t enable_interface_clocks(void)
    {
        int32_t rv = 1;

        int32_t timeout = TIMEOUT_LEN;
        writel(PRCM_MOD_EN, CM_PER_L3_CLKCTRL);
        while ((readl(CM_PER_L3_CLKCTRL) != PRCM_MOD_EN) && --timeout);
        if(timeout==0) rv = 0;
        
        timeout = TIMEOUT_LEN;
        writel(PRCM_MOD_EN, CM_PER_L4LS_CLKCTRL);
        while ((readl(CM_PER_L4LS_CLKCTRL) != PRCM_MOD_EN) && --timeout);
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        writel(PRCM_MOD_EN, CM_PER_L4FW_CLKCTRL);
        while ((readl(CM_PER_L4FW_CLKCTRL) != PRCM_MOD_EN) && --timeout);
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        writel(PRCM_MOD_EN, CM_WKUP_L4WKUP_CLKCTRL);
        while ((readl(CM_WKUP_L4WKUP_CLKCTRL) != PRCM_MOD_EN) && --timeout);
        if(timeout==0) rv = 0;

        writel(PRCM_MOD_EN, CM_PER_L3_INSTR_CLKCTRL);
        timeout = TIMEOUT_LEN;
        while ((readl(CM_PER_L3_INSTR_CLKCTRL) != PRCM_MOD_EN) && --timeout);
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        writel(PRCM_MOD_EN, CM_PER_L4HS_CLKCTRL);
        while ((readl(CM_PER_L4HS_CLKCTRL) != PRCM_MOD_EN) && --timeout);
        if(timeout==0) rv = 0;

        return rv;
    }

    /* -- power_domain_wkup_transition ---------------------------------------
     * 
     * This function forces the power domain wakup transition.  This ensures
     * that the L3 and L4 interface clocks are active before using the
     * peripherals.
     * -----------------------------------------------------------------------
     */
    static void power_domain_wkup_transition(void)
    {
        writel(PRCM_FORCE_WAKEUP, CM_PER_L3_CLKSTCTRL);
        writel(PRCM_FORCE_WAKEUP, CM_PER_L4LS_CLKSTCTRL);
        writel(PRCM_FORCE_WAKEUP, CM_WKUP_CLKSTCTRL);
        writel(PRCM_FORCE_WAKEUP, CM_PER_L4FW_CLKCTRL);
        writel(PRCM_FORCE_WAKEUP, CM_PER_L3S_CLKSTCTRL);
        writel(PRCM_FORCE_WAKEUP, CM_PER_OCPWP_L3_CLKSTCTRL);
    }



    /* -- enable_per_clocks --------------------------------------------------
     * 
     * This function enables the clocks of the peripherals needed for booting.
     *
     * -----------------------------------------------------------------------
     */
    static int32_t enable_per_clocks(void)
    {
        int32_t rv=1;
        int32_t timeout = TIMEOUT_LEN;
        /* Enable Control Module (Redudant, should have been done in ROM boot */
        writel(PRCM_MOD_EN, CM_WKUP_CONTROL_CLKCTRL);
        while ((readl(CM_WKUP_CONTROL_CLKCTRL) != PRCM_MOD_EN) && --timeout);
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        /* Enable DEBUGSS Module */
        writel(PRCM_MOD_EN, CM_WKUP_DEBUGSS_CLKCTRL);
        while ((readl(CM_WKUP_DEBUGSS_CLKCTRL) != PRCM_MOD_EN) && --timeout);
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        /* enable the module clock for timer 2 */
        writel(PRCM_MOD_EN, CM_PER_TIMER2_CLKCTRL);
        while (((readl(CM_PER_TIMER2_CLKCTRL) & PRCM_MOD_EN) != PRCM_MOD_EN) && --timeout);
        if(timeout==0) rv = 0;

        /* select the Master OSC 24 MHz as timer 2 clock source */
         writel(0x1, CLKSEL_TIMER2_CLK); /* reset value */

        timeout = TIMEOUT_LEN;
        /* enable the module clock for timer 3 */
        writel(PRCM_MOD_EN, CM_PER_TIMER3_CLKCTRL);
        while (((readl(CM_PER_TIMER3_CLKCTRL) & PRCM_MOD_EN) != PRCM_MOD_EN) && --timeout);
        if(timeout==0) rv = 0;

        /* select the Master OSC 24 MHz as timer 3 clock source */
         writel(0x1, CLKSEL_TIMER3_CLK); /* reset value */

        timeout = TIMEOUT_LEN;
        /* Enable Timers 4,5 and 7 used for PWM signals */
        writel(PRCM_MOD_EN, CM_PER_TIMER4_CLKCTRL);
        while((readl(CM_PER_TIMER4_CLKCTRL) != PRCM_MOD_EN) && --timeout);
        if(timeout==0) rv = 0;
         writel(0x1, CLKSEL_TIMER4_CLK); 

        timeout = TIMEOUT_LEN;
        writel(PRCM_MOD_EN, CM_PER_TIMER5_CLKCTRL);
        while((readl(CM_PER_TIMER5_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;
         writel(0x1, CLKSEL_TIMER5_CLK);

        timeout = TIMEOUT_LEN;
        writel(PRCM_MOD_EN, CM_PER_TIMER7_CLKCTRL);
        while((readl(CM_PER_TIMER7_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;
         writel(0x1, CLKSEL_TIMER7_CLK);

         /* Enable WDT timer */
        timeout = TIMEOUT_LEN;
        writel(PRCM_MOD_EN, CM_WKUP_WDT1_CLKCTRL);
        while((readl(CM_WKUP_WDT1_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;
         writel(0x1, CLKSEL_WDT1_CLK);

        timeout = TIMEOUT_LEN;
        /* UART0 */
        writel(PRCM_MOD_EN, CM_WKUP_UART0_CLKCTRL);
        while ((readl(CM_WKUP_UART0_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        /* UART1 */
        writel(PRCM_MOD_EN, CM_PER_UART1_CLKCTRL);
        while ((readl(CM_PER_UART1_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        /* UART2 */
        writel(PRCM_MOD_EN, CM_PER_UART2_CLKCTRL);
        while ((readl(CM_PER_UART2_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        /* GPMC */
        writel(PRCM_MOD_EN, CM_PER_GPMC_CLKCTRL);
        while ((readl(CM_PER_GPMC_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        /* ELM */
        writel(PRCM_MOD_EN, CM_PER_ELM_CLKCTRL);
        while ((readl(CM_PER_ELM_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        /* MMC0 */
        writel(PRCM_MOD_EN, CM_PER_MMC0_CLKCTRL);
        while ((readl(CM_PER_MMC0_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;

    //    timeout = TIMEOUT_LEN;
    //    /* MMC1 */
    //    writel(PRCM_MOD_EN, CM_PER_MMC1_CLKCTRL);
    //    while ((readl(CM_PER_MMC1_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
    //    if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        /* i2c0 */
        writel(PRCM_MOD_EN, CM_WKUP_I2C0_CLKCTRL);
        while ((readl(CM_WKUP_I2C0_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        /* i2c1 */
        writel(PRCM_MOD_EN, CM_PER_I2C1_CLKCTRL);
        while ((readl(CM_PER_I2C1_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        /* i2c2 */
        writel(PRCM_MOD_EN, CM_PER_I2C2_CLKCTRL);
        while ((readl(CM_PER_I2C2_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;

        /* gpio0 module */
        writel(PRCM_MOD_EN, CM_WKUP_GPIO0_CLKCTRL);
        timeout = TIMEOUT_LEN;
        while ((readl(CM_WKUP_GPIO0_CLKCTRL) != PRCM_MOD_EN) && --timeout);
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        /* gpio1 module */
        writel(PRCM_MOD_EN, CM_PER_GPIO1_CLKCTRL);
        while ((readl(CM_PER_GPIO1_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        /* gpio2 module */
        writel(PRCM_MOD_EN, CM_PER_GPIO2_CLKCTRL);
        while ((readl(CM_PER_GPIO2_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;

        timeout = TIMEOUT_LEN;
        /* gpio3 module */
        writel(PRCM_MOD_EN, CM_PER_GPIO3_CLKCTRL);
        while ((readl(CM_PER_GPIO3_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;

    //    timeout = TIMEOUT_LEN;
    //    /* Ethernet NOT USING*/
    //    writel(PRCM_MOD_EN, CM_PER_CPGMAC0_CLKCTRL);
    //    while ((readl(CM_PER_CPGMAC0_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
    //    if(timeout==0) rv = 0;
    //

    /*    timeout = TIMEOUT_LEN;
         spi0  NOT USING
        writel(PRCM_MOD_EN, CM_PER_SPI0_CLKCTRL);
        while ((readl(CM_PER_SPI0_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;*/

        timeout = TIMEOUT_LEN;
        /* spi1  USING */
        writel(PRCM_MOD_EN, CM_PER_SPI1_CLKCTRL);
        while ((readl(CM_PER_SPI1_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
        if(timeout==0) rv = 0;


    //   timeout = TIMEOUT_LEN;
    //    /* RTC MIGHT USE */
    //    writel(PRCM_MOD_EN, CM_RTC_RTC_CLKCTRL);
    //    while ((readl(CM_RTC_RTC_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
    //    if(timeout==0) rv = 0;
    //
    //    timeout = TIMEOUT_LEN;
    //    /* MUSB MIGHT USE */
    //    writel(PRCM_MOD_EN, CM_PER_USB0_CLKCTRL);
    //    while ((readl(CM_PER_USB0_CLKCTRL) != PRCM_MOD_EN) && --timeout) ;
    //    if(timeout==0) rv = 0;

        return rv;
    }

    Hope to hear back from you soon. Regards!

  • Matthijs van Duin,

    Thank you for your response. I accept your suggestions and will look into them.

    Pardon me for not providing you with enough information to judge the issues that I am facing. I am new to this field of firmware and baremetal coding and couldnot decide on all the information that you will be requiring to answer my query. But I am really thankful to you for getting back with suggestions despite all odds.

    I have edited the post if that makes anything clearer. Otherwise I am open to answer any question that you have on my query, so kindly feel free to ask me back for any specific information that you may need. I will try my best to gather the information and get back to you.

    You may also want to view my response to Pavel's query above where I try to clarify most of the things, in case that helps you to judge what might be the issue.

    Eagerly waiting to hear back your inputs.

    Regards!
  • Taralicin,

    TARALICIN DEKA said:
    I am using Starterware (not using an OS. I guess this is what defines the Starterware!).

    Note that StarterWare is out dated, and replace by PSDK-RTOS:

    For McSPI code example, you might refer to the AM335x TI PSDK u-boot code base, as u-boot is more close to bear-metal, u-boot is not OS, see files:

    u-boot-2017.01/arch/arm/dts/am33xx.dtsi

    u-boot-2017.01/drivers/spi/omap3_spi.c

    This u-boot code base you can take from the latest AM335x TI PSDK v4.01

    Make sure also Per PLL is properly configured, it should be active and locked.

    TARALICIN DEKA said:
    I used the logic analyzer to check the SPI clock on the pin 31 of Port 9 and it always stayed low.

    I am not familiar with element14 BeagleBone Black schematics. Can you share a link to it? Or can you point to which AM335x pin exactly this correspond? Is it to pin spi0_sclk (A18 in ZCE package, A17 in ZCZ package) or pin spi1_sclk (E18/J19 in ZCE package, A13/C18/H16 in ZCZ package) or else?

    Make sure the pin you are using is properly pinmuxed.

    For more info regarding AM335x McSPI pins, refer to the AM335x datasheet, section 4.3 Signal Descriptions

    Regards,
    Pavel

  • TARALICIN DEKA said:
    In the code we have set the module mode of the CM_PER_SPI1_CLKCTRL Register to Enable (0x2) as well as the CM_PER_L4LS_CLKCTRL Register to Enable (0x2). We have set the SPI polarity as 0 and Phase as 1 in accordance with our slave device datasheet. We also tried setting the CLKACTIVITY_SPI_GCLK and CLKACTIVITY_L4LS_GCLK in CM_PER_L4LS_CLKSTCTRL register as these are mentioned to be the main clock domains of SPI in the AM355x processor datasheet and several other E2E posts. I am still unable to transmit anything over the SPI bus.

    Try to read/write any McSPI1 module register. If you are able to read/write McSPI1 registers successful, then PRCM and Per PLL settings should be fine and you need to focus on McSPI1 module settings and pinmux settings.

  • Pavel Botev said:
    I am not familiar with element14 BeagleBone Black schematics. Can you share a link to it? Or can you point to which AM335x pin exactly this correspond? Is it to pin spi0_sclk (A18 in ZCE package, A17 in ZCZ package) or pin spi1_sclk (E18/J19 in ZCE package, A13/C18/H16 in ZCZ package) or else?

    P9.31 is spi1_clk.

    You can find the BBB schematic here.

    I also have a detailed pins spreadsheet here. The "P9" and "P8" tabs give an overview of the expansion headers. Balls aren't listed there, but you can find those on the "BBB" tab (you can sort on column D via menu Data → Filter views → By connection).

  • Thanks Matthijs. So this should be pin A13 of ZCZ package.

    Taralicin,

    You can also check if you have the correct pinmux value in the conf_mcasp0_aclkx register (phy addr 0x44E10990).

    Regards,
    Pavel
  • Pavel,

    Thank you for the suggestion.

    1) Currently, the "conf_mcasp0_aclkx" register at phy addr 0x44E10990 is set up as follows:

    conf_mcasp0_aclkx_mmode = 3
    conf_mcasp0_aclkx_puden = 1
    conf_mcasp0_aclkx_putypesel = 1
    conf_mcasp0_aclkx_rxactive = 1
    conf_mcasp0_aclkx_slewctrl = 1

    It will be great if you can confirm if this is the right configuration.

    I have few more question related to the issue:

    1) Do we need to enable the pullup bit of that register for the clock to function properly?

    2) Also, we came across the "MCSPI_SYST" Register at address 0x481A0124. It has slots to set the direction of the pins. We tried to set the SPIENDIR = 0, SPIDATDIR1 = 1 (MISO), SPIDATDIR0 = 0 (MOSI) in this register but this did not change the clock behavior and we see just a single pulse on the clock line.
    Is it required to configure this register? Because we have already set the "MS" bit in MCSPI_MODULCTRL Register to 0 (Master mode).

    3) Also, we are trying to configure 4 GPIO pins to function as the Chip Select. We have configured "PIN34" in MCSPI_MODULCTRL Register to 1 for this purpose. Is this configuration sufficient to use the GPIO pins as CS?

    Hope to hear back from you at the earliest.
  • I see the status near my post saying "TI thinks resolved". Whereas my issue is not yet solved.

    I did reply to Pavel's last suggestion on the issue but am not sure if it was reviewed as it was maked with the above mentioned status. So I am resposting it here. Hope to hear your concern on this.

    Pavel,

    Thank you for the suggestion.

    1) Currently, the "conf_mcasp0_aclkx" register at phy addr 0x44E10990 is set up as follows:

    conf_mcasp0_aclkx_mmode = 3
    conf_mcasp0_aclkx_puden = 1
    conf_mcasp0_aclkx_putypesel = 1
    conf_mcasp0_aclkx_rxactive = 1
    conf_mcasp0_aclkx_slewctrl = 1

    It will be great if you can confirm if this is the right configuration.

    I have few more question related to the issue:

    1) Do we need to enable the pullup bit of that register for the clock to function properly?

    2) Also, we came across the "MCSPI_SYST" Register at address 0x481A0124. It has slots to set the direction of the pins. We tried to set the SPIENDIR = 0, SPIDATDIR1 = 1 (MISO), SPIDATDIR0 = 0 (MOSI) in this register but this did not change the clock behavior and we see just a single pulse on the clock line.
    Is it required to configure this register? Because we have already set the "MS" bit in MCSPI_MODULCTRL Register to 0 (Master mode).

    3) Also, we are trying to configure 4 GPIO pins to function as the Chip Select. We have configured "PIN34" in MCSPI_MODULCTRL Register to 1 for this purpose. Is this configuration sufficient to use the GPIO pins as CS?

    Hope to hear back from you at the earliest.
  • TARALICIN DEKA said:
    conf_mcasp0_aclkx_mmode = 3
    conf_mcasp0_aclkx_puden = 1
    conf_mcasp0_aclkx_putypesel = 1
    conf_mcasp0_aclkx_rxactive = 1
    conf_mcasp0_aclkx_slewctrl = 1

    It will be great if you can confirm if this is the right configuration.

    This looks okay to me.

    TARALICIN DEKA said:
    1) Do we need to enable the pullup bit of that register for the clock to function properly?

    I would recommend setting putypesel to reflect the default state of the clock signal, i.e. pull-down if using SPI mode 0 or 1, pull-up if using SPI mode 2 or 3. Keeping pull-up/down enabled is not critical however, it's just to ensure the pins will not float if undriven, e.g. before McSPI is configured into master mode. (I'm also not 100% sure whether it continues to be driven in-between transfers.)

    TARALICIN DEKA said:
    2) Also, we came across the "MCSPI_SYST" Register at address 0x481A0124.

    This register is used for test mode only (SYSTEM_TEST bit set in MODULCTRL). It is not relevant in functional operation.

    TARALICIN DEKA said:
    Also, we are trying to configure 4 GPIO pins to function as the Chip Select. We have configured "PIN34" in MCSPI_MODULCTRL Register to 1 for this purpose. Is this configuration sufficient to use the GPIO pins as CS?

    Be sure to also set the SINGLE bit in MODULCTRL

  • Matthijs van Duin,
    Thank you for your feedback.

    We have the SINGLE bit set already.

    While debugging, we realized that accidentally we were clearing the "IS" and "DPE1" bits in MCSPI_CH0CONF register.
    Now, after setting those values back to 1 (default values) which sets D0 as output and D1 as input, we found that the RX0 register is always showing a value of "FF" when we are trying to read from a slave register (i.e. after transmitting any value via TX0 register to the slave). It looks like D1 (MISO) is always floating.

    Do you have any idea about why this might be happening?
  • Pavel,
    While debugging I observed the following sequence of steps happening with the MCSPI_CH0STAT Register :

    1) after enabling the SPI1 channel 0 and before writing the very first byte into the TX0 register for transmission, the MCSPI_CH0STAT Register reads 0x02, that is TXS bit is 1 (meaning TX0 register is empty).

    2) Immediately after the value to be transmitted is written to the TX0 register (written value is 8 bit), the value of the register stays the same 0x02.

    3) After the EOT bit is set that indicates end of transmission, the MCSPI_CH0STAT Register value changes to 0x07 (EOT is SET, TX0 is empty, RX0 is full).

    4) Then, after enabling the SPI1 channel 0 and before I write the second value to the TX0 register for transmission, the MCSPI_CH0STAT Register reads 0x06 (NOTE: not 0X02 like before the first transfer in step 1), that is EOT bit is set,TXS bit is set, RX0 reg is empty.

    5) Immediately after the value to be transmitted is written to the TX0 register, the value of the register reads 0x02.

    6) After the EOT bit is set that indicates end of transmission, the MCSPI_CH0STAT Register value changes to 0x07 (EOT is SET, TX0 is empty, RX0 is full).

    ......and steps 4 to 6 repeats for all other transfers.

    This looks like the TXS bit is never going 0 that means the TX0 register is never full.
    I tried reading the value of TX0 register after EOT is set and it read the value that I wanted to send, which looks right to me. But I am not sure why the TXS bit is never going to 0.

    I am worried about how this transmission and reception is happening because, the RX0 register is always receiving a value of 0xFF (and MISO looks like to be floating).
    After first byte is transferred, RX0 reads 0x000000FF. After 2nd byte is transferred RX0 reads 0x0000FFFF.... And finally after 4th byte is transferred RX0 always reads 0xFFFFFFFF.
    So, I am not sure if my transmission and reception is working properly.

    Eagerly waiting to hear your feedback on this.
  • TARALICIN DEKA said:
    This looks like the TXS bit is never going 0 that means the TX0 register is never full.

    Since McSPI is idle when you write the first word, it is immediately transferred from the TX register to the shift register, hence you never observe TXS being low. If you'd write a second word while the transfer is still in progress, you'll see TXS going low until transmission of the second word can begin (which is when the first transfer has completed and, if turbo mode is not enabled, the RX register is empty).

    Everything you're describing sounds like normal behaviour to me.

    TARALICIN DEKA said:
    MISO looks like to be floating

    Well, if MISO is not being driven by the slave then obviously you'll read either 0xff (if pull-up is enabled) or 0x00 (if pull-down is enabled). The slave not responding is obviously not a problem of McSPI itself. You'll need to cross-check whether what you're sending matches what the slave is expecting (correct spi mode, supported clock speed, appropriate timing constraints surrounding chip select, correct data).

    You can double-check whether you can correctly receive data by connecting MISO to MOSI instead of connecting an actual spi slave, and confirming you receive back any data you transmit.

    TARALICIN DEKA said:
    After first byte is transferred, RX0 reads 0x000000FF. After 2nd byte is transferred RX0 reads 0x0000FFFF.... And finally after 4th byte is transferred RX0 always reads 0xFFFFFFFF.

    Since you've configured an spi word width of 8 bits, the top 24 bits of the register should be considered undefined. Either mask them off, or use a byte-read to the RX0 register instead of a 32-bit read.

    BTW, do avoid reading the RX0 register with the debugger, since that will most likely cause the RXS flag to be cleared.

  • Matthijs van Duin,

    "You can double-check whether you can correctly receive data by connecting MISO to MOSI instead of connecting an actual spi slave, and confirming you receive back any data you transmit."

    The check that you suggested sounds interesting. But for SPI to work, I will need a valid clock and Chip select between the Master and Slave. If I should not connect the slave, and just connect MOSI to MISO of the BBB, where do you suggest connecting the chip select and clock line to?

  • TARALICIN DEKA said:
    The check that you suggested sounds interesting. But for SPI to work, I will need a valid clock and Chip select between the Master and Slave. If I should not connect the slave, and just connect MOSI to MISO of the BBB, where do you suggest connecting the chip select and clock line to?

    For a loopback test like this there is no need to connect chip select and clock to anything at all.

  • Matthijs van Duin,
    I did the loop back test. And I could see that MISO was receiving the data that were being transmitted by MOSI.
    I also printed the values of TX0 and RX0 register and they also agreed to the above observation.

    What does a successful loopback test say about the clock? Does this mean the internal clock of the SPI module is working fine ?

    I am concerned about the clock because when I try to talk to the SCMD (my slave device), I donot see a regular clock. It is always random clock pulses. So I am wondering what the loop back test say about the clock and how I should proceed with further debugging to fix this 'random pulse clock' issue from that.
  • TARALICIN DEKA said:
    What does a successful loopback test say about the clock? Does this mean the internal clock of the SPI module is working fine ?

    A successful loopback test requires a correct clock signal to be driven onto the external pin, since McSPI receives back the clock signal present on the SCK pin and uses it to shift the data register.

    TARALICIN DEKA said:
    I am concerned about the clock because when I try to talk to the SCMD (my slave device), I donot see a regular clock. It is always random clock pulses.

    I'm not sure what you mean by "random clock pulses", but SPI does not have a regular clock. The clock signal is only active during data transfers.

    Do you have a link to a datasheet of the slave device you're trying to interface to?

  • Matthijs van Duin,

    Thank you for your response.

    By "random clock pulses" I mean that I see single clock pulses at random times and the clock pulse does not stay active during the complete transfer (just shows single pulses at random times)

    I have attached the logic analyzer snapshot below for your reference.

    Here is the link to the slave device that I am using. You can find the datasheet in the "documents" section.

    https://www.sparkfun.com/products/13911 

    I observed something strange:
    When I print the receive buffer RX0 values, they kept changing (earlier with D0 as output and D1 as input, RX0 used to read 0xFF). But the MISO line with the logic analyzer always shows the same 0xFF like before.

    I tried doing the loopback test again with this new configuration, and in the loopback test MISO MOSI showed the same values, also buffers TX0 and RX0 read same which I think is correct. But I am not sure why RX0 values keep changing but MISO line with logic analyzer shows 0xFF when I connect the slave.

    Although there is not much of a difference in the clock behavior.

    Do you have any thoughts on that?

    Also below are few settings for D0 , D1 and CLK that are done following the starterware code. I wonder if they are correct or should I interchange the setting for D0 and D1 here. I didnot find any explanation for the AXR0, AFSR and found AFSX in place of FSX in the processor manual. 

    /* SPI1 */
    #define CONF_MCASP0_AHCLKR (CONTROL_MODULE + 0x99C)
    #define CONF_SPI1_CS0 CONF_MCASP0_AHCLKR
    #define CONF_MCASP0_FSX (CONTROL_MODULE + 0x994)
    #define CONF_SPI1_D0 CONF_MCASP0_FSX
    #define CONF_MCASP0_AXR0 (CONTROL_MODULE + 0x998)
    #define CONF_SPI1_D1 CONF_MCASP0_AXR0
    #define CONF_MCASP0_ACLKX (CONTROL_MODULE + 0x990)
    #define CONF_SPI1_SCLK CONF_MCASP0_ACLKX

    It will be great if you can verify the settings and let me know your feedback.

    Again, I really appreciate all your help and suggestions till now. Thanks a lot.

  • What might be going wrong if TX0 and RX0 values are not reflected in the MISO MOSI line of the logic analyzer when connected to the relevent D0 and D1 Pins?

    I have configured bit IS, DPE1 and DPE0 of MCSPI_CH0CONF register as input or output according to pin directions.

    Earlier I could see values in MISO and MOSI that agreed to TX0 and RX0 values but now I am unable to guess what configuration got changed that might be ruining this up!