Skip to content

Instantly share code, notes, and snippets.

@hxmuller
Last active July 25, 2023 06:47
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save hxmuller/1c209d2dcbd9f5e717416a37237b649e to your computer and use it in GitHub Desktop.
Save hxmuller/1c209d2dcbd9f5e717416a37237b649e to your computer and use it in GitHub Desktop.
Program the SPI NOR flash on a Pinebook Pro using a Raspberry Pi

Program SPI NOR Flash on Pinebook Pro with a Raspberry Pi

TL;DR: This describes the process, hardware, and software used to perform in-circuit programming of the 128Mbit SPI NOR flash in the Pinebook Pro using a Raspberry Pi.

Warning

You, the user of this information bear ALL responsibility for ANY outcome of its use, whether negative or positive. My success in this operation can be attributed to the following factors:

  • Attention to detail
  • Curiousity
  • Research
    • datasheets
    • man pages
    • critical review of web articles
  • Having all required materials prior to starting

The SPI NOR flash (identified below) this document refers to is rated for a minimum 100000 program/erase cycles. Exercising it beyond that limit will likely require its replacement which is non-trivial.

Although these instructions describe the process using the Pinebook Pro and a Raspberry Pi, it is recommmended that you have access to a separate laptop/desktop with internet access and micro SD card reader. If you render your Pinebook Pro unusable by accident you can potentially use this other machine to restore the Pinebook Pro to a usable state.

If working in an area conducive to electrostatic discharge (ESD) an ESD wrist strap is recommended.

You, the user of this information, are responsible for ANY and ALL outcomes of its use.

Introduction

The Pinebook Pro and a few of its cousins (ROCKPro64, ROCK64, PINE A64-LTS, PINE H64 vB, CUBE?) contain a 128Mbit SPI NOR flash chip. My specific unit contains the GigaDevice GD25Q127CSIG. The datasheet is available on the wiki for review.

My interest in accessing the SPI NOR flash is both in reading/verification of its contents and in programming the device with new contents (u-boot). Ideally this could be performed directly from u-boot which would require both functioning SPI and USB drivers in u-boot. The u-boot version shipping on the Pinebook Pro (PBP) at present can access neither the SPI NOR flash nor a USB flash drive. This was determined through experimentation. I can confirm the SPI NOR flash on the Pinebook Pro arrives erased (all 1s) and that the process I will describe works.

This document was originally intended to describe the same process, but using an FT2232H Mini Module. It turns out the mini module I purchased was defective and I had to resort to a different approach. I have no preference for the Raspberry Pi (RPI), but I did have one available to use. This process is sure to work with PINE SBCs but I do not own any at present.

Hardware Requirements

NOTE: All links provided in this section are for illustrative purposes and not intended as an endorsement of a product, company, or service.

Software Requirements

  • Raspbian (Buster) Lite
  • flashrom (installed on Raspbian Lite by default)
  • dd (installed on default Debian desktop by default)

Prepare Raspberry Pi 2 model B Raspbian Disk Image

I can confirm the Raspbian disk image created September 2019 includes the required utility, flashrom. No additional downloads or application installations are required. If in the future flashrom is not included then you must install it yourself on the Raspberry Pi. Remember, prior to connecting an IOT device to the internet it must be configured to improve security. The process described below does not require the Raspberry Pi to be connected to the internet at any time.

  1. Use Pinebook Pro to download Raspbian Lite

  2. Verify the SHA256 checksum for the download:

    $ cd /path/to/download
    $ editor verify.txt
    
    • Copy checksum from download page and paste into document
    • On same line, append 2 spaces to end of the checksum
    • On same line, type in the name of the downloaded file
    • Save and close the file
    $ sha256sum -c verify.txt
    

    The output of the last command should indicate OK

  3. Extract the Raspbian disk image:

    $ unzip <DOWNLOADED FILENAME>
    
  4. Insert an empty micro SD card into card reader on Pinebook Pro

  5. Determine mmc device created for micro SD card (most likely /dev/mmcblk0) by entering the following in a terminal:

    $ lsblk
    

    The eMMC device will NOT be the mmcblk# entry that has both the /boot and / partitions, the other mmcblk# is the one you want to use in the next step (most likely /dev/mmcblk1)

  6. The command below assumes /dev/mmcblk1 but YOU must confirm using the command above. Copy the Raspbian disk image to the micro SD card:

    $ sudo dd if=<image filename>.img of=/dev/mmcblk1 bs=4M conv=fsync
    
  7. Remove the micro SD card from the Pinebook Pro and insert it into the Raspberry Pi.

