Shop OBEX P1 Docs P2 Docs Learn Events
C3 Read a decimal value to the FLASH — Parallax Forums

C3 Read a decimal value to the FLASH

nestor73nestor73 Posts: 33
edited 2011-06-19 00:39 in Propeller 1
Hi,

i'm fairly new to this, so can someone explain me how a decimal value (1..20)
is written to the flash memory ? I have studied and tried the c3_flash_demo_010.spin
and i can write values , but the reading doesn't return the values. I'm sure i'm doing
something wrong with the address or the value , or the bytes to read write :tongue:

thanx for any eplanation

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2011-06-17 07:47
    Writing to flash works the way it's described in the demo program. Are you using the unmodified demo program? If not, post what you're using. If you're using the demo program, what are you entering when it asks?

    You're asking how a decimal value is written to flash memory. You probably don't want the literal answer to your question, it's interesting, but won't help you get things to work. Tell us what you're doing and maybe we can help more.
  • nestor73nestor73 Posts: 33
    edited 2011-06-18 01:26
    Hi Mike,

    I don't really have written new code to do this in my project, i'm still messing with the demo to try and figure out how to make it easier to implement.

    I don't really get the whole setup in the Flash_Write and Flash_Read , i was hoping to just point to an address and write a hex and read it from the
    same place. If only life was that simple ? :P

    I cant seem to find any demo that writes a decimal value and reads it back as example :(
  • nestor73nestor73 Posts: 33
    edited 2011-06-18 01:49
    If i , for example, try to run this code :
         g_sbuffer[ 1 ] := 256                             ' Fill the Buffer 
         Flash_Write( 0, @g_sbuffer, 512 )         ' write buffer to flash
        bytefill ( @g_sbuffer, $00, 512)               ' clear buffer out
        Flash_Read( 0, @g_sbuffer, 512 )          ' read flash into buffer
    

    and i try to read the second address :
    NP:=g_sbuffer[ 1 ]
    

    the value of NP remains empty (=00)

    not sure where it goes wrong..
  • kuronekokuroneko Posts: 3,623
    edited 2011-06-18 01:59
    g_sbuffer[1] := 256                             ' Fill the Buffer
    
    g_sbuffer is a byte buffer. Assigning 256 to one of its elements is equivalent to assigning 0 (a byte can only hold values from 0..255). Try a different value.
  • nestor73nestor73 Posts: 33
    edited 2011-06-18 02:04
    Oh dang, that 's true, but i also tried with smaller numbers before , eg. 8 and 10 i still get a 00.

    Maybe i am going wrong in displaying the returns to the screen ?
    NPS:=strings.hexadecimalToInteger(NP)  ' convert to integer 
    tmp.displayString(strings.integertodecimal(NPS,2), tmp#blue, tmp#white, 6,25 )       
    
    PUB hexadecimalToInteger(characters) | sign '' 10 Stack Longs
      characters := checkSign(ignoreSpace(characters), @sign)
      repeat (strsize(characters) <# 8)
        ifnot(checkDigit(characters, "0", "9"))
          ifnot(checkDigit(characters, "A", "F") or checkDigit(characters, "a", "f"))
            quit
          result += $90_00_00_00
        result := ((result <- 4) + (byte[characters++] & $F))
      result *= sign
    
  • kuronekokuroneko Posts: 3,623
    edited 2011-06-18 02:14
    The function hexadecimalToInteger expects a string AFAICS. I'd suggest sending the value NP to the serial terminal (dec method) before trying anything more sophisticated, e.g.
    serial.dec(NP)
    
    Once this is verified take the next step and send it to your particular display.
  • nestor73nestor73 Posts: 33
    edited 2011-06-18 02:17
    Ok thanks allot, i'll try this and come back here
  • nestor73nestor73 Posts: 33
    edited 2011-06-18 02:53
    Whatever i try, i still get a '0' with
    Serial.Dec(g_sbuffer[1])
    

    I make sure that the Flash_Erase has been done in the startup,
    then i write a value to the buffer[1] , but so far no real readout :(
  • kuronekokuroneko Posts: 3,623
    edited 2011-06-18 03:09
    Does the test/demo program you mention in the first post work for you? Personally I don't have a C3 so anything would have to be a blind suggestion from my side. It would also be helpful if you'd attached your modified test program in its entirety.
  • nestor73nestor73 Posts: 33
    edited 2011-06-18 03:25
    Yes, the test program works on the TV output, i can enter a Decimal number , for example : address : 1 , value : 12 , bytes : 1
    and the readout of 1 byte at address 1 gives me 0C

    I'm going to write a new small test program, the whole program would take too much.
  • nestor73nestor73 Posts: 33
    edited 2011-06-18 03:36
    Here it is :
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      _pinGroup = 2
      _startUpWait = 1
      CLOCKS_PER_MILLISECOND = 5000*16
      CLOCKS_PER_MICROSECOND = 5*16       ' simple xin*pll / 1_000_000                     
      
      ' SPI pins
      SPI_SEL_CLK            = 8  ' used to clock the SPI counter that feeds 4-bit value to SPI selection decoder, clocks on rising edge
      SPI_SEL_CLR            = 25 ' used to clear the SPI counter back to 0000b (NULL SPI device), active LOW
      SPI_MOSI               = 9  ' SPI master out serial in to slave
      SPI_MISO               = 10 ' SPI master in serial out from slave, 10 for good C3, change to 7 for BROKEN C3 with YELLOW jumper.
      SPI_SCK                = 11 ' SPI clock from master to all slaves
    
     ' SPI channels defines 
      SPI_CHAN_NULL          = 0 ' NULL channel, disables all on/off board devices.
      SPI_CHAN_SRAM0         = 1 ' 32K SRAM Bank 0.
      SPI_CHAN_SRAM1         = 2 ' 32K SRAM Bank 1.
      SPI_CHAN_FLASH         = 3 ' 1MB FLASH Memory.
      SPI_CHAN_AD            = 4 ' MCP3202 2-Channel 12-bit A/D.
      SPI_CHAN_SD            = 5 ' Micro SD Card.
      ' interface header SPI selects
      SPI_CHAN_SPI6          = 6 ' Header Interface SPI6.
      SPI_CHAN_SPI7          = 7 ' Header Interface SPI7.
      ' Atmel 2F004/8xxx series basic commands
      WRITE_ENABLE     = $06
      WRITE_DISABLE    = $04
      READ_STATUS      = $05
      WRITE_STATUS     = $01
      READ_DATA        = $03
      SEQ_PROGRAM      = $AF  
      BYTE_PROGRAM     = $02 
      BLOCK_ERASE4     = $20
      BLOCK_ERASE32    = $52
      BLOCK_ERASE64    = $D8
      SECTOR_ERASE     = $20    
      CHIP_ERASE       = $60 
      JEDEC_ID         = $9F
      PROTECT_SECTOR   = $36 
      UNPROTECT_SECTOR = $39 
      ' custom commands we make up, not part of chip spec, just used here, start at code 0xF0
      UNPROTECT_CHIP   = $F0
        ' ASCII codes for ease of parser development
      ASCII_A      = 65
      ASCII_B      = 66
      ASCII_C      = 67
      ASCII_D      = 68
      ASCII_E      = 69
      ASCII_F      = 70
      ASCII_G      = 71
      ASCII_H      = 72
      ASCII_O      = 79  
      ASCII_P      = 80
      ASCII_Z      = 90
      ASCII_0      = 48
      ASCII_9      = 57
      ASCII_LEFT   = $C0
      ASCII_RIGHT  = $C1
      ASCII_UP     = $C2
      ASCII_DOWN   = $C3 
      ASCII_BS     = $C8 ' backspace
      ASCII_DEL    = $C9 ' delete
      ASCII_LF     = $0A ' line feed 
      ASCII_CR     = $0D ' carriage return
      ASCII_ESC    = $CB ' escape
      ASCII_HEX    = $24 ' $ for hex
      ASCII_BIN    = $25 ' % for binary
      ASCII_LB     = $5B ' [ 
      ASCII_SEMI   = $3A ' ; 
      ASCII_EQUALS = $3D ' = 
      ASCII_PERIOD = $2E ' .
      ASCII_COMMA  = $2C ' ,
      ASCII_SHARP  = $23 ' #
      ASCII_NULL   = $00 ' null character
      ASCII_SPACE  = $20 ' space
      ASCII_TAB    = $09 ' horizontal tab
        ' null pointer, null character
      NULL         = 0  
    OBJ
      Serial :    "Parallax Serial Terminal"       
    VAR
      byte g_sbuffer[512]
    PUB demo 
      Serial.Start(115_200)
      Flash_Open
      Flash_Erase_Chip(1)
      bytefill ( @g_sbuffer, $00, 512)                               
      g_sbuffer[ 1 ] := 99
      Flash_Write( 0, @g_sbuffer, 512 )
      
      bytefill ( @g_sbuffer, $00, 512)   
      repeat
        Flash_Read( 0, @g_sbuffer, 512 )
        Serial.Str(String(" ValueDecimal :"))
        Serial.Dec(g_sbuffer[ 1 ])
        delay_ms(1000)
    
    PUB Flash_Open | _index, _spi_data, _flash_start_addr
      ' use global unprotect to unprotect entire chip at once, write "0" to bits 2,3,4,5
      SPI_Select_Channel( SPI_CHAN_FLASH )
      _spi_data := SPI_Write_Read( 8, WRITE_ENABLE, $FF )
      SPI_Select_Channel( 0 )
      Flash_Write_Status ( Flash_Read_Status & %11_0000_11 )
      Delay_MS( 10 )   
      ' // return success always
      return( 1 )
      
    PUB Flash_Read_Status | _spi_data
    {{
    Reads the FLASH memory status register
    PARMS: None.
    RETURNS: status register value
    }}
      '// set CS to SPI select channel 3 (FLASH)
      SPI_Select_Channel( SPI_CHAN_FLASH )
      _spi_data := SPI_Write_Read( 8, READ_STATUS, $FF )
      ' now read data returned
      _spi_data := SPI_Write_Read( 8, $FF, $FF )
       
      '// disable SPI interface
      '// set CS to SPI select channel 0 (null)
      SPI_Select_Channel( 0 )
      ' return results
      return ( _spi_data )   
    ' // end Flash_Read_Status
    ' /////////////////////////////////////////////////////////////////////////////
    PUB Flash_Write_Status ( status ) | _spi_data
    {{
    Writes the FLASH memory status register
    PARMS:
    status - value to update the status register with
    RETURNS: None.
    }}
      '// set CS to SPI select channel 3 (FLASH)
      SPI_Select_Channel( SPI_CHAN_FLASH )
      _spi_data := SPI_Write_Read( 8, WRITE_STATUS, $FF )
      _spi_data := SPI_Write_Read( 8, status, $FF )  
       
      '// disable SPI interface
      '// set CS to SPI select channel 0 (null)
      SPI_Select_Channel( 0 )
      ' return success for now
      return ( 1 )   
    ' // end Flash_Write_Status
    ' /////////////////////////////////////////////////////////////////////////////
    PUB Flash_Erase_Chip( wait ) | _spi_data
      '// set CS to SPI select channel 3 (FLASH)
      SPI_Select_Channel( SPI_CHAN_FLASH )
      _spi_data := SPI_Write_Read( 8, WRITE_ENABLE, $FF )
       
      '// disable SPI interface
       
      '// set CS to SPI select channel 0 (null)
      SPI_Select_Channel( 0 )
      '// set CS to SPI select channel 3 (FLASH)
      SPI_Select_Channel( SPI_CHAN_FLASH )
      _spi_data := SPI_Write_Read( 8, CHIP_ERASE, $FF )
       
      '// disable SPI interface
       
      '// set CS to SPI select channel 0 (null)
      SPI_Select_Channel( 0 )
      ' test if user requested wait for completion?
      if (wait)
        repeat
          ' erase operation still ongoing?
          if ((Flash_Read_Status & $01)==0)
            return (1)
         
      '// return success for now
      return(1)
    ' /////////////////////////////////////////////////////////////////////////////
    PUB Flash_Write( flash_start_addr, buffer_ptr, num_bytes) | _index, _spi_data
    {{
    This function writes num_bytes bytes to the FLASH memory at flash_start_addr from the sent buffer_ptr.
    It uses the byte/page write function. Although, there is a "sequential" byte write function available
    on the AT26DF081A the new rev of the Atel chips (AT25xxxx series) coming out in 2011 have replaced the sequential write with
    another function :(, thus we simply have to check for page boundaries and re-issue another page write
    every 256 bytes.
    PARMS:
    flash_start_addr - starting address in the FLASH memory to write the data at.
    buffer_ptr       - local byte pointer to Prop memory holding data to write to FLASH memory.
    num_bytes        - number of bytes to write to FLASH from source buffer_ptr. 
    }}
      '// STEP 1: enable writing to the chip again
      '// enable SPI interface
       
      '// set CS to SPI select channel 3 (FLASH)
      SPI_Select_Channel( SPI_CHAN_FLASH )
      _spi_data := SPI_Write_Read( 8, WRITE_ENABLE, $FF )
       
      '// disable SPI interface
       
      '// set CS to SPI select channel 0 (null)
      SPI_Select_Channel( 0 )
       
      '// STEP 2: write buffer to address in flash //////////////////
       
      '// set CS to SPI select channel 3 (FLASH)
      SPI_Select_Channel( SPI_CHAN_FLASH )
       
      '// initiate byte/page program command
      _spi_data := SPI_Write_Read( 8, BYTE_PROGRAM, $FF )
       
      '// write starting address byte by byte, MSB first...
      _spi_data := SPI_Write_Read( 8, flash_start_addr >> 16, $FF )
      _spi_data := SPI_Write_Read( 8, flash_start_addr >> 8, $FF )
      _spi_data := SPI_Write_Read( 8, flash_start_addr >> 0, $FF )
      '// write first byte of 
      _spi_data := SPI_Write_Read( 8, byte [buffer_ptr][ 0 ], $FF )
      _index := 1   
      '// write remaining bytes
      repeat until (_index => num_bytes )
        ' now test if we are on a page boundary, if so finish page, and start new page
        if ( ((flash_start_addr + _index) // 256) == 0)
          '// set CS to SPI select channel 0 (null)
          SPI_Select_Channel( 0 )
          ' replace this with polling...
          Delay_MS(10) 
          '// set CS to SPI select channel 3 (FLASH)
          SPI_Select_Channel( SPI_CHAN_FLASH )
          _spi_data := SPI_Write_Read( 8, WRITE_ENABLE, $FF )
          SPI_Select_Channel( 0 )
          SPI_Select_Channel( SPI_CHAN_FLASH )
                   
          '// re-issue byte/page program command
          _spi_data := SPI_Write_Read( 8,BYTE_PROGRAM,$FF )
          '// write starting address byte by byte, MSB first...
          _spi_data := SPI_Write_Read( 8, (flash_start_addr + _index) >> 16, $FF )
          _spi_data := SPI_Write_Read( 8, (flash_start_addr + _index) >> 8, $FF )
          _spi_data := SPI_Write_Read( 8, (flash_start_addr + _index) >> 0, $FF )
          ' end if 
        '// write the next byte of data
        _spi_data := SPI_Write_Read( 8, byte [buffer_ptr][ _index ], $FF )
        _index++
        
        ' // end for index    
      '// set CS to SPI select channel 0 (null)
      SPI_Select_Channel( 0 )
      ' write final bytes left in internal buffer, replace this with polling...
      Delay_MS(10) 
         
      '// disable SPI interface
       
      '// return success
      return(1)
       
    ' // end Flash_Write
    ' ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    PUB Flash_Read( flash_start_addr, buffer_ptr, num_bytes) | _index, _spi_data
    {{
    This function reads num_bytes from the FLASH memory starting at memory location flash_start_addr and stores the data in
    buffer_ptr.
    PARMS:
    flash_start_addr - starting address in FLASH memory to read data from.
    buffer_ptr       - local Prop byte pointer to store the read data at.
    num_bytes        - the number of bytes to read from the FLASH memory. 
    RETURNS: None.
    }}
      '// set CS to SPI select channel 3 (FLASH)
      SPI_Select_Channel( SPI_CHAN_FLASH )
      '// initiate read command
      _spi_data := SPI_Write_Read( 8, READ_DATA, $FF )
      '// write starting address byte by byte, MSB first...
      _spi_data := SPI_Write_Read( 8, flash_start_addr >> 16, $FF )
      _spi_data := SPI_Write_Read( 8, flash_start_addr >> 8, $FF )
      _spi_data := SPI_Write_Read( 8, flash_start_addr >> 0, $FF )
      
      '// now read data 
      repeat _index from  0 to num_bytes-1
        byte [buffer_ptr][_index] := SPI_Write_Read( 8, $00, $FF )
        ' // end for index
      '// disable SPI interface
      '// set CS to SPI select channel 0 (null)
      SPI_Select_Channel( 0 )
      '// return success 
      return(1)
    ' // end Flash_Read
    ' /////////////////////////////////////////////////////////////////////////////
    '//////////////////////////////////////////////////////////////////////////////
    ' FLASH MACROS ////////////////////////////////////////////////////////////////
    '//////////////////////////////////////////////////////////////////////////////
    PUB FLASH_ADDR_TO_BLOCK( n )
      n := (n >> 12)
    ' /////////////////////////////////////////////////////////////////////////////
      
    PUB FLASH_BLOCK_TO_ADDR( n )
      n := (n << 12)
    ' /////////////////////////////////////////////////////////////////////////////
    ' /////////////////////////////////////////////////////////////////////////////
    ' SPI ROUTINES///////// ///////////////////////////////////////////////////////
    ' /////////////////////////////////////////////////////////////////////////////
    PUB SPI_Init
    {{
    This function initializes the SPI IO's, counter, and mux, selects channel 0 and returns.
    PARMS: none.
    RETURNS: nothing.
    }}
      ' set SPI mux counter IOs up
      DIRA[SPI_SEL_CLK] := 1 ' set to output
      OUTA[SPI_SEL_CLK] := 0
      DIRA[SPI_SEL_CLR] := 1 ' set to output
      OUTA[SPI_SEL_CLR] := 0 ' CLR counter
      OUTA[SPI_SEL_CLR] := 1 ' allow counting
      ' set up SPI lines
      OUTA[SPI_MOSI]     := 0 ' set to LOW
      OUTA[SPI_SCK]      := 0 ' set to LOW
     
      DIRA[SPI_MOSI]     := 1 ' set to output
      DIRA[SPI_MISO]     := 0 ' set to input
      DIRA[SPI_SCK]      := 1 ' set to output
      ' set SPI to NULL channel 0
      SPI_Select_Channel( 0 )
    ' end SPI_Init
    
    ' /////////////////////////////////////////////////////////////////////////////
    PUB SPI_Write_Read( num_bits, data_out, bit_mask) | data_in
    {{
    This function writes and reads SPI data a bit at a time (SPI is a circular buffer protocal), the data is in MSB to LSB format
    and up to 32-bits can be transmitted and received, the final result is bit masked by bit_mask
    PARMS:
    num_bits : number of bits to transmit from data_out
    data_out : source of data to transmit
    bit_mask : final result of SPI transmission is masked with this to grab the relevant least significant bits
    RETURNS: data retrieved from SPI transmission
    }}
      ' clear result
      data_in := 0
      ' now read the bits in/out
      repeat num_bits
        ' drop clock
        OUTA[SPI_SCK] := 0
        ' place next bit on MOSI
        OUTA[SPI_MOSI] := ((data_out >> (num_bits-- - 1)) & $01)
     
        ' now read next bit from MISO
        data_in := (data_in << 1) + INA[SPI_MISO]
          
        ' raise clock
        OUTA[SPI_SCK] := 1
      ' set clock and MOSI to LOW on exit
      OUTA[SPI_MOSI]  := 0
      OUTA[SPI_SCK]   := 0
      ' at this point, the data has been written and read, return result
      return ( data_in & bit_mask )            
        
    ' end SPI_Write_Read
    ' /////////////////////////////////////////////////////////////////////////////
    PUB SPI_Select_Channel( channel )
    {{
    This function sets the active SPI channel chip select on the SPI mux, this is accomplished by first resetting the
    SPI counter that feeds the SPI select decoder, then upcounting the requested number of channels.
    PARMS:
    channel : channel 0 to 7 to enable where the channels are defined as follows
              0 - NULL channel, disables all on/off board devices.
              1 - 32K SRAM Bank 0.
              2 - 32K SRAM Bank 1.
              3 - 1MB FLASH Memory.
              4 - MCP3202 2-Channel 12-bit A/D.
              5 - Micro SD Card.
              6 - Header Interface SPI6.
              7 - Header Interface SPI7.
    RETURNS: nothing.
    }}
      ' requesting channel 0? If so, easy reset
      if (channel == 0)
        ' clear the 161
        OUTA[SPI_SEL_CLR] := 0 ' CLR counter
        OUTA[SPI_SEL_CLR] := 1 ' allow counting
        return
      ' else non-null channel, count up to channel...
      
      ' first reset the SPI channel counter
      ' clear the 161
      OUTA[SPI_SEL_CLR] := 0 ' CLR counter
      OUTA[SPI_SEL_CLR] := 1 ' allow counting
      ' now increment to requested channel
      ' clock the 161
       OUTA[SPI_SEL_CLK] := 0
       repeat channel
         OUTA[SPI_SEL_CLK] := 1
         OUTA[SPI_SEL_CLK] := 0        
    ' end SPI_Select_Channel
    
    ' /////////////////////////////////////////////////////////////////////////////
    ' UTILITY ROUTINES ////////////////////////////////////////////////////////////
    ' /////////////////////////////////////////////////////////////////////////////
    
    PUB StrCpy( dest_str_ptr, source_str_ptr ) | _index
    {{
    mimics C strcpy, copies source -> destination including NULL
    }}
    ' test if there is storage
    if (dest_str_ptr == NULL)
      return (NULL)
    _index := 0
    repeat while (byte [ source_str_ptr ][_index] <> NULL)
      ' copy next byte
       byte [ dest_str_ptr ][_index] := byte [ source_str_ptr ][_index]    
       _index++
    ' null terminate
    byte [ dest_str_ptr ][_index] := NULL
    ' return number of bytes copied
    return ( _index )
    ' // end StrCpy
    ' /////////////////////////////////////////////////////////////////////////////
    PUB StrUpper(string_ptr)
    {{
    upcases a string
    }}
      if (string_ptr <> NULL)
        repeat while (byte[ string_ptr ] <> NULL)
          byte[ string_ptr ] :=  ToUpper( byte[ string_ptr ] )
          string_ptr++  
      ' return string
      return (string_ptr)
    ' // end StrUpper
    ' /////////////////////////////////////////////////////////////////////////////
    PUB ToUpper(ch)
    {{
    returns the uppercase of the sent character
    }}
    if (ch => $61 and ch =< $7A)
      return(ch-32)
    else
      return(ch)
    ' // end ToUpper
    ' /////////////////////////////////////////////////////////////////////////////
    PUB IsInSet(ch, set_string)
    {{
    tests if sent character is in string
    }}
    repeat while (byte[set_string][0] <> NULL)
      if (ch == byte[set_string++][0])
        'serial.txstring(string ("found!") )
        return( ch )
    'serial.txstring(string ("not found!") )
    ' not found
    return( -1 )    
    ' // end IsInSet
    ' /////////////////////////////////////////////////////////////////////////////
    PUB IsSpace(ch)
    {{
    tests if sent character is white space, cr, lf, space, tab
    }}
    if ( (ch == ASCII_SPACE) or (ch == ASCII_LF) or (ch == ASCII_CR) or (ch == ASCII_TAB))
      return (ch)
    else
      return(-1)  
    ' // end IsSpace
    ' /////////////////////////////////////////////////////////////////////////////
    PUB IsNull(ch)
    {{
    tests if sent character is null
    }}
    if ( (ch == NULL))
      return (1)
    else
      return(-1)  
    ' // end IsNull
    ' /////////////////////////////////////////////////////////////////////////////
    PUB IsDigit(ch)
    {{
    tests if sent character is a number 0..9, returns integer 0..9
    }}
    if (ch => ASCII_0 and ch =< ASCII_9)
      return (ch-ASCII_0)
    else
      return(-1)  
    ' // end IsDigit
    ' /////////////////////////////////////////////////////////////////////////////
    PUB IsAlpha(ch)
    {{
    tests if sent character is a number a...zA...Z
    }}
    ch := ToUpper(ch)
    if ( (ch => ASCII_A) and (ch =< ASCII_Z))
      return (ch)
    else
      return(-1)  
    ' end IsAlpha
    ' /////////////////////////////////////////////////////////////////////////////
    PUB IsPunc(ch)
    {{
    tests if sent character is a punctuation symbol [EMAIL="!@#$%^&*()--+={}[]|\;:'&quot;,<.>/"]!@#$%^&*()--+={}[]|\;:'",<.>/[/EMAIL]?
    }}
    ch := ToUpper(ch)
    if (  ((ch => 33) and (ch =< 47)) or  ((ch => 58) and (ch =< 64)) or ((ch => 91) and (ch =< 96)) or ((ch =>123) and (ch =< 126))  ) 
      return (ch)
    else
      return(-1)  
    ' // end IsPunc
                                                                                    
    ' /////////////////////////////////////////////////////////////////////////////
    PUB HexToDec(n)
    {{
    converts hex digit to decimal
    }} 
      if ( (n => "0") and (n =< "9") )
        return (n - ASCII_0)
      elseif ( (n => "A") and (n =< "F") )
        return (n - "A" + 10)
      else
        return ( 0 )  
    ' // end HexToDec
    ' /////////////////////////////////////////////////////////////////////////////
    PUB itoa(value, string_ptr) | i
    {{
     converts value into a string and stores in string_ptr with NULL termination
     }}
      if value < 0
        -value
        byte [ string_ptr++ ]  := "-"
      i := 1_000_000_000
      repeat 10
        if value => i
          byte [ string_ptr++ ]  := value / i + "0"
          value //= i
          result~~
        elseif result or i == 1
          byte [ string_ptr++ ]  := "0"
        i /= 10
      ' null terminate
      byte [ string_ptr ] := NULL    
    ' // end itoa
    ' /////////////////////////////////////////////////////////////////////////////
    PUB atoi2(string_ptr, length) | _index, _sum, _ch, _sign
    {{
    this function tries to convert the string to a number, supports binary %, hex $, decimal (default)
    string_ptr can be to a null terminated string, or the length can be overridden by sending the length shorter
    than the null terminator, ignores ws
    Eg. %001010110, $EF, 25
    }}
    ' initialize vars
    _index := 0
    _sum   := 0
    _sign  := 1
     
    ' consume white space
    repeat while (IsSpace( byte[ string_ptr ][_index] ) <> -1)
      _index++
     
    ' is there a +/- sign?
    if (byte [string_ptr][_index] == "+")
      ' consume it
      _index++
    elseif (byte [string_ptr][_index] == "-")
      ' consume it
      _index++
      _sign := -1    
         
    ' try to determine number base
    if (byte [string_ptr][_index] == ASCII_HEX)
      _index++
      repeat while ( ( IsDigit(_ch := byte [string_ptr][_index]) <> -1) or ( IsAlpha(_ch := byte [string_ptr][_index]) <> -1)  )
        _index++
        _sum := (_sum << 4) + HexToDec( ToUpper(_ch) )
        if (_index => length)
          return (_sum*_sign)
     
      return(_sum*_sign)
    ' // end if hex number    
    elseif (byte [string_ptr][_index] == ASCII_BIN)
      repeat while ( IsDigit(_ch := byte [string_ptr][++_index]) <> -1)
        _sum := (_sum << 1) + (_ch - ASCII_0)
        if (_index => length)
          return (_sum*_sign)
     
      return(_sum*_sign)
    ' // end if binary number  
    else
      ' must be in default base 10, assume that
      repeat while ( IsDigit(_ch := byte [string_ptr][_index++]) <> -1)
        _sum := (_sum * 10) + (_ch - ASCII_0)
        if (_index => length)
          return (_sum*_sign)
     
      return(_sum*_sign)
     
    ' else, have no idea of number format!
    return(0)
     
    ' // end atoi2
    ' /////////////////////////////////////////////////////////////////////////////
    PUB Delay_MS( time )
    {{
    Delays "time" milliseconds and returns.
    }}
      waitcnt (cnt + time*CLOCKS_PER_MILLISECOND)
    ' // end Delay_MS
    ' /////////////////////////////////////////////////////////////////////////////
    PUB Delay_US( time )
    {{
    Delays "time" microseconds and returns.
    }}
      waitcnt (cnt + time*CLOCKS_PER_MICROSECOND)
    
    ' // end Delay_US
    '//////////////////////////////////////////////////////////////////////////////
      
    
  • nestor73nestor73 Posts: 33
    edited 2011-06-18 03:49
    Also filling the complete buffer returns nothing but zero's
    PUB demo 
      Serial.Start(115_200)
      Flash_Erase_Chip(1)
     ' bytefill ( @g_sbuffer, $00, 512)
      repeat g_index from 0 to 511
          g_sbuffer[ g_index ] := (g_index*g_index) // 256
     ' g_sbuffer[ 1 ] := 99
     
      Flash_Write( 0, @g_sbuffer, 512 )
      
      bytefill ( @g_sbuffer, $00, 512)   
      Flash_Read( 0, @g_sbuffer, 512 )
     
       repeat g_index from 0 to 511        
            Serial.Str(String(" Value :"))
            Serial.Hex(g_sbuffer[ g_index ],8)
            delay_ms(100)
    
  • nestor73nestor73 Posts: 33
    edited 2011-06-18 03:56
    Well.... solved..

    I forgot to add :
      SPI_Init
      Flash_Open
    

    As Homer Simpson would say..... DOH !
  • kuronekokuroneko Posts: 3,623
    edited 2011-06-18 04:05
    ' initialize SPI IO (eventhough, we aren't using it in this demo at all, good habit to set it up)
    Don't you just love those comments?
  • nestor73nestor73 Posts: 33
    edited 2011-06-18 08:32
    It was exactly this comment that made me ignore the SPI... indeed, you gotta love those comments !
  • nestor73nestor73 Posts: 33
    edited 2011-06-18 09:33
    I came accross a new problem. How can enable an address to be rewritten /updated ? I see in the manual this explanation :

    Note: you can only write a memory location that has not been written to. Once a memory location has been written to, you can’t alter it, you must erase the block, sector, or the entire chip first to clear the memory location.

    Ok, so i tried the following :

    1) When i delete the entire chip at startup, then add a new value to the address, things work fine

    2) When i change that value and want to update it to the flash, i therefor read the 0..512 bytes into
    a buffer, i change buffer of the value ( buffer [address]= newvalue) , i erase the whole chip and
    i write the whole buffer again. Doesn't work . For some reason i have the feeling that the erasing
    doesn't happen, i don't know why since i call the same function (Flash_Erase_Chip(1))

    3) i tried to write a $FF to the address , doesn't work either.

    Someone knows a method to erase only the address i want to update ?
  • Mike GreenMike Green Posts: 23,101
    edited 2011-06-18 09:47
    You can't. The smallest unit that can be erased is a 4K block. Remember that there's a limit on the number of times you can erase a block or the whole chip. Eventually the chip (or the individual block) wears out and can't be erased anymore.

    Are you just looking to learn how to use the flash memory or do you have a specific application in mind?

    Attached is an object for reading and writing to either flash or SRAM on the C3. It's functionally the same as the Winbond flash driver already in the Object Exchange. It lets you set up named files that you can read or create (no updating in place). It also lets you read and write individual blocks and erase 4K sectors.
  • nestor73nestor73 Posts: 33
    edited 2011-06-19 00:39
    Thanx Mike, i managed to get it working by erasing the fist block (Flash_Erase(0) ), and rewriting the buffer to it. Aldo i think this is highly ineffecient.
Sign In or Register to comment.