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.

DM385 SPI transmit problem

Other Parts Discussed in Thread: DM385, SYSCONFIG, CCSTUDIO

Hi,

I am currently working on customizing TI's IPNC software package on DM385 processor and its system consists with Linux and BIOS RTOS.

As I changed hardware module, I had to implement SPI firmware code in BIOS side and I have been stuck here for many weeks so far.

I do not understand why following issue is not working and I may so grateful if you could comment any advices for me.

issus. MCSPI_CH0STAT[TXS] is always full.

although I wrote a value in MCSPI_TX0 register, MCSPI_CH0STAT[TXS] is always full and never becomes empty. I think this is a sign of my value is not input in the register.

My initializing step is

*(volatile UInt32*)(0x48181590) = 0x2; // SPI CLK Enable

*(volatile UInt32*)(SPI0_BASE_ADDR + 0x110) |= (0x1<<1); // MCSPI_SYSCONFIG SOFTRESET

*(volatile UInt32*)(SPI0_BASE_ADDR + 0x10) |= (0x1<<2); // MCSPI_HL_SYSCONFIG IDLEMODE 1h
*(volatile UInt32*)(SPI0_BASE_ADDR + 0x10) &= ~(0x1<<3); //
*(volatile UInt32*)(SPI0_BASE_ADDR + 0x110) |= (0x1<<3); // MCSPI_SYSCONFIG SIDLEMODE 1h
*(volatile UInt32*)(SPI0_BASE_ADDR + 0x110) &= ~(0x1<<4); //
*(volatile UInt32*)(SPI0_BASE_ADDR + 0x110) |= (0x3<<8); // MCSPI_SYSCONFIG CLOCKACTIVITY 3h

*(volatile UInt32*)(SPI0_BASE_ADDR + 0x12C) |= (0x1<<24); // SBPOL 1h
*(volatile UInt32*)(SPI0_BASE_ADDR + 0x12C) |= (0x1<<13); // TRM 2h
*(volatile UInt32*)(SPI0_BASE_ADDR + 0x12C) &= ~(0x1<<12);
*(volatile UInt32*)(SPI0_BASE_ADDR + 0x12C) |= (0x1<<7) | (0x1<<8) | (0x1<<9); // WL 7h
*(volatile UInt32*)(SPI0_BASE_ADDR + 0x128) = 0x1; // McSPI_MODULCTRL
*(volatile UInt32*)(SPI0_BASE_ADDR + 0x12C) |= (0x1<<6); // EPOL 1h
*(volatile UInt32*)(SPI0_BASE_ADDR + 0x12C) |= (0x1<<1); // POL 1h
*(volatile UInt32*)(SPI0_BASE_ADDR + 0x12C) |= (0x1); // PHA 1h

*(volatile UInt32*)(SPI0_BASE_ADDR + 0x12C) |= (0x1<<24) // SBPOL 1h
| (0x1<<25) | (0x1<<26) // TCS 3h
| (0x1<<29); //CLKG 1h

*(volatile UInt32*)(SPI0_BASE_ADDR + 0x118) = (0x0); // MCSPI_IRQSTATUS 0h

and after the initialization I called spi write function, which simply is

*(volatile UInt32*)(SPI0_BASE_ADDR + 0x134) = 0x1; // MCSPI_CH0CTRL Channel 0 enable
*(volatile UInt32*)(SPI0_BASE_ADDR + 0x138) = IMX172_WRITE_CMD;
while((*(volatile UInt32*)(SPI0_BASE_ADDR + 0x130))==0) {;}   // Wait until empty MCSPI_CH0STAT
*(volatile UInt32*)(SPI0_BASE_ADDR + 0x134) = 0x0; // MCSPI_CH0CTRL Channel 0 disable

With scope, I am not able to detect any signal has been sent through the SPI data line and MCSPI_CH0STAT[TXS] is never changed.

Below 2 tables are parts of datasheet that I was referred to and if you need further information, please let me know.

----------------------------------------Table 21-8. SPI Transmit Mode Initialization-------------------------------------------
Step                                                                                    Register/Bit Field/Programming Model                Value
Set transmit mode.                                                           MCSPI_CHxCONF[13:12] TRM                             0x2
Set the word length.                                                         MCSPI_CHxCONF[11:7] WL                                  0x8
Clock initialization and channel enabling                    MCSPI_MODULCTRL[2] MS                                 0x0
                                                                                              MCSPI_CHxCTRL[0] EN                                        0x1
Channels activated low during active state                  MCSPI_CHxCONF[6] EPOL                                  0x1
Clock held high during active state                                MCSPI_CHxCONF[1] POL                                     0x0
Data latched on odd-numbered edges of the SPI       MCSPI_CHxCONF[0] PHA                                     0x0
clock
Reset the status bits.                                                         MCSPI_IRQSTATUS                                               0x0