Configure Raspberry Pi 2 model B

  • Connect the Raspberry Pi to a monitor using an HDMI cable
  • Connect USB keyboard to RPI
  • Connect power supply to wall and insert micro USB connector into RPI

It will power on, resize the root file system and boot to a login prompt. The default credentials for login and passord on a new installation of Raspbian are:

  • login: pi
  • password: raspberry

Configure your keyboard and locale as necessary:

$ sudo dpkg-reconfigure keyboard-configuration
$ sudo dpkg-reconfigure console-setup
$ sudo dpkg-reconfigure locales

Although this process does not attach the RPI to a network, it is best practice to change the password:

$ passwd

Once logged in you will have access to a console. A new installation does not configure SPI on the RPI. You can confirm that by listing the contents of the /dev directory and looking for spidev#.# entries:

$ ls /dev

To configure SPI on the RPI run the following tool:

$ sudo raspi-config

A menu will open, select the following:

  • 5 Interfacing options
  • P4 SPI

Then select Yes when asked "Would you like the SPI interface enabled?" You will then get a message that the SPI interface is enabled. You can confirm by running the following command and looking for spidev#.# entries:

$ ls /dev

Now that configuration is complete, poweroff the RPI:

$ systemctl poweroff

Then disconnect the HDMI cable, USB keyboard, and micro USB power cable from the Raspberry Pi to simplify wiring.

Connect Pomona 5250 test clip to Raspberry Pi GPIO and breadboard

The Pomona 5250 test clip provides secure connection to the GD25Q127C SPI NOR flash chip. The test clip could be eliminated by soldering wires directly to the flash chip pins but that introduces risk into the process.

We must provide a separate 3V3 voltage power supply as the Pinebook Pro motherboard will draw more power from the Raspberry Pi 2 model B than it can provide while it is booting and it will send the RPI into a boot loop. A breadboard is used to simplify connecting a separate 3V3 power supply to the Pomona 5250 test clips.

The GD25Q127C SPI NOR flash has an indented circle on the chip that identifies the location of pin 1, it is marked in the pinout below with an asterisk:

     +------------------+
     |*                 |
 CS --- 1            8 --- VCC
     |                  |
 SO --- 2            7 --- HOLD/RESET
     |                  |
 WP --- 3            6 --- SCLCK
     |                  |
VSS --- 4            5 --- SI
     |                  |
     +------------------+

         GD25Q127CSIG

The Raspberry Pi has one bus and two chip selects (CE0,CE1). When SPI is enabled on the Raspberry (process described above) two devices will show up in the /dev directory, spidev0.0 and spidev0.1. The first digit before the period is the bus, the second digit after the period is the chip select. We will be using the first chip select (0) and I omit CE1 in the graphic below to simplify the graphic. We will be connecting a ground from the RPI to the 3v3 power supply through the breadboard, so I have identified one of the GND pins below. The simplified RPI SPI pinout is shown below:

              1 2
            +-----+
            | * * |
            | * * |
            | * * | GND
            | * * |
            | * * |
            | * * |
            | * * |
            | * * |
            | * * |
GPIO10/MOSI | * * |
 GPIO9/MISO | * * |
GPIO11/SCLK | * * | CEO/GPIO8
            | * * |
            | * * |
            | * * |
            | * * |
            | * * |
            | * * |
            | * * |
            | * * |
            +-----+
             39 40

    Raspberry Pi SPI Pinout
     (excluding CE1/GPIO7)

Pin 1 of the Raspberry Pi GPIO header is marked on the bottom PCB silkscreen with a square. If you orient the RPI face up on your work surface (Raspberry Pi logo facing up) and rotate it so the ethernet and USB connectors are towards you, then the GPIO pins of the RPI will be in the same orientation as the graphic above. As shown, Pin 1 is the top left pin when in this orientation.

