Fun with e-paper and Arduino using an Adafruit Grand Central M4 and IT9851

Had some fun playing around with an e-paper display this last weekend.  Chose the Adafruit Grand Central M4 (SAM51) because of the large amount of flash and SRAM, but alas it was not enough SRAM to do what I wanted to do.  This is a GDEP097TC2 e-paper display with a parallel interface, hence the use of the IT9851 controller.  This is a really beautiful display at a diagonal size of 9.7″ but a high resolution of 1200W x 825H pixels.  As seen in the pictures below it can display 16 shades of grey.

The IT8951 has the capability of updating very quickly, however we are a little limited with SPI for now.  I plan to get the I80 (parallel interface) working on the IT9851 later, but I don’t have the flat cable and connectors right now to match the I80 interface connector.  I haven’t looked into partial updates, but I believe this is also possible if there is enough SRAM to create an image buffer.  I am hoping to do this after I receive an SDRAM module.

Adruino GDEP097TC2 epaper

Was planning on creating a buffer in SRAM for the display so that the image could be edited then displayed, but due to how the IT9851 accepts data, its 4 bits per pixel (16 shades of grey) or half a byte per pixel.  Calculating this out the display is 1200W x 825H which comes out to 990,000 pixels, and we would need a buffer of 990,000 / 2 = 495,000 bytes.  The Grand Central M4 only has 256k of SRAM.  This is defiantly out, at least for now.  I have an SDRAM module on order that I am going to use to expand the memory available for a later project, listing that below if there is any interest.

https://www.waveshare.com/sdram-board-b.htm

For this the following parts are used:
+ Adafruit Grand Central M4
+ WaveShare 1200×825, 9.7inch E-Ink display HAT for Raspberry Pi
+ 2GB SD card

The Adafruit Grand Central M4 is really handy to have around for various Arduino (or Circuit Python) projects where you don’t want to worry about flash and SRAM limits (most of the time).  I would recommend picking a couple up if you are ordering anything from Adafruit and want a beefy board around to do projects in Arduino or Circuit Python.  I have not tried Circuit Python yet, but it has peaked my interest on a few occasions.

Even though we can’t load the entire image into SRAM, no worry we will work around it for this project.  We have an SD card slot on the Adafruit Grand Central M4 so we are going to use a 2GB SD card to hold the image data for us and send it to the IT8951 as we read it from the SD card.  There is a small buffer of 1200 * 54 = 64800 bytes (57 lines) to speed this up.  I believe the SD card functions are limited to 65k due to the use of a uint16_t in the read function for size.

For whatever reason I can’t figure out why the image I load into the IT8951 is reversed, it could be that the image data is reversed in the BMP file, anyway I did some fancy coding to reverse the pixels of each line as its sent to the IT8951.  This is a little wonky, but works for now.  Maybe I can somehow get the IT8951 to load the memory backwards, but I haven’t investigated too far into the IT8951’s inner workings yet.

The image data is in BMP format and has to be formatted specifically, more detail is on the WaveShare wiki at the following webpage.

https://www.waveshare.com/wiki/9.7inch_e-Paper_HAT

However, we are assuming these images are formatted correctly and we will go ahead and use the provided images and copy them to an SD card.  I would recommend a 2GB SD card, not sure if others will work.  I formatted it to FAT16, not sure if FAT32 will work so I recommend using a FAT16 format.  You could go about and find images, crop them, etc, but I am providing the three that I used for this project in the zip file below.

Let me note that I have not really cleaned up the code for reasons that I might use those function in the future or just didn’t get around to cleaning some parts.  You will find some function are not connected to anything but were used during the development cycle to test things.

m4_GDEP097TC2_hwspi_sd_202102202200.zip

Unzip this above file and place it in your Arduino sketch folder.  You should already have Arduino setup to use the Adafruit M4 Grand Central.  If not, you can review the setup procedure on their website.  The files in the “images_for_sd_card” should be copied to the SD card, then they can be deleted from the Arduino project folder if you wish, they don’t appear to harm anything by leaving them there.  Remember to change your board type to “Adafruit Grand Central M4 (SAM51)” in the tools menu.  There are no extra libraries required.

I first wrote this with the software SPI library, hence it is still present, but switched over to hardware SPI later on, it works much smoother.  The IT9851 supports up to 24Mhz SPI speed, but high speed SPI does not appear to like these long wires, connectors, and other stuff, so its throttled back to 12Mhz, do experiment with it though if you wish.  Also it is purposely not using the default SPI interface to leave it free for other things, the SERCOM6 interface is being used for the SPI interface, it is trivial to change it back by changing the various options in the software_spi.h file as shown below, uncomment only one of these.

//#define USE_SOFTWARE_SPI 1
//#define USE_HARDWARE_SPI_DEFAULT 1
#define USE_HARDWARE_SPI_SERCOM6 1

Now on to the wiring, it is trivial to also find the wiring information in the files software_spi.h and IT8951.h files.  The wiring is listed below, also note the IT8951 board DOES need 5V for power, but the logic is 3.3V.

Arduino digital IO function
6 IT8951 RST
7 IT8951 HRDY
8 IT8951 CS
47 IT8951 MISO
48 IT8951 MOSI
49 IT8951 CLK
5V IT8951 5V
GND IT8951 GND

Do make sure you are connecting to the “digital” pins and not the “analog” pins as I did the first time and couldn’t figure out why it wasn’t working.

That’s about it, connect things up, insert the SD card, load the Arduino code and that should be about it.  Below are some more pictures.

Adruino GDEP097TC2 epaper

Adruino GDEP097TC2 epaper

Adruino GDEP097TC2 epaper

Adruino GDEP097TC2 epaper

Adruino GDEP097TC2 epaper

Adruino GDEP097TC2 epaper

Investigating Blue 125khz RFID tags (from China) bought off Amazon with a Proxmark3

My Proxmark3 RDV40.1 finally arrived yesterday and I have been busy investigating this RFID reader/writer/copier bought off Amazon.  It came bundled with soem blue plastic RFID tags (125khz and 13.56Mhz) and some 125khz RFID cards.  Before the Proxmark3 came I played around with reading and writing some of the included cards but had no way to really verify anything.

Finally I got a hold of a Proxmark3 and it took the better part of yesterday to get it up and going.  This was mostly getting the built from source software working then programming the firmware to the Proxmark3 hardware.

Searching for hours on end about these mysterious tags that I could program with the Chinese copier, read with the Proxmark3, but not program with the Proxmark3 was quite frustrating.  One thing to mention about the strategy here, this works IF you have own or have access to the programmer that programmed the tags.

From internet searching (picture searches are useful) for these blue tags I ran across some possible candidates for them.  I found mentions of TK4100, EM4100, EM4305, T5577 and EM4305

While looking around these two posts provided a wealth of information of where to get started in figuring out the password how how to program the blue tags.
http://www.proxmark.org/forum/viewtopic.php?id=6388
http://www.proxmark.org/forum/viewtopic.php?id=6245

I few lessons learned, these blue 125khz tags do not have the best of antennas in them, even if they can be read, writing data is a whole different story.  These tags are powered from the magnetic field generated by the reader/writer and if not enough power can be drawn from the electromagnetic field the writes will fail.  They need to be positioned in the “sweet spot” of the Proxmark3 to be written to correctly, or attach an antenna with higher gain.

This is the proxmark3 client source that I am using, commands will be slightly different with a different version.

https://github.com/RfidResearchGroup/proxmark3

After some investigation it is not uncommon for these copiers from China to put passwords on the tags they copy.  Once the tag has a password it can not be reprogrammed without that password.  Good thing for us that this data is not encrypted and we can just sniff it with the Proxmark3 and read off the password.

The Proxmark3 client has a brute force script that tries common passwords, but lets go through the sniffing method.

First we are going to read the tag and see what additional data is returned.

Startup the Proxmark3 software, this is the version output from what I am using for reference.

[=] Session log /Users/user/.proxmark3/logs/log_20210219.txt
[+] loaded from JSON file /Users/user/.proxmark3/preferences.json
[=] Using UART port /dev/tty.usbmodemiceman1
[=] Communicating with PM3 over USB-CDC


  ██████╗ ███╗   ███╗█████╗ 
  ██╔══██╗████╗ ████║╚═══██╗
  ██████╔╝██╔████╔██║ ████╔╝
  ██╔═══╝ ██║╚██╔╝██║ ╚══██╗
  ██║     ██║ ╚═╝ ██║█████╔╝       Iceman ☕
  ╚═╝     ╚═╝     ╚═╝╚════╝    ❄️ bleeding edge

  https://github.com/rfidresearchgroup/proxmark3/


 [ Proxmark3 RFID instrument ]

 [ CLIENT ]
  client: RRG/Iceman/master/v4.9237-3016-gf6bca6e3a 2021-02-06 18:19:42
  compiled with Clang/LLVM Apple LLVM 12.0.0 (clang-1200.0.32.28) OS:OSX ARCH:x86_64

 [ PROXMARK3 ]
  firmware.................. PM3RDV4
  external flash............ present
  smartcard reader.......... present
  FPC USART for BT add-on... absent

 [ ARM ]
  bootrom: RRG/Iceman/master/release (git) 
       os: RRG/Iceman/master/v4.9237-3016-gf6bca6e3a 2021-02-06 18:20:33
  compiled with GCC 10.2.1 20201103 (release)

 [ FPGA ] 
  LF image built for 2s30vq100 on 2020-07-08 at 23: 8: 7
  HF image built for 2s30vq100 on 2020-07-08 at 23: 8:19
  HF FeliCa image built for 2s30vq100 on 2020-07-08 at 23: 8:30

 [ Hardware ]
  --= uC: AT91SAM7S512 Rev A
  --= Embedded Processor: ARM7TDMI
  --= Nonvolatile Program Memory Size: 512K bytes, Used: 310789 bytes (59%) Free: 213499 bytes (41%)
  --= Second Nonvolatile Program Memory Size: None
  --= Internal SRAM Size: 64K bytes
  --= Architecture Identifier: AT91SAM7Sxx Series
  --= Nonvolatile Program Memory Type: Embedded Flash Memory

I previously copied an HID 125khz card using the copier from China, and now I am going to read that card and attempt to erase/write it.  First of all here is the output from the LF search.

[usb] pm3 --> lf search

[=] NOTE: some demods output possible binary
[=] if it finds something that looks like a tag
[=] False Positives ARE possible
[=] 
[=] Checking for known tags...
[=] 
[+] [H10301] - HID H10301 26-bit;  FC: 118  CN: 16038    parity: valid
[=] raw: 000000000000002006ec7d4c

[+] Valid HID Prox ID found!

[+] Chipset detection: T55xx
[?] Hint: try `lf t55xx` commands
[usb] pm3 --> 

We notice it detected a T55xx chip, which gives us a hint of what kind of chip is in this card, so lets try to dump the card.

[usb] pm3 --> lf t55xx dump
[+] Reading Page 0:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[+]  00 | 80000000 | .0000000000000000000000000000000 | ....
[+]  01 | 80000000 | .0000000000000000000000000000000 | ....
[+]  02 | 80000000 | .0000000000000000000000000000000 | ....
[+]  03 | 80000000 | .0000000000000000000000000000000 | ....
[+]  04 | 80000000 | .0000000000000000000000000000000 | ....
[+]  05 | 80000000 | .0000000000000000000000000000000 | ....
[+]  06 | 80000000 | .0000000000000000000000000000000 | ....
[+]  07 | 80000000 | .0000000000000000000000000000000 | ....
[+] Reading Page 1:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[+]  00 | 80000000 | .0000000000000000000000000000000 | ....
[+]  01 | 80000000 | .0000000000000000000000000000000 | ....
[+]  02 | 80000000 | .0000000000000000000000000000000 | ....
[+]  03 | 80000000 | .0000000000000000000000000000000 | ....
[+] saved to json file lf-t55xx-80000000-80000000-80000000-80000000-80000000-80000000-80000000-dump.json
[+] saved 12 blocks to text file lf-t55xx-80000000-80000000-80000000-80000000-80000000-80000000-80000000-dump.eml
[+] saved 48 bytes to binary file lf-t55xx-80000000-80000000-80000000-80000000-80000000-80000000-80000000-dump.bin
[usb] pm3 --> 