----------------------------------------Table 21-12. Transmit-Only Procedure – Polling Method------------------------------
Step                                                                                    Register/Bit Field/Programming Model                 Value
Configure the channel according to the mode.          See Table 21-8
Start the channel.                                                             MCSPI_CHxCTRL[0] EN                                         0x1
Wait until end of transfer?                                               MCSPI_CHxSTAT[2:1]                                            = 0x2
Stop the channel.                                                             MCSPI_CHxCTRL[0] EN                                         0x0

-------------------------------------------------------------------------------------------------------------------------------------------------

Very grateful for your time to read this issue.

Best regards,

HanGil Kang

  • Hangil,

    HanGil Kang said:

    I am currently working on customizing TI's IPNC software package on DM385 processor and its system consists with Linux and BIOS RTOS.

    As I changed hardware module, I had to implement SPI firmware code in BIOS side and I have been stuck here for many weeks so far.

    From what I understand, you are programming the McSPI module from the BIOS (C674x DSP) side, not from the Linux (Cortex-A8 ARM) side, is that correct? Can you also try this McSPI programming from the Linux side, do you have the same issue?

    Note also that C674x DSP has limited access to the McSPI peripheral module (see datasheet for details). McSPI0 base address is 0x48030000 for Cortex-A8 ARM and other L3 masters, and 0x08030000 for C674x DSP.

    BR
    Pavel

  • Thank you so much Pavel for the reply but I think my explanation was not enough to describe the situation I am facing.

    In fact, BIOS side that I am writing source code is VPSS part and from my understanding it is a part of cortex-M3 sides(even source code name is main_m3vpss.c). Inside codes, there is a function named "BIOS_start()" and that is why I think it is run on BIOS RTOS system.

    In the source code, there is GPIO SPI control part and its base address is 0x4804C000. Moreover, as DSP is not included in DM385 processor, all L3 and L4 memory maps seem to have only one address type.

    I also tried the test source code of your link
    http://www.mistralsolutions.com/product-engineering-services/support-downloads/ -> Diagnostic Software -> CCS_Test_code -> Base_Board -> SPI_Flash
    and wrote new source code as is in spiflash.c. However still I figured out the source code stops while waiting transmit buffer empty(while ( (MCSPI_CH0STAT & 0x02) == 0 );), which I do not really understand why...

    Here I attach new revised source code written by SPI_Flash source code and I wish you could tell me another aspect for solving the issue.
    I really appreciate for your help..

    Warm and best regards.

    Hangil

    void Iss_Imx172HWSPIInit()
    {
    Vps_printf("HW SPI Init!\n");
    *(volatile UInt32*)(0x48181590) = 0x2; // SPI CLK Enable
    Vps_printf("HW SPI CLK Enabled!\n");
    /* Reset SPI */
    *(volatile UInt32*)(SPI0_BASE_ADDR + 0x110) |= 0x02;
    /* Wait for reset to complete */
    while(((*(volatile UInt32*)(SPI0_BASE_ADDR + 0x114)) & 0x01) == 0x00);
    Vps_printf("HW SPI softreset done!\n");

    Vps_printf("NEW Init!\n");

    *(volatile UInt32*)(SPI0_BASE_ADDR + 0x110) |= (0x3<<8); // MCSPI_SYSCONFIG CLOCKACTIVITY 3h


    /* Configure MCSPI Module */
    *(volatile UInt32*)(SPI0_BASE_ADDR + 0x128) = 0
    | ( 0 << 8 ) // Data managed by MCSPI_TX(i) and MCSPI_RX(i) registers
    | ( 0 << 7 ) // Multiple word access disabled
    | ( 0 << 4 ) // No delay for first spi transfer ????????????????????????????????
    | ( 0 << 3 ) // Functional mode
    | ( 0 << 2 ) // Master
    | ( 0 << 1 ) // SPIEN is used as a chip select
    | ( 1 << 0 );// Only one channel will be used in master mode

    /* Configure MCSPI Channel 0 */
    *(volatile UInt32*)(SPI0_BASE_ADDR + 0x12C) = 0
    | ( 0 << 29 ) // Clock divider granularity of power of two
    | ( 1 << 28 ) // The buffer is not used to receive data
    | ( 1 << 27 ) // The buffer is not used to transmit data
    | ( 1 << 25 ) // 1.5 cycles between CS toggling and first or last edge of SPI clock
    | ( 1 << 24 ) // Start bit polarity is held to 1 during SPI transfer
    | ( 0 << 23 ) // Disable start bit
    | ( 0 << 20 ) // SPIEN active between SPI words
    | ( 0 << 19 ) // Turbo is deactivated
    | ( 1 << 18 ) // Data Line1 selected for reception
    | ( 0 << 17 ) // No transmission on Data Line1
    | ( 1 << 16 ) // Data Line0 selected for transmission
    | ( 0 << 15 ) // DMA Read Request disabled
    | ( 0 << 14 ) // DMA Write Request disabled
    | ( 0x2 << 12 ) // Transmit and Receive mode
    | ( 7 << 7 ) // SPI word length = 8
    | ( 1 << 6 ) // SPIEN is held low during the active state
    | ( 0 << 2 ) // CLKD Divide by 1
    | ( 1 << 1 ) // SPICLK is held low during the active state
    | ( 0 << 0 );// Data are latched on even numbered edges of SPICLK

    /* Enable MCSPI channel */
    *(volatile UInt32*)(SPI0_BASE_ADDR + 0x128) = 0x01; // Enable Channel
    return;
    }

    void Iss_Imx172HWSPIWrite(UInt16 *regAddr, UInt8 *regValue)
    {
    UInt8 upperAddr, lowerAddr;
    Vps_printf("===================HW SPI WRITE START====================\n");
    lowerAddr = (UInt8)(*regAddr&0xff);
    upperAddr = (UInt8)(*regAddr>>8);
    Vps_printf("HW upper = %x, lower = %x, regValue = %x\n", upperAddr, lowerAddr, *regValue);

    Vps_printf("NEW SPI\n");
    /* Enable Channel */
    *(volatile UInt32*)(SPI0_BASE_ADDR + 0x134) = 0x01;

    /* Wait for transmit empty */
    while (( (*(volatile UInt32*)(SPI0_BASE_ADDR + 0x130)) & 0x02) == 0 );
    *(volatile UInt32*)(SPI0_BASE_ADDR + 0x138) = IMX172_WRITE_CMD; // Write to RX buffer 0

    /* Wait for transmit empty */
    while (( (*(volatile UInt32*)(SPI0_BASE_ADDR + 0x130)) & 0x02) == 0 );
    *(volatile UInt32*)(SPI0_BASE_ADDR + 0x138) = lowerAddr; // Write to RX buffer 0

    /* Wait for transmit empty */
    while (( (*(volatile UInt32*)(SPI0_BASE_ADDR + 0x130)) & 0x02) == 0 );
    *(volatile UInt32*)(SPI0_BASE_ADDR + 0x138) = upperAddr; // Write to RX buffer 0

    /* Wait for transmit empty */
    while (( (*(volatile UInt32*)(SPI0_BASE_ADDR + 0x130)) & 0x02) == 0 );
    *(volatile UInt32*)(SPI0_BASE_ADDR + 0x138) = regValue; // Write to RX buffer 0

    /* Disable Channel */
    *(volatile UInt32*)(SPI0_BASE_ADDR + 0x134) = 0x00;
    Vps_printf("===================HW SPI WRITE END====================\n");
    return;
    }
  • HanGil Kang said:
    In fact, BIOS side that I am writing source code is VPSS part and from my understanding it is a part of cortex-M3 sides(even source code name is main_m3vpss.c). Inside codes, there is a function named "BIOS_start()" and that is why I think it is run on BIOS RTOS system.

    Can you try your McSPI code out of this VPSS-M3 side? I mean to try at u-boot, linux kernel, user space (spidev) or CCStudio project, all these in Cortex-A8 control. Make sure also your McSPI pins are set correctly. Are you trying to use polling, interrupt or DMA mode?

    HanGil Kang said:
    I also tried the test source code of your link
    http://www.mistralsolutions.com/product-engineering-services/support-downloads/ -> Diagnostic Software -> CCS_Test_code -> Base_Board -> SPI_Flash
    and wrote new source code as is in spiflash.c. However still I figured out the source code stops while waiting transmit buffer empty(while ( (MCSPI_CH0STAT & 0x02) == 0 );), which I do not really understand why...

    Can you also compare with the u-boot McSPI driver source code base:

    u-boot/drivers/spi/omap3_spi.c - see function int spi_xfer()

    u-boot/drivers/mtd/spi/spi_flash.c - this is the file that uses this u-boot McSPI driver

    BR
    Pavel

  • Thanks a lot Pavel!

    I do appreciate for your help indeed.

    After I changed source code as your reference source, SPI signals are finally detected.

    Thanks again and you really have a great day!

    Bestestest regards

    Hangil
  • Hello,

    Does dm8148 spi drivers should be used with u-boot/drivers/spi/omap3_spi.c routines ?

    Regards,
    Ran
  • Ran,

    Yes, this SPI driver is also valid for DM814x uboot.

    BR
    Pavel