I found it easiest to make the connections by orienting the test clip, RPI, and breadboard on your work surface in this fashion:

                 Pomona 5250 test clip

       Pin 1 ->  *       *
                 *       *
                 *       *
                 *       *



                             Raspberry Pi
         +------------------------------+
         | ********************  +----+ |
Pin 1 -> | ********************  |    | |
         |                       +----+ |
 +-------+-------------------+   +----+ |
 |           NEG  ***** *****|   |    | |
 |           POS  ***** *****|   +----+ |
 |                           |  +-----+ |
 |                           |  |     | |
 |                           |  |     | |
 |                           |  +-----+ |
 |                           +----------+
 |                           |
 +---------------------------+
 Breadboard

The test clip does not have a Pin 1, it works the same if you rotate it 180 degrees. But I chose that orientation as it was simplest for me to attach the test clip to the PBP later. The pin numbering of the test clip will be the same as that of the SPI NOR flash chip.

Make connect the test clip, RPI, and breadboard using the following table:

Test Clip  Raspberry Pi  Breadboard  Jumper Wire
--------------------------------------------------

 1          24/CE0                   female/female

 2          21/MISO                  female/female

 3 (WP)                   POS        female/male

 4                        NEG        female/male

 5          19/MOSI                  female/female

 6          23/SCLK                  female/female

 7                        POS        female/male

 8                        POS        female/male

            6/GND         NEG        female/male

Double and triple check that you have made the correct connections.

NOTE: Pin 3 of the test clip corresponds to the WP (write protect) pin of the flash chip and it is connected to 3V3 (POS) on the breadboard. Connecting Pin 3 to ground does not prevent the chip from being programmed, as expected. This is most likely due to the WP pin being back powered through the board while attached to the powered test clip.

Connect 3V3 power supply to breadboard

If you are using a 5V/3V3 breadboard power supply similar to the link provided above in the Hardware Requirements section, then it is a simple matter of plugging it into the breadboard, configuring it correctly with the jumpers and then plugging power into the power supply.

I do not own a breadboard power supply but had in the past created a simple bench power supply from an ATX power supply which has a breadboard attached to the top that I can use to power projects with 12V/-12V/5v/3V3. Description of its construction is outside the scope of this document.

Turn on your power supply and measure the output voltage to ensure you are getting the expected 3V3. You can then turn it back off again.

With the power supply turned off. I used two lengths of 22 AWG solid core hook up wire, stripped at both ends, and connected the GND from the power supply to the NEG of the breadboard, and then connected the 3V3 from the power supply to the POS of the breadboard.

Prepare Pinebook Pro for flashing

  • Power down the Pinebook Pro
  • Remove the external power source if attached
  • Remove the bottom magnesium cover following disassembly instructions on the Pine64 PBP wiki
  • Carefully disconnect battery connector from PBP main board
  • Carefully remove the metal EMI shield from the main board using a non-metallic, non-conductive tool (fingernail works for me)

Once the EMI shield is removed, you will find that the SPI flash is clearly marked next to the RESET and RECOVERY buttons.

Connect Pomona test clip to SPI NOR flash chip

It is possible to purchase an imitation Pomona test clip cheaper than the original but reviews are generally negative of them. I can confirm the authentic unit I purchased securely clips to the SPI NOR flash chip.

Open the test clip and carefully clip it to the SPI NOR flash chip. The orientation of the Pin 1 you used for your test clip should match that of flash chip. The chip on my board clearly marks Pin 1 with an indented circle.

Reconnect Raspberry Pi and turn on 3V3 power supply

  • Connect HDMI cable to Raspberry Pi
  • Connect USB keyboard to RPI
  • Connect micro USB power cable to RPI
  • Turn on 3V3 power supply

If you are going to be creating log files or images from ROM and file time stamps are important to you, then set the timezone and time/date:

$ sudo timedatectl set-timezone <TIMEZONE>
$ sudo date --set "YYYY-MM-DD HH:MM:SS"

Mount a flash drive on the RPI using the following:

$ sudo systemd-mount --owner=pi /dev/sda1 /media/sda1

Using Flashrom

The version of flashrom used in this documentation is that installed in the Raspbian Lite distribution as of Sep 2019 which is v1.0-1. The version can be determined by running the following:

$ apt-cache policy flashrom

