Shop OBEX P1 Docs P2 Docs Learn Events
P2 simple SPI flash memory driver — Parallax Forums

P2 simple SPI flash memory driver

pic18f2550pic18f2550 Posts: 400
edited 2022-10-31 15:41 in Propeller 2
PRI Spi_Init() | div
  div:= (clkfreq / 100_000_000) #> 4                   ' adjust smart pin base period to actual frequency
  ORG
                fltl    #spi_di                        ' reset smart pins
                fltl    #spi_do
                wrpin   ##modeClk,#spi_ck              ' smart pin transition mode
                wrpin   ##modeTXD,#spi_di              ' smart pin synchronous serial transmit
                wrpin   ##modeRXD,#spi_do              ' smart pin synchronous serial receive
                wxpin   div,#spi_ck                    ' clock transition base period
                drvl    #spi_ck                        ' enable smart pin
  END

I would like to know with which clock the SD card is driven, if the clkfreq is 256Mhz.

Thanks

Comments

  • Wuerfel_21Wuerfel_21 Posts: 5,106
    edited 2022-10-31 20:48

    Since it is using transition mode, the effective clock is clkfreq/(div*2).
    For clkfreq = 256_000_000 that obviously comes out to... 4. Which it will always do since 500_000_000 is not a valid clkfreq.)

    So the clock frequency comes out to 32 MHz

  • wxpin ( P2clk / ( SPIclk * 2 ) ) << 16 , #spi_ck

    wxpin (256,000,000 / ( 5,000,000 * 2 ) ) << 16 , #spi_ck

    That's what I understood from the documentation.
    Is that correct?

  • No, the *2 is because of the transition mode. As the name implies, the divider values counts the cycles between level transitions (i.e. high-to-low and low-to-high), so the overall period is twice the divider value.

    Also, no <<16

  • Ok

    256,000,000÷2÷26 would be the correct way to calculate the value of wxpin? To get a takt of 5.000.000?

  • Checks out, value should be 26

  • I'm a simpleton: I prefer to use pulse mode for the SPI clock. This the setup from my simple flash interface object.

    pub start(khz) | m, x
    
    '' Configure SPI for coms with flash
    '' -- khz is clock frequency in kilohertz
    
      pinh(SF_CS)                                                   ' deselect flash
    
      m := P_SYNC_RX                                                ' spi rx mode
      m |= ((SF_SCK-SF_SDI) & %111) << 24                           ' add SCK offset (B pin)
      x := %0_00000 | (8-1)                                         ' sample ahead of b pin rise, 8 bits
      pinstart(SF_SDI, m, x, 0)                                     ' configure smart pin
      pinf(SF_SDI)                                                  ' reset/disable until used
    
      m := P_SYNC_TX | P_OE                                         ' spi tx mode
      m |= ((SF_SCK-SF_SDO) & %111) << 24                           ' add SCK offset (B pin)
      x := %1_00000 | (8-1)                                         ' start/stop mode, 8 bits
      pinstart(SF_SDO, m, x, 0)                                     ' activate smart pin
      pinf(SF_SDO)                                                  ' reset/disable until used
    
      m := P_PULSE | P_OE                                           ' spi clock mode
      x.word[0] := 2 #> (clkfreq / (khz * 1_000)) <# $FFFF          ' ticks in period
      x.word[1] := x.word[0] >> 1                                   ' ticks in low cycle (50%)
      pinstart(SF_SCK, m, x, 0)
    

    This lets you set the number of bits in the transaction very easily

    pri shiftout(value, bits) | x
    
    '' Shift out bits from value
    
      org
                    ror       value, bits                           ' msb to bit32
                    rev       value                                 ' reverse for S/P LSBFIRST output
    
                    mov       x, bits                               ' set # of output bits
                    sub       x, #1
                    or        x, #%1_00000
                    wxpin     x, #SF_SDO
                    wypin     value, #SF_SDO                        ' set output value
                    drvl      #SF_SDO                               ' arm SPI TX
                    wypin     bits, #SF_SCK                         ' clock bits out
                    nop
                    testp     #SF_SCK                       wc      ' wait for clocking to finish
        if_nc       jmp       #$-1
                    fltl      #SF_SDO                               ' disable SPI TX 
      end
    
  • pik33pik33 Posts: 2,388

    A warning: don't use too low frequency for the flash while SD is inserted. I managed to "unformat" the SD with 2 MHz clock for the flash (sector 0 overwritten). After testing a flash related (working) code there were no more files on the SD.

    I raised the flash clock to 20 MHz, no more SD problems.

  • evanhevanh Posts: 16,031
    edited 2022-11-01 09:22

    Use SPI clock mode 3 (CPOL=1, CPHA=1) to avoid incorrect device selection. That keeps the two clocks high during idle, which is important so as not to select the other device when idle. I've converted FlexC's SD driver to do this.

    The alternative mode 0 workaround is a convoluted device select sequence for each access to each device.

    Jon's code above only needs the clock inverted and it'll work fine as mode 3.

      m := P_PULSE | P_OE | P_INVERT_OUTPUT                     ' spi clock mode
    
  • pic18f2550pic18f2550 Posts: 400
    edited 2022-11-01 14:48

    Wuerfel_21 is that correct?
    I want to write first of all a sector of a SD card.
    What surprises me that in the original only 256 bytes stand should it not be 512?

    CON
            CLK_FREQ = 256_000_000        ' system freq as a constant
            _clkfreq = CLK_FREQ
    
    CON     spi_cs = 3
            spi_ck = 2
            spi_di = 1 ' P2 -> flash
            spi_do = 0 ' flash -> P2
    
            modeCLK = P_TRANSITION + P_OE + P_INVERT_OUTPUT     ' SPI_CK
            modeTXD = P_SYNC_TX + P_OE |((spi_ck - spi_di) & %111)<<24 ' + P_SYNC_IO + P_FILT0_AB
            modeRXD = P_SYNC_RX |((spi_ck - spi_do) & %111)<<24
    
            Write_Enable = $06
            Erase_4k     = $20
            Erase_64k    = $D8
            Write_Page   = $02
            Read_Data    = $03
            Read_Status  = $05
    
            div = (_clkfreq / (2 * 5_000_000)) #> 4                   ' adjust smart pin base period to actual frequency
    
    DAT
                    org  0
                    asmclk
    '+------------------------------------------------------------------------------------------------------------------------------+
    '+------------------------------------------------------------------------------------------------------------------------------+
    'PUB Spi_Init() | div
    '  div:= (clkfreq / 100_000_000) #> 4                   ' adjust smart pin base period to actual frequency
    '  ORG
                    fltl    #spi_di                        ' reset smart pins
                    fltl    #spi_do
                    wrpin   ##modeClk,#spi_ck              ' smart pin transition mode
                    wrpin   ##modeTXD,#spi_di              ' smart pin synchronous serial transmit
                    wrpin   ##modeRXD,#spi_do              ' smart pin synchronous serial receive
                    wxpin   div,#spi_ck                    ' clock transition base period
                    drvl    #spi_ck                        ' enable smart pin
     ' END
    '+------------------------------------------------------------------------------------------------------------------------------+
                    mov     cmd, #Write_Enable
    '+------------------------------------------------------------------------------------------------------------------------------+
    'PRI Spi_Cmd8(cmd)
    '  ORG
                    drvh    #spi_cs
                    shl     cmd,#24                        ' shift command up
                    rev     cmd
                    drvl    #spi_cs
                    wxpin   #$27,#spi_di                   ' 8 bits, start/stop mode
                    wypin   cmd,#spi_di
                    drvl    #spi_di                        ' enable TX smart pin
                    wypin   #16,#spi_ck                    ' start CLK sequence (16 transitions = 8 pulses)
                    nop
    .waitRdy2       testp   #spi_ck wz                     ' IN=1 if smart pin ready
            if_nz   jmp     #.waitRdy2                      ' wait until last CLK sequence finished
    '  END
    '+------------------------------------------------------------------------------------------------------------------------------+
                    mov     cmd, #Write_Page
                    mov     adr, #flashAdr
    '+------------------------------------------------------------------------------------------------------------------------------+
    'PRI Spi_Cmd32(cmd, adr)
    ' outputs 4 bytes: 8 bit command + 24 bits adr
    '  ORG
                    drvh    #spi_cs
                    shl     cmd,#24                 'shift command up
                    or      cmd,adr                 'or in address
                    drvl    #spi_cs
    '  END
    '  Spi_WrLong(cmd)
    '+------------------------------------------------------------------------------------------------------------------------------+
                    mov     data, cmd
    '+------------------------------------------------------------------------------------------------------------------------------+
    'PRI Spi_WrLong(data)
    ' outputs 32 bits (MSB first) while spi_cs stays low
    '  ORG
                    rev     data
                    wxpin   #$3f,#spi_di                   ' 32 bits, start/stop mode
                    wypin   data,#spi_di
                    drvl    #spi_di                        ' enable TX smart pin
                    wypin   #64,#spi_ck                    ' start CLK sequence (64 transitions = 32 pulses)
                    nop
    .waitRdy3       testp   #spi_ck wz                     ' IN=1 if smart pin ready
            if_nz   jmp     #.waitRdy3                      ' wait until last CLK sequence finished
    '  END
    '+------------------------------------------------------------------------------------------------------------------------------+
                    mov     data, puffer
    '+------------------------------------------------------------------------------------------------------------------------------+
    rep1
    'PRI Spi_WrLong(data)
    ' outputs 32 bits (MSB first) while spi_cs stays low
    '  ORG
                    rev     data
                    wxpin   #$3f,#spi_di                   ' 32 bits, start/stop mode
                    wypin   data,#spi_di
                    drvl    #spi_di                        ' enable TX smart pin
                    wypin   #64,#spi_ck                    ' start CLK sequence (64 transitions = 32 pulses)
                    nop
    .waitRdy2       testp   #spi_ck wz                     ' IN=1 if smart pin ready
            if_nz   jmp     #.waitRdy2                      ' wait until last CLK sequence finished
    '  END
                    add     data, #4
    '+------------------------------------------------------------------------------------------------------------------------------+
                    rep     128,#rep1                       ' 128*4 = 512 = 1 Sector
    '+------------------------------------------------------------------------------------------------------------------------------+
                    drvh    #spi_cs
    '+------------------------------------------------------------------------------------------------------------------------------+
    '               #################
    loop2           jmp     #loop2
    '+------------------------------------------------------------------------------------------------------------------------------+
    flashAdr      long      $60000                          ' später ab 0
    puffer        long      $1000
    '+------------------------------------------------------------------------------------------------------------------------------+
    cmd           long      0
    adr           long      0
    data          long      0
    
    

    Source: https://github.com/parallaxinc/propeller/tree/master/libraries/community/p2/All/Simple_SpiFlash

  • That's a flash driver, not an SD driver

  • Sorry Wuerfel_21 was already on the other topic, it was about SD cards. :/

Sign In or Register to comment.