We aren’t getting any data from the chip but retrying the LF search command we know there is data on it.  We won’t be able to dump the chip if there is a password on it.  Let’s try to figure out what password the reader put on the tag.  To do this we can capture the data being sent from the Chinese copier.  Here is how to set it up and do the capture.

[usb] pm3 --> lf config --trig 64 --dec 2 --bps 64

[#] LF Sampling config
[#]   [q] divisor.............95 ( 125.00 kHz )
[#]   [b] bits per sample.....8
[#]   [d] decimation..........2
[#]   [a] averaging...........No
[#]   [t] trigger threshold...64
[#]   [s] samples to skip.....0 
[#] LF Sampling Stack
[#]   Max stack usage.........4232 / 8480 bytes
[usb] pm3 --> lf snif

This will setup the Proxmark3 to capture the data coming from the Chinese copier. Read the chip that we want to unlock using the Chinese copier and then “write” it into the Proxmark3 (as of the Proxmark3 is a chip). The Proxmark3 should capture the write attempt and return the prompt, then execute the following two commands and a waveform should appear, we are going to decipher this waveform bit by bit.

[usb] pm3 --> data samples
[usb] pm3 --> data plot

Proxmark3 T55xx password waveform

This is the password that the Chinese copier is trying to set, all we have to do is decipher the bits.  Apply a filter on the waveform above as shown below to help with visualization.

Proxmark3 T55xx password waveform

Our waveform should have some red lines over it which make it easier to read now.

Proxmark3 T55xx password waveform

Now we just read off the bits off according to the protocol (which I don’t have handy at the moment).

Proxmark3 T55xx password waveform

Here is a decode of the bits.

bits byte description
1100 password OP code
0001 1001 0x19 password byte
1001 0010 0x92 password byte
0000 0100 0x04 password byte
0010 0111 0x27 password byte
111 trailing bits

Our password is therefore 0x19920427.  Lets try again to dump the chip with the correct password. First run lf search so the Proxmark3 sets configures for the card, we can also manually configure with lf t55xx config if we know the parameters.

[usb] pm3 --> lf search

[=] NOTE: some demods output possible binary
[=] if it finds something that looks like a tag
[=] False Positives ARE possible
[=] 
[=] Checking for known tags...
[=] 
[+] [H10301] - HID H10301 26-bit;  FC: 118  CN: 16038    parity: valid
[=] raw: 000000000000002006ec7d4c

[+] Valid HID Prox ID found!

[+] Chipset detection: T55xx
[?] Hint: try `lf t55xx` commands
[usb] pm3 --> lf t55 detect -p19920427
[=]      Chip Type      : T55x7
[=]      Modulation     : FSK2a
[=]      Bit Rate       : 4 - RF/50
[=]      Inverted       : Yes
[=]      Offset         : 33
[=]      Seq. Term.     : No
[=]      Block0         : 0x00107070 (Auto detect)
[=]      Downlink Mode  : default/fixed bit length
[=]      Password Set   : Yes
[=]      Password       : 19920427

We see the chip, and the password is correct as it responds.  We found a T55x7 chip (actually a T5577 chip in in this tag). The chip is in an emulation mode for HID 125khz now so its modulation and such has been changed to match the chip it copied.  Let’s attempt to dump its data.

[usb] pm3 --> lf t55xx dump p 19920427
[+] Reading Page 0:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[+] Reading Page 1:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.
[!] ⚠️  Safety check: Could not detect if PWD bit is set in config block. Exits.

We are getting a safety check to make sure we know what we are doing. Attempting to use a password on a card that does not have one set can damage it hence the warning. We know the password is correct and we can dump the card (at your own risk) since we are going to override this warning.

[usb] pm3 --> lf t55xx dump p 19920427 o
[+] Reading Page 0:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[=] Safety check overridden - proceeding despite risk
[+]  00 | 00107070 | 00000000000100000111000001110000 | ..pp
[+]  01 | EAAACAAA | 11101010101010101100101010101010 | ....
[+]  02 | AB4D4D2B | 10101011010011010100110100101011 | .MM+
[+]  03 | 55332D28 | 01010101001100110010110100101000 | U3-(
[+]  04 | 00000000 | 00000000000000000000000000000000 | ....
[+]  05 | 00000000 | 00000000000000000000000000000000 | ....
[+]  06 | 00000000 | 00000000000000000000000000000000 | ....
[+]  07 | 19920427 | 00011001100100100000010000100111 | ...'
[+] Reading Page 1:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[+]  00 | 00107070 | 00000000000100000111000001110000 | ..pp
[+]  01 | E01500D0 | 11100000000101010000000011010000 | ....
[+]  02 | 3075F62B | 00110000011101011111011000101011 | 0u.+
[+]  03 | 00A00003 | 00000000101000000000000000000011 | ....
[+] saved to json file lf-t55xx-EAAACAAA-AB4D4D2B-55332D28-dump.json
[+] saved 12 blocks to text file lf-t55xx-EAAACAAA-AB4D4D2B-55332D28-dump.eml
[+] saved 48 bytes to binary file lf-t55xx-EAAACAAA-AB4D4D2B-55332D28-dump.bin

Here is our dump. Next let’s try to erase the card (to clear the password also). There are password set/clear commands, but if you just want to recover card so it can be used on another reader it is easy to just wipe it.

Lets first search for the card, then attempt to erase it, then try to search for it again. If we erased it it should not return any data.

[usb] pm3 --> lf search

[=] NOTE: some demods output possible binary
[=] if it finds something that looks like a tag
[=] False Positives ARE possible
[=] 
[=] Checking for known tags...
[=] 
[+] [H10301] - HID H10301 26-bit;  FC: 118  CN: 16038    parity: valid
[=] raw: 000000000000002006ec7d4c

[+] Valid HID Prox ID found!

[+] Chipset detection: T55xx
[?] Hint: try `lf t55xx` commands
[usb] pm3 --> lf t55xx wipe
[=] Target T55x7 tag
[=] Default configuration block 000880E0

[=] Begin wiping...
[=] Writing page 0  block: 00  data: 0x000880E0 
[=] Writing page 0  block: 01  data: 0x00000000 
[=] Writing page 0  block: 02  data: 0x00000000 
[=] Writing page 0  block: 03  data: 0x00000000 
[=] Writing page 0  block: 04  data: 0x00000000 
[=] Writing page 0  block: 05  data: 0x00000000 
[=] Writing page 0  block: 06  data: 0x00000000 
[=] Writing page 0  block: 07  data: 0x00000000 
[usb] pm3 --> lf search

[=] NOTE: some demods output possible binary
[=] if it finds something that looks like a tag
[=] False Positives ARE possible
[=] 
[=] Checking for known tags...
[=] 
[+] [H10301] - HID H10301 26-bit;  FC: 118  CN: 16038    parity: valid
[=] raw: 000000000000002006ec7d4c

[+] Valid HID Prox ID found!

[+] Chipset detection: T55xx
[?] Hint: try `lf t55xx` commands

It appears the wipe command didn’t work, this is because there is a password set, we need the password to change data on the card, let’s try again with the password.

[usb] pm3 --> lf search

[=] NOTE: some demods output possible binary
[=] if it finds something that looks like a tag
[=] False Positives ARE possible
[=] 
[=] Checking for known tags...
[=] 
[+] [H10301] - HID H10301 26-bit;  FC: 118  CN: 16038    parity: valid
[=] raw: 000000000000002006ec7d4c

[+] Valid HID Prox ID found!

[+] Chipset detection: T55xx
[?] Hint: try `lf t55xx` commands
[usb] pm3 --> lf t55xx wipe -p 19920427
[=] Target T55x7 tag
[=] Using password 19920427
[=] Default configuration block 000880E0

[=] Begin wiping...
[=] Writing page 0  block: 00  data: 0x000880E0 pwd: 0x19920427
[=] Writing page 0  block: 01  data: 0x00000000 
[=] Writing page 0  block: 02  data: 0x00000000 
[=] Writing page 0  block: 03  data: 0x00000000 
[=] Writing page 0  block: 04  data: 0x00000000 
[=] Writing page 0  block: 05  data: 0x00000000 
[=] Writing page 0  block: 06  data: 0x00000000 
[=] Writing page 0  block: 07  data: 0x00000000 
[usb] pm3 --> lf search

[=] NOTE: some demods output possible binary
[=] if it finds something that looks like a tag
[=] False Positives ARE possible
[=] 
[=] Checking for known tags...
[=] 
[-] ⛔ No known 125/134 kHz tags found!
[+] Chipset detection: T55xx
[?] Hint: try `lf t55xx` commands

It looks like we change something on the card. Assuming the card is now wiped, lets try to detect it again then dump its contents (without the password).

[usb] pm3 --> lf t55xx detect
[=]      Chip Type      : T55x7
[=]      Modulation     : ASK
[=]      Bit Rate       : 2 - RF/32
[=]      Inverted       : No
[=]      Offset         : 33
[=]      Seq. Term.     : Yes
[=]      Block0         : 0x000880E0 (Auto detect)
[=]      Downlink Mode  : default/fixed bit length
[=]      Password Set   : No

[usb] pm3 --> lf t55xx dump
[+] Reading Page 0:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[+]  00 | 000880E0 | 00000000000010001000000011100000 | ....
[+]  01 | 00000000 | 00000000000000000000000000000000 | ....
[+]  02 | 00000000 | 00000000000000000000000000000000 | ....
[+]  03 | 00000000 | 00000000000000000000000000000000 | ....
[+]  04 | 00000000 | 00000000000000000000000000000000 | ....
[+]  05 | 00000000 | 00000000000000000000000000000000 | ....
[+]  06 | 00000000 | 00000000000000000000000000000000 | ....
[+]  07 | 00000000 | 00000000000000000000000000000000 | ....
[+] Reading Page 1:
[+] blk | hex data | binary                           | ascii
[+] ----+----------+----------------------------------+-------
[+]  00 | 000880E0 | 00000000000010001000000011100000 | ....
[+]  01 | E01500D0 | 11100000000101010000000011010000 | ....
[+]  02 | 3075F62B | 00110000011101011111011000101011 | 0u.+
[+]  03 | 00A00003 | 00000000101000000000000000000011 | ....
[+] saved to json file lf-t55xx-dump.json
[+] saved 12 blocks to text file lf-t55xx-dump.eml
[+] saved 48 bytes to binary file lf-t55xx-dump.bin

Looks like the card is now blank (without a password) so we are free to use it as we please. Notice the modulation is also now default, hence why we needed to run detect first before the dump so the Proxmark3 knows which modulation to use. These programmable chips (like the T55x7 or EM4x05 series chips) are special in a way in that they can emulate a number of modulations depending on which card it is emulating. Not all chips can be programmed or reprogrammed.

One other method I would like to discuss is a slightly faster method that can be tried to recover the password. This method only worked because we have the device that set the password in our hands and we could examine the password it is sending with the Proxmark3. The Promark3 can also brute force the password which can take a while, however, a lot of these Chinese copier’s passwords are well known and common so the Proxmark3 has a script that will try all the common known passwords. Here is how that works below, it so happens this Chinese copier uses one of the well knows passwords.

I again copied the card with the Chinese copier, then tried the brute force method below.

[usb] pm3 --> lf search

[=] NOTE: some demods output possible binary
[=] if it finds something that looks like a tag
[=] False Positives ARE possible
[=] 
[=] Checking for known tags...
[=] 
[+] [H10301] - HID H10301 26-bit;  FC: 118  CN: 16038    parity: valid
[=] raw: 000000000000002006ec7d4c

[+] Valid HID Prox ID found!

[+] Chipset detection: T55xx
[?] Hint: try `lf t55xx` commands
[usb] pm3 --> lf t55xx chk
[=] press 'enter' to cancel the command

[+] loaded 112 keys from dictionary file /Users/user/Documents/dev_proxmark3/repo/proxmark3/client/dictionaries/t55xx_default_pwds.dic
[=] press 'enter' to cancel the command
[=] testing 51243648
[=] testing 000D8787
[=] testing 19920427
[=]      Chip Type      : T55x7
[=]      Modulation     : FSK2a
[=]      Bit Rate       : 4 - RF/50
[=]      Inverted       : Yes
[=]      Offset         : 33
[=]      Seq. Term.     : No
[=]      Block0         : 0x00107070 (Auto detect)
[=]      Downlink Mode  : default/fixed bit length
[=]      Password Set   : Yes
[=]      Password       : 19920427

[+] found valid password: [ 19920427 ]

[+] time in check pwd 1 seconds

We were able to find the password easily with just trying common passwords with the “lf t55xx chk” command. Since we know the password we can go ahead and dump or wipe the card as shown above.

Hope this has been helpful to recover passwords set from an RFID copier.

Reading FeliCa RFID with a RC-S620S and Arduino

FeliCa reader project

After some more playing around with RFID tags and trying to read some FeliCa tags with the Proxmark3 it was obvious I needed a reader designed for FeliCa.  FeliCa was designed by SONY and has a very long history of usage starting in the 1990’s and beginning wide use in 2001 with the SUICA prepaid rail card.  It is similar to a ISO/IEC 14443, and is closer to a ISO/IEC 18092 (Near Field Communication, NFC TYPE-F) in its communications but its specification actually follows specification JIS: X6319-4.

The card offers very high level encryption and security, I have not seen a single instance of it being hacked even after all these years (yet).

To read the card and get the card id, called the IDm, I found a RC-S620S FeliCa reader at the local shop and searched around to see if anyone had attempted to connect it up to an Arduino platform.  Not suppressing I found some information on this site below with some sample Arduino code.

https://deviceplus.jp/hobby/entry_f02/

With this information I used the Arduino platform to successfully retrieve the IDm from various FeliCa cards in my possession.  After this, I found out that it is not that difficult to retrieve the current balance of the electronic money on the card as well after running across the following below site.  FeliCa is very commonly used in Japan and this can retrieve the unique 8 byte card id (IDm) and balance information for Suica, Icoca, PiTaPa, nanao, edy, and others.

https://www.orsx.net/archives/3835

I then proceeded to create a reader with an OLED display to display the IDm of the card along with the remaining electronic money balance.  This uses an Arduino Feather M0 basic along with a 128×64 OLED display to show the results.  Surprisingly, SONY released an Arduino library for the RC-S620S, which is still up on their website for download, but needs a few fixes since it is from so many years back (2000).

http://blog.felicalauncher.com/sdk_for_air/?page_id=2699

Download the above library and place it in the Arduino “libraries” folder.  In the file “RCS620S.cpp” the following changes need to be made.

Line Search for Replace with
10 #include “Wprogram.h” #include “Arduino.h”
312 Serial.write(data, len); Serial1.write(data, len);
327 if (Serial.available() > 0) { if (Serial1.available() > 0) {
328 data[nread] = Serial.read(); data[nread] = Serial1.read();
338 Serial.flush(); Serial1.flush();

The following hardware items were used in this project:

Adafruit Feather M0 Basic Proto – ATSAMD21 Cortex M0
+ https://www.adafruit.com/product/2772
Adafruit FeatherWing OLED – 128×64 OLED Add-on For Feather
+ https://www.adafruit.com/product/4650
FeatherWing Tripler Mini Kit – Prototyping Add-on For Feathers
+ https://www.adafruit.com/product/3417
NFC FeliCa Reader/Writer Module RC-S620/S
+ https://international.switch-science.com/catalog/353/
FeliCa RC-S620/S and FeliCa Link RC-S730 pitch converter board set (with flat cable)
+ https://international.switch-science.com/catalog/1029/

Here is the pinout of the RC-S602S.  It can work on either 3.3V or 5.0V.  Connect to the “uart1” of the Arduino device being used.  In the case of the Adafruit Feather m0 Basic this is D0 (UART1 RX) and D1 (UART1 TD).  There are two grounds, connect them both to ground.  The RC-S620S can be powered by 5.0v or 3.3v.  An Arduino Uno would work, but it has only one hardware UART, the softserial won’t be able to keep up with the 115200 BAUD of the RC-S620S.  I believe the limit for the softserial is around 9600 or 19200.

Connect the flat cable as shown here in the picture.

RC-S620S flat cable

RC-S620S

RC-S620S pinout

pin color description
1 red VCC (5v or 3.3v)
2 green RXD
3 white TXD
4 black GND
5 n/c do not connect, reserved
6 black GND

A version with the OLED display functions is in the below ZIP file, it is rather big to copy paste here.  Credit for the parts that I copy pasted is these two sources below.

https://deviceplus.jp/hobby/entry_f02/
https://www.orsx.net/archives/3835

https://www.drassal.net/filestore/m0_felica_oled_20210209.zip

The following code is a very simple serial only version that can be pasted.  A zip fie is also available to download.

https://www.drassal.net/filestore/m0_felica_uart_20210209.zip

#include <RCS620S.h>

#define COMMAND_TIMEOUT               400
#define POLLING_INTERVAL              500
#define RCS620S_MAX_CARD_RESPONSE_LEN 30

// FeliCa Service/System Code
#define CYBERNE_SYSTEM_CODE           0x0003
#define COMMON_SYSTEM_CODE            0xFE00
#define PASSNET_SERVICE_CODE          0x090F
#define EDY_SERVICE_CODE              0x170F
#define NANACO_SERVICE_CODE           0x564F
#define WAON_SERVICE_CODE             0x680B

RCS620S rcs620s;

// UNO
#define SERIAL_DEBUG Serial
// Due
// #define SERIAL_DEBUG SerialUSB

void setup() {
  int ret;
  while (!Serial && millis() < 10000);
  Serial.begin(115200);
  Serial.println("Serial init done!");

  // RC-S620Sの初期化
  Serial1.begin(115200);
  Serial.println("Serial1 init done!");
  ret = rcs620s.initDevice();
  while (!ret) {}
  rcs620s.timeout = COMMAND_TIMEOUT;
  Serial.println("RC-S620S init ok");
}

void polling(void) {
  int ret;
  char temp[3];
  char cardid[17];

  // FeliCaのタッチ状態を得る
  ret = rcs620s.polling();

  // FeliCaがタッチされた場合
  if(ret) {
    // IDmを取得する
    for(int i = 0; i < 8; i++){
      sprintf(temp, "%02X", rcs620s.idm[i]);
      cardid[i * 2] = temp[0];
      cardid[(i * 2) + 1] = temp[1];
    }
    cardid[16] = 0;

    printId(cardid);
  }
  
  rcs620s.rfOff();
}

void polling_balance(void) {
  char temp[3];
  char cardid[17];
  uint32_t balance;
  uint8_t buf[RCS620S_MAX_CARD_RESPONSE_LEN];
   
  rcs620s.timeout = COMMAND_TIMEOUT;
   
  // サイバネ領域
  if(rcs620s.polling(CYBERNE_SYSTEM_CODE)){
    // Suica PASMO
    if(requestService(PASSNET_SERVICE_CODE)){
      if(readEncryption(PASSNET_SERVICE_CODE, 0, buf)){
        // Little Endianで入っているPASSNETの残高を取り出す
        balance = buf[23];                  // 11 byte目
        balance = (balance << 8) + buf[22]; // 10 byte目

        // IDmを取得する
        for(int i = 0; i < 8; i++){
          sprintf(temp, "%02X", rcs620s.idm[i]);
          cardid[i * 2] = temp[0];
          cardid[(i * 2) + 1] = temp[1];
        }
        cardid[16] = 0;

        // 残高表示
        printBalance(cardid, "PASSNET", &balance);
      }
    }
  }
   
  // 共通領域
  else if(rcs620s.polling(COMMON_SYSTEM_CODE)){
    // Edy
    if(requestService(EDY_SERVICE_CODE)){
      if(readEncryption(EDY_SERVICE_CODE, 0, buf)){
        // Big Endianで入っているEdyの残高を取り出す
        balance = buf[26];                  // 14 byte目
        balance = (balance << 8) + buf[27]; // 15 byte目

        // IDmを取得する
        for(int i = 0; i < 8; i++){
          sprintf(temp, "%02X", rcs620s.idm[i]);
          cardid[i * 2] = temp[0];
          cardid[(i * 2) + 1] = temp[1];
        }
        cardid[16] = 0;

        // 残高表示
        printBalance(cardid, "Edy", &balance);
      }
    }
     
    // nanaco
    else if(requestService(NANACO_SERVICE_CODE)){
      if(readEncryption(NANACO_SERVICE_CODE, 0, buf)){
        // Big Endianで入っているNanacoの残高を取り出す
        balance = buf[17];                  // 5 byte目
        balance = (balance << 8) + buf[18]; // 6 byte目
        balance = (balance << 8) + buf[19]; // 7 byte目
        balance = (balance << 8) + buf[20]; // 8 byte目

        // IDmを取得する
        for(int i = 0; i < 8; i++){
          sprintf(temp, "%02X", rcs620s.idm[i]);
          cardid[i * 2] = temp[0];
          cardid[(i * 2) + 1] = temp[1];
        }
        cardid[16] = 0;
        
        // 残高表示
        printBalance(cardid, "nanaco", &balance);
      }
    }
     
    // waon
    else if(requestService(WAON_SERVICE_CODE)){
      if(readEncryption(WAON_SERVICE_CODE, 1, buf)){
        // Big Endianで入っているWaonの残高を取り出す
        balance = buf[17];                  // 21 byte目
        balance = (balance << 8) + buf[18]; // 22 byte目
        balance = (balance << 8) + buf[19]; // 23 byte目 balance = balance & 0x7FFFE0; // 残高18bit分のみ論理積で取り出す balance = balance >> 5;             // 5bit分ビットシフト

        // IDmを取得する
        for(int i = 0; i < 8; i++){ sprintf(temp, "%02X", rcs620s.idm[i]); cardid[i * 2] = temp[0]; cardid[(i * 2) + 1] = temp[1]; } cardid[16] = 0; // 残高表示 printBalance(cardid, "waon", &balance); } } } rcs620s.rfOff(); } // request service int requestService(uint16_t serviceCode){ int ret; uint8_t buf[RCS620S_MAX_CARD_RESPONSE_LEN]; uint8_t responseLen = 0; buf[0] = 0x02; memcpy(buf + 1, rcs620s.idm, 8); buf[9] = 0x01; buf[10] = (uint8_t)((serviceCode >> 0) & 0xff);
  buf[11] = (uint8_t)((serviceCode >> 8) & 0xff);
 
  ret = rcs620s.cardCommand(buf, 12, buf, &responseLen);
   
  if(!ret || (responseLen != 12) || (buf[0] != 0x03) ||
      (memcmp(buf + 1, rcs620s.idm, 8) != 0) || ((buf[10] == 0xff) && (buf[11] == 0xff))) {
    return 0;
  }
 
  return 1;
}
 
int readEncryption(uint16_t serviceCode, uint8_t blockNumber, uint8_t *buf){
  int ret;
  uint8_t responseLen = 0;
   
  buf[0] = 0x06;
  memcpy(buf + 1, rcs620s.idm, 8);
  buf[9] = 0x01; // サービス数
  buf[10] = (uint8_t)((serviceCode >> 0) & 0xff);
  buf[11] = (uint8_t)((serviceCode >> 8) & 0xff);
  buf[12] = 0x01; // ブロック数
  buf[13] = 0x80;
  buf[14] = blockNumber;
 
  ret = rcs620s.cardCommand(buf, 15, buf, &responseLen);
 
  if (!ret || (responseLen != 28) || (buf[0] != 0x07) ||
      (memcmp(buf + 1, rcs620s.idm, 8) != 0)) {
    return 0;
  }
 
  return 1;
}

void printId(char *card_id){
  Serial.print("IDm      : ");
  Serial.println(card_id);
  return;
}

void printBalance(char *card_id, char *service_name, uint32_t *balance){
  char result[8];
  Serial.print("IDm      : ");
  Serial.println(card_id);

  Serial.print(" SERVICE : ");
  sprintf(result, "%u", *balance);
  Serial.println(service_name);
  
  Serial.print(" BALANCE : ");
  Serial.println(result);
  
  return;
}

void loop() {
  // put your main code here, to run repeatedly:
  //polling();
  polling_balance();
  delay(POLLING_INTERVAL);
}

RFID development with a Proxmark3 RDV4.01 – first time use on MacOs

As I am occasionally doing more and more RFID related tasks at work, and curious about the data stored on all these RFID devices that I see more and more I got ahold of a Proxmark3 RDV 4.01 to gain more insight to RFID and help out with development.

Running on MacOS am completely new to the Proxmark3, take that back, about 10 years ago I got a Proxmark3 but at the time RFID was not as wide spread and never got a change to get a lot of use out of it.  Fast forward, what really peaked my interest is the use of RFID in some interesting products such as the recently released Savi’s Workshop Handbuilt Star Wars Lightsabers at Hollywood Studios Disney World.  It is easy to find information on YouTube or search engines about the RFID use in these cool new items.

Anyway, opening up the (really nice) case, this is what the inside looks like.

Proxmark3 RDV 4.01

Proxmark3 RDV 4.01

 

It looks like I am being forced to use “brew” to do this, I am not a fan of brew because I don’t know where it is putting files and want to keep my laptop clean.  I already wiped the laptop last month to git rid of a lot of “garbage” installed by things like brew.  I created a throw away account on the laptop and going to use it to do the things that require brew.  I just finished setting up brew and wrote up the below post as I was doing it.

https://www.drassal.net/wp/index.php/2021/02/05/installing-macos-brew-without-sudo

I am following this guide to setup the proxmark3 software, and after setting up brew, it was actually quite straight forward.

Based on this guide
https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md

After entering the terminal, and setting up your path for brew (if necessary) running the following three commands should get everything automatically setup, it will take a while to download and compile so grab a drink or coffee while waiting.

brew tap RfidResearchGroup/proxmark3

If you have don’t have the “Blue Shark” accessory run this command next.
brew install proxmark3

If you do have the “Blue Shark” accessory run this command.
brew install –with-blueshark proxmark3

Go grab a drink or coffee while it runs and hopefully there are no errors.  Once this is done use the below command to update the the proxmark3 hardware.  Hold the button as the USB is connected, if the LEDs turn off when the button is released the bootloader is old, repeat the process but hold the button down through the whole bootloader update process.

pm3-flash-all

In my case I got this error message
[!!] 🚨 ====================== OBS ! ===========================================
[!!] 🚨 Note: Your bootloader does not understand the new CMD_BL_VERSION command
[!!] 🚨 It is recommended that you first update your bootloader alone,
[!!] 🚨 reboot the Proxmark3 then only update the main firmware

So, according to the guide I ran the command for updating the bootloader only.

proxmark3 /dev/tty.usbmodemiceman1 –flash –unlock-bootloader –image ~/usr/local/share/proxmark3/firmware/bootrom.elf

After it completes release the USB button, put the proxmark3 back into bootloader mode by holding the button while plugging in the USB, this time two LEDs should stay lit after releasing the button.

Proceed to update the main firmware by the following command
proxmark3 /dev/tty.usbmodemiceman1 –flash –unlock-bootloader –image ~/usr/local/share/proxmark3/firmware/fullimage.elf

Note, “fullimage.elf” refers to the main application image, not including the bootloader, confusing, but this is how the proxmark3 does it.

After this is done just to be sure you are on the right firmware version reconnect the USB without holding down the button then run the following command to enter the client.

pm3

Enjoy playing with the proxmark3!
I’ll be posting some things later about the proxmark3 as I have time to test things out with it.

Installing MacOs brew without sudo

In trying to setup the proxmark3 environment I ran into a frustrating problem, it was setup to be installed with brew… oh no.

My current MacOs version is MacOs BigSur 11.1, so this works with that version, Intel anyway, I don’t have an Apple silicon machine to test with, but it could require some tweaks to work.

I have used brew before and I have always had issues with how it works and where it puts files, and the way that the brew developers were uploading analytics was kinda sneaky as in this post.

https://news.ycombinator.com/item?id=11566720

Yeah this is a while ago, but, how the dev team of brew, being open source and all appealing to developers and the open source community would be a little sneaky about this was not cool.  Not to drag on this topic, but I really don’t think brew needs sudo access to my whole computer, just last month I completly wiped and reinstalled MacOs (latest version too) to rid myself of all the development “junk” that I just allowed to be installed anywhere… yeah development software will turn your computer into a trash can of random files and junk eventually if you don’t carefully watch it.

According to brew itself it says it does not require sudo, but it STILL wants sudo access to install… meh.

https://superuser.com/questions/655113/understanding-homebrew-no-sudo-philosophy-and-questioning-faq

Anyway, being forced into a corner to install brew to install the proxmark3 development tools I decided I would play it safe, I created a new non-admin user account called “proxmark3” to play it safe, and installed brew on that account without sudo with the following script, I had to modify it slightly though which I will explain here.  Original is below.

https://gist.github.com/skyl/36563a5be809e54dc139

I have zipped it up and archived it incase it disappears or changes.  I haven’t tested all possible setups, so you might need to install XCode or other support files before this will work correctly too.

https://www.drassal.net/filestore/brew_without_sudo_20210205.zip

You will notice I blew away a couple if conditions, for some reason it was not detecting the macos version correctly so I just chose for it and deleted the if statements that checked for the macos version.  It will put the executeables under your hold folder in /home/proxmark3/usr, etc.  For some reason the create directory fails so just make them yourself if you get an error.

Also, with how I tweaked the script it defaults to /home/prosmark3 for the home directory, edit as necessary.  Set the execute permission using

mkdir /user/proxmark3/usr
mkdir /user/proxmark3/usr/local
chmod u+x install.rb
./install.rb

After installation is done run the following command to get everything up to date.  We also need to set the path.  Remember to either set the path each time you open a terminal and want to use brew things, or put it somewhere to auto execute each time terminal opens.  I couldn’t get .bash_profile to work for me.

PATH=”$PATH:/Users/proxmark3/usr/local/bin”
brew doctor

This will take a while to run, after it finishes enjoy running brew without sudo!!!

Back to playing with the proxmark3!

nRF9160 ESP32-CAM JPEG image uploader through LTE

This is a guide in progress and is no where near complete, but did want to get some initial information and links to the project files up while I work on the rest of the guide.

Have been working on a few project involving the nRF9160 lately and am trying to get support added into TinyGSM for the nRF9160, there is a discussion over here that I started for that at the address below.

https://github.com/vshymanskyy/TinyGSM/issues/486

Feel free to join in and help out of you have interest in using TinyGSM with the nRF9160.

This project uses an ESP32-CAM development board to take pictures and use the Feather nRF9160 to upload the JPEG images to a server through a form post to a PHP script.  The images can then be immediately viewed in a web browser.

Also this project will also need a SIM card that will allow it to connect to an LTE network.  These JPEG images can be up to 10k in size and will easily eat through a SIM card that does not have enough data.  I just bought a prepaid data only LTE SIM card at a local shop and it works fine, but the LTE network you are connecting to needs to have either NB-IoT or LTE-M support.  It is possible to “borrow” the SIM card from your cell phone too.

Also you will need to know the SIM card’s APN information, if the nRF9160 does not automatically figure it out.  For the few SIM cards I have been working with I have had to manually specify the APN information and sometimes authentication information as well.  More on that later.

esp32_nrf9160_camera_http

A note about the ESP32-CAM, so far I have run into one that was a little glitchy, it would be unstable and freeze/reset randomly.  These ESP32-CAM boards are pretty cheap so I would grab a couple from different vendors, they are common to find on Amazon.  They also should come with the camera, double check that it does.

Here are the three main parts and some links:

ESP32-CAM (the ESP32-CAM board plus camera, I have had good luck with HiLetgo)
+ https://www.amazon.com/HiLetgo-ESP32-CAM-Development-Bluetooth-Raspberry/dp/B07RXPHYNM
+ https://www.amazon.com/ESP32-CAM-Bluetooth-Camera-Module-Development/dp/B07S5PVZKV
Feather nRF9160 (board containing the new LTE radio from Nordic)
https://www.jaredwolff.com/store/nrf9160-feather/
FTDI 3V3 cable (to program the ESP32-CAM, make sure it is 3V3)
https://www.amazon.com/Converter-Terminated-Galileo-BeagleBone-Minnowboard/dp/B06ZYPLFNB
https://www.digikey.com/en/products/detail/ftdi-future-technology-devices-international-ltd/TTL-234X-3V3/6823715

 

esp32_nrf9160_camera_http
esp32_nrf9160_camera_http

esp32_nrf9160_camera_http

esp32_nrf9160_camera_http

esp32_nrf9160_camera_http

Here is how to wire it all up.  There are some pictures to show the wiring if its easier to visualize, and below the pictures are tables with the pinout details.

esp32_nrf9160_camera_http

esp32_nrf9160_camera_http

There are two buttons also visible, the top button is a “take picture” button, shorted so pictures are automatically taken.  The bottom button is the “bootloader” button.  Press this button and hold it while pressing the reset button (on the bottom side of the ESP32-CAM board).  After the ESP32-CAM reset button is pressed release the “bootloader” button.  Wiring between the nRF9160 and the ESP32-CAM and pinout descriptions is shown below.

Feather nRF9160  ESP32-CAM
Pin Desciption Pin Desciption
 RST  reset IO15 nRF9160 reset
 D5  UART2 RX  IO12 UART TX
 D7  UART2 TX  IO13 UART RX
Feather nRF9160
Pin Desciption Info
 GND ground connect to the common ground
 RST reset connect to ESP32-CAM pin IO015
 D5 UART2 RX connect to ESP32-CAM pin IO12
 D7 UART2 TX connect to ESP32-CAM pin IO13
ESP32-CAM
Pin Desciption Info
 5V0 5.0v power input connect to FTDI pin 3 (red)
 GND GND connect to the common ground
 U0R UART0 RX connect to FTDI pin 4 (orange)
 U0T UART0 TX connect to FTDI pin 5 (yellow)
 IO0 GPIO D0 bootloader enable pin, active low
 IO12 GPIO D12 connect to nRF9160 pin D5
 IO13 GPIO D13 connect to nRF9160 pin D7
 IO14 GPIO D14 “take picture” switch, active low
 IO14 GPIO D15 connect to nRF9160 pin RST
FTDI 3V3 6-pin connector
Pin Description Info
 1 (black) GND connect to the common ground
 2 (brown)  CTS#  not used
 3 (red)  5V0  connect to ESP32-CAM 5V0 pin
 4 (orange)  TXD  connect to ESP32-CAM U0R pin
 5 (yellow)  RXD  connect to ESP32-CAM U0T pin
 6 (green)  RTS#  not used

Please do make sure the FTDI cable you are using is a 3.3v version.  The signal lines will be 3.3v but red pin will still have 5.0v on it.  We will power the ESP32-CAM 3V3 regulator from with the 5.0v on the FTDI cable.  Also notice the nRF9160 has its own USB cable, it is powered from that cable.  Since there is no pin on the Feather nRF9160 that we can use to power the Feather nRF9160 we are powering the Feather nRF9160 with a second USB cable.

The Arduino hardware support and some libraries will also need to be installed, to install the Arduino library for the ESP32-CAM open up the Arduino preferences add the following URL to the “Additional Boards Manager URLs box, there is a button to the right that will open up a text box to easily add more than one URL.

https://dl.espressif.com/dl/package_esp32_index.json

esp32_nrf9160_camera_http

Press the “OK” buttons and then open up the “Board Manger” from the “Tools” “board” menu.

esp32_nrf9160_camera_http

Type “esp32” into the search box and install the “esp32” board package.  This will add support for many ESP32 based boards including the “AI Thinker ESP32-CAM.” the board that we are working with.  Be sure to select the board after installing it.

There are a couple other libraries that can be installed through the “Library Manager” if they are not installed, these are:
+ StreamDebugger
+ Time

Additionally, we use TinyGSM, but the version in the Library Manager does not have nRF9160 support, please download that from here and extract the contents into the “library” folder, generally located in “My Documents/Arduino/libraries”.

https://www.drassal.net/filestore/esp32_nrf9160_camera_http_20210203/TinyGSM_20210203.zip

Also grab the Arduino sketch from the below link, unzip this in your Arduino sketch folder.

https://www.drassal.net/filestore/esp32_nrf9160_camera_http_20210203/esp32_nrf9160_camera_http_20210203.zip

These next steps will involve getting the Feather nRF9160 programmed so it will work with TinyGSM (as a AT command driven serial LTE modem).  Getting the nRF9160 programmed might take a little patience.  I found the easiest way is to use “nrfjprog” from Nordic, however, there are GUI based programming tools available also.

I have not had luck with the bootloader for the Feather nRF9160 as the hex file we will load is a little too big.  We may need to use a hardware JLink programmer, or an nRF9160DK, I also hear an nRF53 series DK will also work. A 6-pin TagConnect cable will also be required to connect the Feather nRF9160 programming pins to the programmer.

For the TagConnect, there are a couple routes to go, this cable should connect directly to the nRF9160DK but I have not personally tested it.  Also the smaller thinner wires might break easier with heavy use.

https://www.tag-connect.com/product/tc2030-ctx-nl-6-pin-no-legs-cable-with-10-pin-micro-connector-for-cortex-processors

The connector that I have is the the following, I made an adapter board so I can use it for other projects in the future.  The pins on this connector are routed straight through, pin-for-pin.  There are links to a couple other useful items that can be used to make the adapter board.

https://www.tag-connect.com/product/tc2030-idc-nl
https://www.adafruit.com/product/2743
https://www.adafruit.com/product/1675

The TagConnect cables are not cheap, but are very useful to have around, I am seeing more and more development boards with TagConnect pads.  If you are buying one I would recommend grabbing both of the generic 6-pin and 10-pin versions for future use, these two links below.

https://www.tag-connect.com/product/tc2030-idc-nl
https://www.tag-connect.com/product/tc2050-idc-nl-10-pin-no-legs-cable-with-ribbon-connector

There two files to program, one is to update the nRF9160’s baseband (modem) firmware, the other is to program the actual nRF9160’s main MCU.  If the nRF9160DK is being used instead of the Feather nRF9160 there is one additional hex file to program for the nRF9160DK’s “board controller” nRF52840.

 

https://www.drassal.net/filestore/esp32_nrf9160_camera_http_20210203/nrf9160_baseband_20210203.zip

https://www.drassal.net/filestore/esp32_nrf9160_camera_http_20210203/nrf9160_firmware_20210203.zip

Detailed instructions for programming the nRF9160 is a discussion in itself and I will write up another post with all the details about how to program the three types of nRF9160 boards that I have run into so far.

There are details in the baseband zip file on how to program the baseband, along with the firmware files in the firmware zip file.  For the firmware files there are many to choose from, for the Feather nRF9160 to program it through the nrfjprog utility or the GUI programmer) it would be serial_lte_modem_circuitdojo_feather_nrf9160_115200_merged.hex, 115200 referring to the speed the UART is running at.

For the time being the programming of the nRF9160 is a little above the scope of this guide and will cover it in another post and link to it here when that post is finished.  For now try to search online to get setup for programming.

Setting up the sketch

Lets go back now to the Arduino IDE and load the sketch, there are a couple things we will need to setup.  First will be the APN information for your SIM card, the APN name and then authentication if required,  TinyGSM is setup to use CHAP now, it can be changed over to PAP if necessary.

esp32_nrf9160_camera_http

Next we need to decide where we are going to send the images to, this is setup at the top of the sketch.  The “UPLOAD_TOKEN” and “UPLOAD_MESSAGE” are not used, but left in as placeholders for some kind of authentication system later.

esp32_nrf9160_camera_http

Here is a simple upload.php that can receive the uploaded images.

<?php
$uploadfile = "";
echo "Receiving file [";
echo $_FILES["imageFile"]["name"];
echo "]\r\n";
if(strlen(basename($_FILES["imageFile"]["name"])) > 0)
{
 $uploadfile = basename($_FILES["imageFile"]["name"]);
 if(move_uploaded_file($_FILES["imageFile"]["tmp_name"], $uploadfile))
 {
 echo "saved ";
 } else {
 echo "error moving file";
 }
} else {
 echo "error image data does not exist";
}
?>

After this build and program the ESP32-CAM.  If everything is setup right you should see the Feather nRF9160 connect to the LTE network and see images being uploaded.  It takes time to connect (6 seconds alone for the Feather nRF9160 hardware reset to finish).

There is a lot more detail I want to add to this but going to post this guide up as it is now and add the rest of the information in a little bit.  The required files and source code are all linked above and that is mostly what I wanted to get posted up while I finish fixing up this guide.

Notes from building a minimum Linux Gentoo Kernel for a Raspberry Pi

Recently I have been working with more and more Raspberry Pi single board computers and as a person who likes the Linux Gentoo distribution I got the urge to make a bare minimum kernel.  These are basically some notes based on what I have learned trying to build a bare-bones custom kernel for the Raspberry Pi.

If you find issues with this kernel config, or find something I missed, please let me know in a comment so I can take a look into it and update information.

I am not going to go quite into detail how to build a kernel and such, this guide is just a reference to what drivers I found are necessary for a bare bones kernel, without any extra drivers.  The only extra things I think I added is for some USB-Serial drivers, since they are required for my application, they can be safely removed.

This is using the Raspberry Pi kernel sources sys-kernel/raspberrypi-sources-4.19.9999, emerge or update this before proceeding.  Also to note, this is for a 32-bit kernel.  I have not been able to get this to work on the new Raspberry Pi 4 yet, it just won’t boot… I will try to figure out why at a later date.

https://www.drassal.net/downloads/config_4.19.86_201912041613

The version that I have installed now is 4.19.86, and this configuration is for that version.  You should be able to use this with newer kernel versions, just use make oldconfig before using make menuconfig.

I started with a minimum kernel with almost no drivers included, and slowly added the drivers necessary to obtain the functionality required, trying to get drivers for all the hardware on the board.  This process of building, checking, rebuilding took several full days and I would like to document what I found out is the minimum install necessary.

I am not quite confident the sound drivers are correct yet, but will hopefully get a chance to test this in the future.

This kernel config posted here works with the following hardware, since it is what I had on hand to test with:
+ Raspberry Pi Zero W
+ Raspberry Pi Zero WH
+ Raspberry Pi 3 Model B
+ Raspberry Pi 3 Model B Plus

In order to get the display to work right on the Raspberry Pi Zero W I had to edit the config.txt file on the boot partition and uncomment this line at the bottom… not sure why yet… only the Raspberry Pi Zero W appears to need it.

[all]
dtoverlay=vc4-fkms-v3d

I started working with a Raspberry Pi 3 Model B, then after that was working moved onto testing on the Zero W and 3 Model B Plus.  Below is some detail of things I found to be specific to a specific platform…

Device Drivers – Network Device Support – USB Network Adapters – Multi-purpose USB Networking Framework – SMSC LAN95XX based USB 2.0 10/100 ethernet devices
+ Wired ethernet for Raspberry Pi 3B

Device Drivers – USB support – Synopsis DWC host support
+ USB for Raspberry Pi Zero W

Device Drivers – Network Device Support – USB Network Adapters – Microchip LAN78XX Based USB Ethernet Adapters
+ Wired ethernet for Raspberry Pi 3B Plus

Device Drivers – Network Device Support – Wireless LAN – Broadcom devices – Broadcom FullMAC WLAN driver
+ Wireless LAN driver

Device Drivers – Network Device Support – Wireless LAN – Broadcom devices – SDIO bus interface support for FullMAC driver
+ Wireless LAN driver support

Sheeva64, recovering/reloading U-Boot from a bricked state

This took a while to get back to but I actually just now bricked my Sheeva64 (corrupted U-Boot) so I could repeat this procedure and make sure everything works correctly.

The layout of the blog doesn’t help with making this easy to read, especially the longer lines, going to look into trying out some different themes soon to address this…

I am actually writing this up as I am confirming and actually doing the steps, so hopefully it all goes well, if not I will have a cool new paperweight!
I just ran through ALL the instuctions written here again after writing this, so there should be no issues, if there are, please leave me a comment!

First of all a brief introduction to the bootloader and some general information… can be skipped if you are familiar with it, just to be complete I will include it.

This is a procedure that took a while to work out, after that I was directed to the official method by GlocabScale Technologies, which I will also provide at the end.

When we are talking about a bricked Sheeva64 there are a few different ways to brick it…
1. Somehow or another the kernel image or internal eMMC (SD card) or whatever you are booting off from is corrupted.
This is actually not very serious and can be repaired without much trouble, which I will write about in another post.
2. The bootloader (U-Boot) is corrupted or been erased.  U-Boot is essentially what is first executed when the Sheeva64 CPU is turned on.

U-Boot is responsible for a couple of very important functions, first it initializes very low level stuff.
This includes things like the CPU clocks, DDR memory controller and other peripherals, ethernet, etc.

It this provides this information to the kernel that is loaded so the kernel knows what devices exist, etc in the hardware.
U-Boot, having support for FAT and sometimes other filesystems, reads the kernel image (its only a few megabytes) and
copies that into DDR memory at a predetermined expected address then executes that kernel code.

This essentially loads the kernel and passes control to the kernel which then loads the operating system, following a similar path to how a normal x86/x64 system boots up.

The difference here with the Sheeva64 it is does not have a traditional BIOS, which is normally responsible for low level initialization functions in a x86/x64 PC.  This is where U-Boot comes in, it takes on the role of low level initializtion and then loads and executes the kernel.

This U-Boot loader is stored in a small chip called a SPI NOR (or NAND) memory chip, it only has a few megabytes of storage space, just enough for the U-Boot loader to fit.
If this bootloader (the code first executed by the Sheeva64 CPU) is not present… nothing happens when you turn it on… the device is practically bricked.

While the Sheeva64 is bricked, and there is no bootable U-Boot in the SPI NOR flash, it can still be brought up manually, but, after it is brought up a new U-Boot will need to be written to restore the ability for the Sheeva64 to self boot again.

With the DreamPlug, another product by GlobalScale Technologies, which I have used for many years, it was possible to connect a JTAG debugger to the CPU and put the CPU into debug mode and upload a U-Boot image into the DDR memory, then execute it, allowing the DreamPlug to be brought up when U-Boot was corrupted.

However, while I can JTAG into the Sheeva64 CPU (I have tried) I can read the CPU ID information, etc, but have not managed to be able to initialize the CPU correctly or bring it up by hand through the JTAG debug interface, and I think this has something to do with the new security features of the new Armada A3700 CPU.  It requires a very specific initialization sequence to be followed, and lucky for us, it has its own debug interface now which is automatically entered if U-Boot can’t be loaded, or if a boot mode jumper is set.

Basically, long story short, you don’t even need to open up the Sheeva64 to be able to recover the U-Boot since JTAG access is no longer necessary.
We are going to use the recovery prompt built into the A3700 CPU available through the debug serial port (mini USB) connection.

Now onto the recovery process… first we are going to verify that the recovery command prompt shows up correctly on your Sheeva64.
Connect a micro USB table to the debug port on the Sheeva64 and open a serial terminal using the following settings… 115200-8-N-1
I am going to upload a python program that can also be used, and I recommand and encourage you to look at the python source before executing it on your own PC to make sure it doesn’t contain anything bad…

python3 -m serial.tools.miniterm –raw –eol CR –encoding ascii /dev/ttyUSB0 115200

The debug USB (serial) port on the Sheeva64 is powered from the USB connection so you won’t lose the USB connection if power is removed from the Sheeva64, which is good for us because we will need a way to reset it.
With the cable connected, and your serial terminal open, reset the Sheeva64 by unplugging it and plugging it back in, you should see a prompt similar to this image…

sheeva_recovery01

Just press enter here and if you get a “E” or error response back you are good, you have access to the CPU recovery console.
Next we are going to instruct the CPU to expect an upload of some bootable code, there are a few files that have to be uploaded, and it will take some time.
I am going to provide the files that I generated here, which is a lengthy process, which I will also outline how to do in this post.

Grab the “sheeva64_debricker_20191203.tar.bz2” file and extract it to a location of your choice, it should all be self-contained.
tar -xjf sheeva64_debricker_20191203.tar.bz2

https://www.drassal.net/downloads/sheeva64_debricker_20191203.tar.bz2

We are going to do a couple things, and they have to be done rather quickly, so having three terminal windows ready to execute these commands might be useful.
I recommend having the following three terminal windows open and will refer to them as termianl 1, 2, and 3.
1. The terminal with the recovery console open, it turns out the python script above is a little more friendly as it auto disconnects correctly when we execute the next command in terminal 2.
2. The terminal that we will use to upload the new RAM bootable U-Boot image and other related processor specific code.
3. The terminal that you will use with minicom or your favorite terminal software to open as soon as the CPU is executing the U-Boot.

Here is am image of how I had my screen setup for this, lining up each window side by side.

sheeva_recovery09

Change to the folder that the above tar.bz2 file was extracted in for terminal 2, we will be executing some things from in there.
As a note, this process might need sudo access to the /dev/ttyUSB0 device, if you are not comfortable with this setup a VM to sandbox this, or setup a throw away livecd install on another machine.
/dev/ttyUSB0 is assumed below, please adjust things if necessary…

After U-Boot loads up, it will continue, just like normal, to load up your kernel and start up your OS, we don’t want that to happen so be quick to connect up in terminal 3 and press that “any key” to interrupt the U-Boot process… most likely your OS will not even load correctly as this RAM version of U-Boot functions just enough to bring the system up to rewrite the U-Boot loader into SPI NOR flash.

There are a couple small things to warn about.  This RAM loaded U-Boot is capable of overriting your enviornment variables, so don’t try to save any U-Boot settings, it might foul them up.
If your U-Boot settings are also corrupted, I will include some instructions below to reset those back.

Here is the sequence we are going to do…
I think you will need pyserial for this, some reference is here https://pyserial.readthedocs.io/en/latest/tools.html
If you can’t use the below command it doesn’t hurt to try another serial software and disconnect it after typing in the wtp command.
On terminal 1 execute
sudo python3 -m serial.tools.miniterm –raw –eol CR –encoding ascii /dev/ttyUSB0 115200

type “wtp” and press enter.
The CPU will be put into a mode to wait for an upload from this same USB serial debug cable you are connected to now.

sheeva_recovery01

On terminal 2, execute the following command…
sudo ./WtpDownload_linux -P UART -C 0 -R 115200 -B TIM_ATF.bin -I wtmi_h.bin -I boot-image_h.bin -E

sheeva_recovery02

sheeva_recovery03

sheeva_recovery04

This is glitchy and sometimes does not work.  It should not stop, or appear frozen during any time of execution.
If it appears frozen, something went wrong, Ctrl + C it and reset the Sheeva64 by unplugging and reconnecting power… wait a few seconds after unplugging to be sure its fully reset.
After it is reset, do the above wtp step again to put it in the serial upload mode and try again.  It took me many attempts to figure this part out, but it can be a little finicky.

The upload process will take a little over a minute to complete (around 1min and 15sec on my setup), be watching your screen and be prepared to connect minicom or another serial terminal software quickly (on terminal 3), you need to interrupt the boot sequence, press any key when that message pops up (on terminal 3) to interrupt the startup process.
After upload is complete and command prompt is returned on terminal 2 get connected on terminal 3 and now we should have a U-Boot interface to work with.

sheeva_recovery05

Remember, now U-Boot is running from RAM so if we reset or remove power now we have to begin again from step 1, we still havent’t copied the bootloader back into the NOR flash, this is the next step.
Grab a USB memory stick that you have laying around, it should be formatted VFAT or FAT32 (possibly FAT16 works too) and copy the sheeva64-bootloader-cpu-1000-ddr4-1cs-1g-atf-711ecd32-uboot-gc338309136-utils-57a8e47-20190625-REL.bin over to it in the root folder.  This is in the “u-boot_images” folder in the “sheeva64_debricker_20191203.tar.bz2” file.

A brief explination of the filename here, the CPU operates at 1000Mhz, DDR is DDR4 type, 1CS setting, and 1GB in quantity.
There are some other files avaialble from the GlobalScale Technologies website so be sure to grab the if needed.

Insert this into the Sheeva64’s bottom USB2.0 port, the USB3.0 won’t work, I think the USB3.0 driver is not working correctly in the make-shift recovery bootloader yet…
Execute this command in the U-Boot console, this will rewrite your bootloader…

bubt sheeva64-bootloader-cpu-1000-ddr4-1cs-1g-atf-711ecd32-uboot-gc338309136-utils-57a8e47-20190625-REL.bin spi usb

This will take a little time to complete, be patient and give it some time, erasing and writing to NOR flash isn’t the fastest thing in the world.
Once writing to the NOR flash is complete the USB memory stick can be removed and you can reset the Sheeva64 with the “reset” command.
It should now self-boot into the U-Boot console.  Next, if your U-Boot enviornment variables are fouled up you will still have to fix those, but, the hard part is done.
To fix the U-Boot variables execute the below commands in the U-Boot console…

*** none of these commands will save until the “saveenv” or “hw_info store” command is used, so if you make a mistake, just use “reset” and try again.
*** these fix the enviornment variables
env default -a
setenv image_name boot/Image
setenv fdt_name boot/armada-3720-sheeva64.dtb
setenv bootcmd ‘mmc dev 1; ext4load mmc 1:1 $kernel_addr_r $image_name; ext4load mmc 1:1 $fdt_addr_r $fdt_name; setenv bootargs $console root=PARTUUID=89708921-01 rw rootwait net.ifnames=0 biosdevname=0; booti $kernel_addr_r – $fdt_addr_r’
saveenv

*** these will fix your ethernet address, if it somehow got changed…
*** ethaddr is printed on the label on the back of the Sheeva64, but I don’t know where eth1addr comes from, I am going to have to bring this up to GlobalScale and ask them about it.
setenv pcb_rev 5.0.1
setenv ethaddr xx:xx:xx:xx:xx:xx
setenv eth1addr xx:xx:xx:xx:xx:xx
saveenv
hw_info store

*** the below command will execute the boot process
boot

This concludes the recovery process of the U-Boot boot loader.  If the SD card or internal eMMC is corrupted, this is a different recovery procedure.
There is information on the GlobalScale Technologies website here to help with that…

https://www.globalscaletechnologies.com/p-86-sheeva64.aspx
From here open up the Downloads section and V5.
A direct link is also below
ftp://108.178.146.214/downloads/Sheeva%2064/V5/

I have trouble opening this up in Safari on my MacBook, it seems FTP is not a built in feature of browsers anymore…

Next, if the above binary does not work for you, or you want to build this from scratch and get your own U-Boot enviornment setup, this next section is for you.

I do want to put a thank you out to the following website which provided some invaluable insight into how to build some of the files used above.

Original source for some of this information is here… it is a good read, but also quite a bit technical.
http://tinkering-is-fun.blogspot.com/2019/02/espressobin-building-u-boot.html

Now onto the more technical explination and how to generate the needed files from scratch.  All necessary things are open source and avaiable to download as of this writing.

To generate everything I used from scratch, first download the following four sources and set the branches to the things listed below…
I will provide the exact commands below.

marvel-tools: https://github.com/MarvellEmbeddedProcessors/A3700-utils-marvell, branch A3700_utils-armada-18.12
marvell-ddr: https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git, branch mv_ddr-armada-18.12
ATF: https://github.com/MarvellEmbeddedProcessors/atf-marvell, branch atf-v1.5-armada-18.12
U-Boot: https://github.com/MarvellEmbeddedProcessors/u-boot-marvell.git, branch u-boot-2018.03-armada-18.12

This is going to be wierd, but we will need not one, but two GCC toolchains to build this correctly.
The first toolchain is for the ARM64 Sheeva64 Marvell Armanda A3700 SoC (CPU).
The second toolchain is for our own PC, to generate the code.  I am assuing you are on a x86 or x64 system here…
If your platform is different (this was performed on a x64 based i7 platform), please modify the instructions to your setup… which I will not go into detail here how to do this…

gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu
gcc-linaro-5.5.0-2017.10-x86_64_arm-linux-gnueabi

Will other toolchains work? Maybe, but why not just use what is known to work for this process… then once you have a working setup you can experiment with other things such as toolchains.
I am going to host all these files on this blog site for completeness sake, and for the reason that stuff on the internet goes missing a lot these days and links break.

A few of the harder to extract parts are here for download hosted here, but they were originally sourced from open source sources.  For these few files I will add a section of how to extract these at a later date.

Then of course, if you are in doubt at all about trusting anything you download here, set yourself up a sandboxed or a throw-away VM machine and conduct the Sheeva64 recovery from a system that you have no concerns about breaking.

As of writing this post I tested each step as writing the instructions so everything should be good.

I am going to basically write somewhat of a script below, and you should almost be able to copy paste line-for-line and just execute them.

First we need to make a folder for where we will be working from, and I am choosing the following.

mkdir /home/user/sheeva64_debricker
cd /home/user/sheeva64_debricker

mkdir /home/user/sheeva64_debricker/downloads
cd /home/user/sheeva64_debricker/downloads

wget https://releases.linaro.org/components/toolchain/binaries/latest-5/aarch64-linux-gnu/gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu.tar.xz
wget https://releases.linaro.org/components/toolchain/binaries/5.5-2017.10/arm-linux-gnueabi/gcc-linaro-5.5.0-2017.10-x86_64_arm-linux-gnueabi.tar.xz
wget https://www.drassal.net/downloads/sheeva64_debricker_blobs.tar.bz2
wget https://www.drassal.net/downloads/sheeva64_debricker_patches.tar.bz2
wget https://www.drassal.net/downloads/sheeva64_debricker_u-boot_images.tar.bz2

*** extract some misc necessities
cd /home/user/sheeva64_debricker
tar -xjvf /home/user/sheeva64_debricker/downloads/sheeva64_debricker_blobs.tar.bz2
tar -xjvf /home/user/sheeva64_debricker/downloads/sheeva64_debricker_patches.tar.bz2
tar -xjvf /home/user/sheeva64_debricker/downloads/sheeva64_debricker_u-boot_images.tar.bz2

mkdir /home/user/sheeva64_debricker/toolchains
cd /home/user/sheeva64_debricker/toolchains

*** extract the downloaded toolchains here
tar -xvpf /home/user/sheeva64_debricker/downloads/gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu.tar.xz
tar -xvpf /home/user/sheeva64_debricker/downloads/gcc-linaro-5.5.0-2017.10-x86_64_arm-linux-gnueabi.tar.xz

*** grab the required utilities
mkdir /home/user/sheeva64_debricker/utils

cd /home/user/sheeva64_debricker/utils
git clone https://github.com/MarvellEmbeddedProcessors/A3700-utils-marvell
cd A3700-utils-marvell
git checkout A3700_utils-armada-18.12

cd /home/user/sheeva64_debricker/utils
git clone https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git
cd mv-ddr-marvell
git checkout mv_ddr-armada-18.12

cd /home/user/sheeva64_debricker/utils
git clone https://github.com/MarvellEmbeddedProcessors/atf-marvell
cd atf-marvell
git checkout atf-v1.5-armada-18.12

cd /home/user/sheeva64_debricker/utils
git clone https://github.com/MarvellEmbeddedProcessors/u-boot-marvell.git
cd u-boot-marvell
git checkout u-boot-2018.03-armada-18.12

*** build the tools
cd /home/user/sheeva64_debricker/utils/atf-marvell

make DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 SECURE=0 CLOCKSPRESET=CPU_800_DDR_800 DDR_TOPOLOGY=2 BOOTDEV=SPINOR PARTNUM=0 PLAT=a3700 CROSS_COMPILE=/home/user/sheeva64_debricker/toolchains/gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-

cp /home/user/sheeva64_debricker/blobs/espressobin/DDR_TOPOLOGY_2-*.txt /home/user/sheeva64_debricker/utils/A3700-utils-marvell/tim/ddr/.

cd /home/user/sheeva64_debricker/utils/u-boot-marvell
git apply /home/user/sheeva64_debricker/patches/u-boot/u-boot-mvebu64/0001-espressobin-enable-emmc.patch
cp /home/user/sheeva64_debricker/patches/u-boot/dts/armada-3720-sheeva64.dts /home/user/sheeva64_debricker/utils/u-boot-marvell/arch/arm/dts/.

cp /home/user/sheeva64_debricker/utils/atf-marvell/build/a3700/debug/bl31.bin /home/user/sheeva64_debricker/utils/u-boot-marvell/.
cd /home/user/sheeva64_debricker/utils/u-boot-marvell

make mvebu_espressobin-88f3720_defconfig CROSS_COMPILE=/home/user/sheeva64_debricker/toolchains/gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
make DEVICE_TREE=armada-3720-sheeva64 LOCALVERSION=-ambian CROSS_COMPILE=/home/user/sheeva64_debricker/toolchains/gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-

if compiler error because gcc is too old, edit the below file
vi /home/user/sheeva64_debricker/utils/u-boot-marvell/arch/arm/config.mk
change line 70, the version change “0600” to “0500” to bypass the gcc version check, then try again, messy, but works

make DEVICE_TREE=armada-3720-sheeva64 LOCALVERSION=-ambian CROSS_COMPILE=/home/user/sheeva64_debricker/toolchains/gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-

cd /home/user/sheeva64_debricker/utils/atf-marvell
make MV_DDR_PATH=/home/user/sheeva64_debricker/utils/mv-ddr-marvell CROSS_COMPILE=/home/user/sheeva64_debricker/toolchains/gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 SECURE=0 CLOCKSPRESET=CPU_1000_DDR_800 DDR_TOPOLOGY=5 BOOTDEV=SPINOR PARTNUM=0 PLAT=a3700 all fip BL33=/home/user/sheeva64_debricker/utils/u-boot-marvell/u-boot.bin WTP=/home/user/sheeva64_debricker/utils/A3700-utils-marvell CROSS_CM3=/home/user/sheeva64_debricker/toolchains/gcc-linaro-5.5.0-2017.10-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-

All the above commands hopefully finished without error…
The U-Boot that is built using this method is actually ment for the EspressoBIN, which is based off the same Marvell A3700 Armanda SoC, but with different peripherals, therefore it is not 100% stable on the Sheeva64, but stable enough to reload the factory U-Boot image, which is all we really need it for.

Now you have built all the necessary files to boot the Sheeva64 from a bricked (very very bricked) state.
The loading command will change a little since we need to reference the files that are all spread out that we just made.
I have found this easiest to do the following way…

We still use our original commands in terminal 1 to set the wtp mode.
sudo python3 -m serial.tools.miniterm –raw –eol CR –encoding ascii /dev/ttyUSB0 115200

In terminal we will modify some stuff, change to the following folder, then execute the load command.

cd /home/user/sheeva64_debricker/utils/atf-marvell/build/a3700/debug/uart-images
sudo /home/user/sheeva64_debricker/utils/A3700-utils-marvell/wtptp/linux/WtpDownload_linux -P UART -C 0 -R 115200 -B TIM_ATF.bin -I wtmi_h.bin -I boot-image_h.bin -E

This will start the upload process as above, and the final recovery process is the same, copy the sheeva64-bootloader-cpu-1000-ddr4-1cs-1g-atf-711ecd32-uboot-gc338309136-utils-57a8e47-20190625-REL.bin file (located in u-boot_images) to a USB memory stick, insert it into the USB2.0 port (by the ethernet port) and finish recovery with the below command.

bubt sheeva64-bootloader-cpu-1000-ddr4-1cs-1g-atf-711ecd32-uboot-gc338309136-utils-57a8e47-20190625-REL.bin spi usb

I really hope the above information is useful as I had to do most of this from scratch as this is still kind of a new device with little resources available.

GlobalScale Technologies does have some recovery inforation, which I will share, but I have not personally tested it yet.
There might be a easier recovery method, but the above method should 100% gurantee a recovery.

Finally, here are the commands to execute in the U-Boot console to reset your enviornment variables…
*** none of these commands will save until the “saveenv” or “hw_info store” command is used, so if you make a mistake, just use “reset” and try again.
*** these fix the enviornment variables
env default -a
setenv image_name boot/Image
setenv fdt_name boot/armada-3720-sheeva64.dtb
setenv bootcmd ‘mmc dev 1; ext4load mmc 1:1 $kernel_addr_r $image_name; ext4load mmc 1:1 $fdt_addr_r $fdt_name; setenv bootargs $console root=PARTUUID=89708921-01 rw rootwait net.ifnames=0 biosdevname=0; booti $kernel_addr_r – $fdt_addr_r’
saveenv

*** these will fix your ethernet address, if it somehow got changed…
*** ethaddr is printed on the label on the back of the Sheeva64, but I don’t know where eth1addr comes from, I am going to have to bring this up to GlobalScale and ask them about it.
setenv pcb_rev 5.0.1
setenv ethaddr xx:xx:xx:xx:xx:xx
setenv eth1addr xx:xx:xx:xx:xx:xx
saveenv
hw_info store

*** the below command will execute the boot process
boot

Sheeva64, rebuilding the kernel

In this post I am going to take a look at rebuilding the Sheeva64’s kernel.  The Sheeva64 is a 64-bit ARM based single board computer based on a Marvell Armada 3720 SoC.  More information about the SoC can be found at Marvell’s website here (https://www.marvell.com/embedded-processors/armada/armada-3700/), or GlobalScale Technologies (the manufacturer) website here (https://www.globalscaletechnologies.com/p-86-sheeva64.aspx).

This process is also very similar to the guide at wiki.espressobin.net located here (http://wiki.espressobin.net/tiki-index.php?page=Software+HowTo).  The SoC is identical, but the board layout and peripherals are slightly different, therefore the exact kernel configuration won’t have all the drivers necessary for the Sheeva64, but it doesn’t hurt to give it a try, it won’t break anything.

First I would like to give credit to the origianl source for most of this located at the below link.
I would like to thank the author for deciphring all the logic in the Armbian.com build system so I could come up with some parts of these instructions.
http://tinkering-is-fun.blogspot.com/2019/02/espressobin-rebuilding-kernel-based-on.html

Next the Armbian.com website and their efforts to make a stand alone fully automated build solution for various single board computers, it is really quite impressive.  The system Armbian.com put together is a really, really nice build setup and recommend you try it if you have any supported boards.  Unfortinatly the Sheeva64 is not supported yet, but a very close match is the EspressoBin containing the exact same Marvell Armada 3720 SoC.
Because the peripherals and board are different the EspressoBin build will not work 100% correctly, but it helped me come up with the below script.  I sure hope they continue supporting and updating their build system.
(https://www.armbian.com/)

The actual Armbian.com build environment, to which I sourced some information, such as the toolchains and patches, is here.
https://github.com/armbian/build

I will try to provide references to original sources and give credit where appropiate.  This is an effort to provide a detailed resource to assist others with the Sheeva64 kernel building process, no harm intended.
If there is something used here that is not referenced properly, please let me know and I will add the appropriate references.

While I try to be accurate, it is possible I missed something or made some mistakes, please double check what you do before you blindly copy-paste and run commands, just incase.  Especially with updating the actual /boot files on the Sheeva64, and u-boot environment, please be very careful and double check.  Some mistakes in here can be costly and take time to fix.

I shouldn’t have to remind you to make back up copies of these items you are going to download, in original unmodified form, incase they ever go away.  More often than not external links will disapear, with no easy way to get ahold of them again.

For peace of mind I would make sure you have an offline copy of these instructions and all required source files.
To ensure you have a build environment that always works, a VM or VirtualMachine is not a bad idea, it will always work and keep its last used state.

Personally I make tar/bz2 backups of sources in their original state for archive purposes.  The below command will help with that (the dot on the end is important, don’t forget it).

tar -jcvpf your_file_name.tar.bz2 –directory=/path_to_folder_you_want_to_archive .

Now onto the actual kernel creation process

rename all the “/your_build_root” to your actual build root.

Create your working folder
cd /your_build_root
mkdir sheeva64_kernel_builder_20190926
cd /your_build_root/sheeva64_kernel_builder_20190926

Grab the configuration file for the Sheeva64, you can get it by one of the following methods below, although I may upload it here soon.
This file will be used as the initial kernel configuration to base your new kernel on, since it has a known working configuration.
For this to work best, the kernel version should match, all the way down to the 120 at the end of the version number.
Use one of the below commands, result should be the same.
cat /proc/config.gz | gunzip > config_4.4.120-armada-18.09.2-g302564291ad5
zcat /proc/config.gz > config_4.4.120-armada-18.09.2-g302564291ad5

For the kernel version running, you can use the below command to name the file accurately.
This sniplet of code is from the below source.
https://www.cyberciti.biz/faq/inux-kernel-where-to-find-modules/

echo “Modules dir: /lib/modules/$(uname -r) for kernel version $(uname -r)”

Next, grab the recommended toolchain from the below link.
https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz

Just use wget to grab it quick, if you would like a troublefree download.
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz

You can see other files related to this toolchain by opening the folder
https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu
It is very likely others will work, but, this is what I used and works

Once you get this downloaded extract the tar file using the below command, it will end up in its own folder
tar -xvpf gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz

If the above link ever goes away, I will try to find a way to fix it or make it available

Grab kernel files from the Marvell repositiory
git clone https://github.com/MarvellEmbeddedProcessors/linux-marvell.git

It might be a good idea to archive these, just incase, but optional
tar -jcvpf linux-marvell_20190927.tar.bz2 –directory=/your_build_root/sheeva64_kernel_builder_20190926/linux-marvell .

Change to the linux-marvell folder
cd linux-marvell

Checkout the correct version, this version (branch) for sure works, I have not tested others, you are welcome to try other branches
git checkout linux-4.4.120-armada-18.09

Apply patches
This automation script was obtained from here
https://gitlab.com/snippets/1827562
Original maker’s webpage is here
http://tinkering-is-fun.blogspot.com/2019/02/espressobin-rebuilding-kernel-based-on.html

The patch files are from here https://github.com/armbian/build/tree/master/patch/kernel/meson64-default

You might find it easier just to use a git clone (git clone https://github.com/armbian/build) and download the entire repository, then copy out what you need instead of messing with downloading individual files.  These patches should be placed in the below folder to line up with the patch command, also below

/your_build_root/sheeva64_kernel_builder_20190926/patch/kernel/meson64-default

I believe the “https://github.com/armbian/build/tree/master/patch/kernel/meson64-next” folder is for later kernel versions, if you want to try that out, but I stuck with 4.14.120 since I know it works.

I believe these patches apply to 4.14.120, but not quite sure, they may already be patched into the linux-marvell source.
Including them just incase… it is possible you don’t need them
Currently this patch script also just runs all of the patches and applies the ones it can… maybe not the best way to do it, will get back to fixing it later

Run the next command inside the linux-marvell folder.
The working copy needs to be clean and there must be no untracked files.
Perform a “git reset –hard” to clean out any problems, all changes will be reverted to the last commit
A commit will be performed after each successful patch
Make sure the file is executable, if not fix it
chmod u+x ../apply-armbian-patches.sh
../apply-armbian-patches.sh ../patches/kernel/mvebu64-default/0005-patch-4.14.120-121.patch

Copy over the configuration file
cp ../config_4.4.120-armada-18.09.2-g302564291ad5 .config

Update .config if changing to a new kernel using make oldconfig.
CROSS_COMPILE=/your_build_root/sheeva64_kernel_builder_20190926/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ARCH=arm64 make oldconfig

With our kernel sources now prepared, we can go onto configuration and the actual building.

Run menuconfig to customize the kernel, if you would like to, can skip this if you happy with the original configuration.
CROSS_COMPILE=/your_build_root/sheeva64_kernel_builder_20190926/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ARCH=arm64 make menuconfig

Now is your chance to turn on any driver support you may want for USB serial devices, etc.

Finaly build the kernel.
It takes the i7-9700K CPU @ 3.60GHz running Linux Gentoo that I recently put together for compiling about 5 minutes or so to compile the kernel with its original options.
CROSS_COMPILE=/your_build_root/sheeva64_kernel_builder_20190926/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ARCH=arm64 make

Double check kernel modules got built.
CROSS_COMPILE=/your_build_root/sheeva64_kernel_builder_20190926/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ARCH=arm64 make modules

Copy out the kernel modules, be careful here, if you leave off the INSTALL_MOD_PATH it will attempt to copy into your /lib/modules folder!!!
CROSS_COMPILE=/your_build_root/sheeva64_kernel_builder_20190926/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ARCH=arm64 make modules_install INSTALL_MOD_PATH=/your_build_root/sheeva64_kernel_builder_20190926/modules_install

You will find your shiny new kernel under this path, copy it out to where you choose
This file will eventually make its way into your Sheeva64’s /boot folder, but I would change the name and not overwrite the original, just incase.
arch/arm64/boot/Image

Also the kernel modules will be needed too, copy them into /lib/modules on the Sheeva64
/your_build_root/sheeva64_kernel_builder_20190926/modules_install/lib/modules/4.4.120-armada-18.09.2-g4b3df2c67631

The dtb file, or flattened device tree will be located here, you should not need to update it though, it will be slightly off since there is not one taylored specifically for the Sheeva64 and you will find some devices won’t work, or will be unstable.  If you choose to compile a different kernel version, this DTB file *might* need to be updated as well.
arch/arm64/boot/dts/marvell/
I can’t recommend a specific one since there is not a direct match for the Sheeva64, but you are welcome to experiment with any of the files marked for the armada-3720 if you want to test things out.

Thats it! Place your new kernel into your Sheeva64 and see if it boots up correctly!
Personally these are the steps I do to update the kernel.
+ scp the files over
+ the Image file goes in /boot but I would rename it to something like Image_20190927 and append the date, don’t overwrite your original
+ the copy the entire kernel modules folder, 4.4.120-armada-18.09.2-g4b3df2c67631, into /lib/modules
+ plug in the mini-USB cable
+ fire up minicom or a terminal program so I can see what the Sheeva64 is doing (115200-8-N-1, no flow control)
+ issue a sudo “shutdown -r now” to restart the Sheeva64 gracefully
+ interrupt the u-boot autoboot process on the terminal when it comes up
+ use “env edit image_name” to direct u-boot to boot the new kernel
+ use “env save” to save the above changes
+ use “boot” to continue the boot process, or “reset” to reset the Sheeva64 and let it autoboot

At this point, you can see in the terminal window if your kernel boots or not, if all goes well, you will see the login prompt
If there are any issues, freezes, or panics, there is a problem with your kernel build, missing an important driver, or other issues
If this is the case perform these steps to bring back the original kernel
+ restart the Sheeva64 by cycling power
+ interrupt the autoboot process in terminal
+ use “env edit image_name” to restore your previous kernel
+ use “env save” to save your changes
+ use “boot” to continue the boot process, or “reset” to reset the Sheeva64 and let it autoboot

Your Sheeva64 should now be back on the old kernel and booting up.
At this point you can try to identify what went wrong and attempt another kernel build changing options in menuconfig as necessary.

Inside the new GlobalScale Technologies Sheeva64

Time to take a look inside the new Sheeva64 and see what has changed from the original SheevaPlug.

There is an introduction post located at https://www.drassal.net/wp/index.php/2019/09/24/sheeva64-by-globalscale-technologies-first-thoughts/ with some initial testing and thoughts on this new platform.  The manufacture’s website is located here https://www.globalscaletechnologies.com/p-86-sheeva64.aspx where you can order your very own Sheeva64.

With a new toy, we all have to take it apart to see what makes it “tick” don’t we?  There is a “warranty void if seal broken” sticker holding the two halfs together, but, nothing that an exacto knife won’t fix!  Removing the four friction fit rubber feet to expose the standard Philips screws, and in a few minutes we have the two halfs apart.

This wasn’t just for the pictures, but I did some JTAG experimenting as well, and will follow up in another post about my findings with the JTAG, but story short, I can detect the Marvell Armada 3720, and connect in, but that is as far as I have gotten.  I need more detail about the low level initialization to go further.  This must be in the u-boot source code if I dig deep enough.

Now what we all have been waiting for, the internal pictures of the new Sheeva64!  This is also very similar to the GlobalScale Technologies EspressoBin single board computer (same 64-bit Arm based Marvell Armada A3720 SoC, so those who have the EspressoBin should notice some similarities.

GlobalScale Sheeva64 main PCB top
GlobalScale Sheeva64 main PCB top
GlobalScale Sheeva64 main pcb top
GlobalScale Sheeva64 main pcb top
GlobalScale Sheeva64 main PCB bottom
GlobalScale Sheeva64 main PCB bottom
GlobalScale Sheeva64 showing top and bottom just opened
GlobalScale Sheeva64 showing top and bottom just opened
GlobalScale Sheeva64 PCB inside case top
GlobalScale Sheeva64 PCB inside case top
GlobalScale Sheeva64 PCB inside case top
GlobalScale Sheeva64 PCB inside case top

We can see that the Sheeva64 has a real RTC (real time clock) to keep time when not powered, which is a very welcomed feature.  It is rare to find on single board computers these days, mostly to save cost I suppose… the Sheeva64 comes with a RTC and a battery to keep time, just like your desktop or laptop computer.

This is the non-WiFi version, we can see the pads where the WiFI and one more DDR4 chip would be placed.  This model only has 1GB of DDR4, but there is a place reserved for one more DDR4 memory chip.

The two gigabit ethernet ports are visible, along with the USB2.0 and USB3.0 ports.  There is an external SD card slot also visible and the mini-USB for the serial console and u-boot tweaking/repair.

We also have the 10-pin standard JTAG connector visible, along with the jumper to set boot mode (Armada 3270 internal ROM or external SPI).  The boot mode from the factory is of course SPI, the internal ROM mode is used to invoke the internal ROM boot loader, which can be used for recovery purposes.  However, if the SPI does not load up right, you might end up in the ROM boot loader anyway regardless of the jumper setting.

I did not remove the heat sink off the bottom of the board, but the Marvell Armada 3720 will be located under that large aluminum heat sink.  This is a fanless design, while I believe the original SheevaPlug had a fan inside it.  Will have to do some testing and load up the CUP with some Gentoo source compiling (will happen soon) and see how the temperatures are.  The heatsink and chips are interfaced with some thick white/greyish colored thermal tape the stuff, the kind of stuff often seen interfacing graphics card memory chips to heatsinks.

A very clean and compact board design, all with a dual core 64-bit processor.

GlobalScale Sheeva64 case top
GlobalScale Sheeva64 case top
GlobalScale Sheeva64 case top
GlobalScale Sheeva64 case top

The plastic case is generous in space and everything appears to have ample space to spare, but this does carry over the same case dimensions as the original SheevaPlug, the insides have been updated, however.

It is worth noting that the screw holes for the four screws holding the top and bottom halfs together appear to be a little soft, and not that deep, keep that in mind that you might not want to disassemble and reassemble too many times, the screw holes may be stripped.  The first time reassembling the screws did not seem to grip well and I may have already stripped mine out to a degree, so it is a good idea to keep that in mind for reassembling.

GlobalScale Sheeva64 case bottom with power supply
GlobalScale Sheeva64 case bottom with power supply
GlobalScale Sheeva64 case bottom with power supply
GlobalScale Sheeva64 case bottom with power supply

The power supply is very compact, but appears to be able to supply 900mA to the USB ports… not specific if that is total current between both ports, or the current for each port. There is a small cushion pushing up against the PCB, I believe to hold the power supply in place and avoid rattles.  The original SheevaPlug did have some occasional issues (a small failure rate) with failed power supplies, the part for the original SheevaPlug is available at this URL, https://www.globalscaletechnologies.com/p-48-sheevaplug-power-supply.aspx, but not 100% sure it is a suitable replacement for the Sheeva64.  I am hoping that improvements were made on the power supply to reduce the failure rate.

Besides the slight concerns about the power supply, for the $89 USD (non WiFi/Bluetooth) or $105 USB (WiFi/Bluetooth included) including internal power supply, it is not a bad price for a dual core 64-bit single board (all self contained) computer that can literally just be plugged in anywhere.

I will be digging into the u-boot and recovery methods in another post soon.  If, by chance, anyone has a bricked (u-boot is corrupted or gone) device before then, leave a comment below and I will see if I can provide you with what you need to recover the SPI flash on your Sheeva64.