When reading from or writing to the flash chip it is convenient to transport the image file between the Raspberry Pi and laptop/desktop using a USB flash drive. This is the main reason a version of the Raspberry Pi with multiple USB-A ports is used.

The starting reference for this portion of the document originates from the flashrom website. The flashrom man page was also used as was experimentation to determine the optimal SPI speed used by the flashrom linux_spi driver.

A series of read operations were performed to determine the upper limit of the spispeed parameter to the flashrom linux_spi driver. The frequency is parsed as KHz, and a value of 1000 (1 MHz) was the initial value used. At this value, it reads the full contents of the SPI NOR flash chip in about 2 minutes and 17 seconds. The upper limit was determined to be 41666 (41.6 MHz) which reads the full contents of the SPI NOR flash chip in about 6.5 seconds. Any speed equal to or greater than 41667 and the operation fails with error "no EEPROM/flash device found".

Probe the SPI NOR flash

The probe will fail unless the spispeed parameter is given. In this example I use the mininum 1 KHz:

sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1

The output of this command shows multiple definitions. The definition I will use will be that closest to the installed chip. (-c GD25Q128C)

Read FULL contents of SPI NOR flash ROM to file

The 128Mbit SPI NOR flash on the Pinebook Pro arrives empty from the factory. This was confirmed by using the process described below.

To read the full contents of the GD25Q127C SPI NOR flash, run the following:

$ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=41666 -c GD25Q128C -r output.rom

That will dump the entire flash contents to output.bin. Examining this file should show a file with all bits set to 1, or every byte should show 'f' in hexadecimal:

$ hexdump -C output.rom

Verify FULL contents of ROM against image

$ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=41666 -c GD25Q128C -v output.rom

Write and verify of FULL contents of SPI NOR flash

To create a dummy 16M ROM image to write to the flash, I did this:

dd if=/dev/urandom of=random_16M.rom bs=16777216 count=1 conv=notrunc,fsync

This was then used to write to the SPI NOR flash:

$ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=41666 -c GD25Q128C -w random_16M.rom -o GD25Q127C.write.log

The write operation also verifies the SPI NOR flash rom contents against the image it is given. A separate verification step is not required.

Erase FULL contents of SPI NOR flash

When the SPI NOR flash is erased, it flips every bit to 1 (every byte is an hexadecimal F). To perform the operation:

$ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=41666 -c GD25Q128C -E

Create ROM layout and test ROM image for PARTIAL operations

The size of the partial data image and location within the 16M byte address space was chosen arbitrarily. The test ROM image was created using the following:

$ dd if=/dev/urandom of=random_256B.bin bs=256 count=1 conv=notrunc,fsync
$ dd if=/dev/zero of=zeros_3840B.bin bs=3840 count=1 conv=notrunc,fsync
$ dd if=/dev/zero of=zeros_16773120B.bin bs=16773120 count=1 conv=notrunc,fsync
$ cat zeros_16773120B.bin random_256B.bin zeros_3840B.bin > test.rom

The ROM layout file was created using the following:

$ echo "000000:FFEFFF zeros1" > test.rom.layout
$ echo "FFF000:FFF0FF data" >> test.rom.layout
$ echo "FFF100:FFFFFF zeros2" >> test.rom.layout

Write and verify PARTIAL contents of SPI NOR flash

This writes and verifies just the region requested. The operation is performed using the following:

$ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=41666 -c GD25Q128C -l test.rom.layout -i data -w test.rom

Read PARTIAL contents of SPI NOR flash

The partial read operation creates a file the same size as the SPI NOR flash ROM. It fills the space in the regions of the image not read with zeros. To conduct the partial read, run the following:

$ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=41666 -c GD25Q128C -l test.rom.layout -i data -r output-partial.read.bin

output-partial.read.bin will be an exact copy of the test.rom file that was created. This is demonstrated by:

cmp test.rom output-partial.read.bin

Verify PARTIAL contents of SPI NOR flash

This will verify just the region requested:

$ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=41666 -c GD25Q128C -l test.rom.layout -i data -v test.rom

Erase PARTIAL contents of SPI NOR flash

This will erase the region requested:

$ sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=41666 -c GD25Q128C -l test.rom.layout -i data -E
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment