Getting started to Motorola MDK Snap

I received the Motorola MDK from Motorola (thank you guys!), it is used to develop Snap covers for Moto Z, Moto Z Play, Moto Z2, etc and decided to test it.

First we need to understand the names that Motorola refers to each piece of hardware. There is a very good introduction here: https://developer.motorola.com/build/mdk-user-guide

It starts with the Reference Moto Mod (AKA Hat), this is a base cover that you put in the back of your smartphone. This Reference Moto Mod has a 80-pin connector where other modules can be connected, these other modules are called Personality Cards. Some example of Personality Cards: Sensor Card, Battery Card, Audio Card, Display Card, Perforated Board, etc.

For each of these Personality Cards Motorola has an Android Application example that you will be instructed to download when you plug the Reference Moto Mod on your smartphone with that Personality Card already inserted on it.

The Battery Card is a little bit tricker. It comes with 0% of battery and it will charge only if you download the Battery Android Application and connect the USB C cable in your phone. Also I noticed that it has some BUGs: first time it appeared charging but the percentage level got stuck at 1%. After 1h it still at 1% then I remove the charge cable and plugged it again and it started to work. I needed to repeat this process about three time because it got stuck at other levels until the battery charging was complete.

Next step was the firmware compilation. I followed this tutorial:

https://www.element14.com/community/groups/moto-mods/blog/2017/05/05/moto-mods-developer-part-3-firmware-setup

Everything compiled fine, but this guy is not using the OpenOCD to flash the firmware. He decided to use the Motorola MDK Utility to flash the firmware in the MDK.

But the Motorola also has a page explaining how to flash the firmware using the OpenOCD:

https://developer.motorola.com/build/tools/debug-and-log

Basically all you need to do is to change the DIP-Switch B4 to position ON and use the USB C cable connected to USB port #1 (the USB port near the Power Button of Moto Z).

Initially I decided to test the OpenOCD without a Personality Board connected and I got this message:

$ openocd -f board/moto_mdk_muc.cfg
Open On-Chip Debugger 0.10.0-dev-00346-gd3d86cc (2017-11-09-18:31)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : FTDI SWD mode enabled
srst_only separate srst_nogate srst_push_pull connect_deassert_srst
srst_only separate srst_nogate srst_push_pull connect_deassert_srst
adapter speed: 500 kHz
adapter_nsrst_delay: 100
srst_only separate srst_nogate srst_push_pull connect_deassert_srst
cortex_m reset_config sysresetreq
Info : clock speed 500 kHz
Info : SWD DPIDR 0x2ba01477
Info : SWD DPIDR 0x2ba01477
Info : SWD DPIDR 0x2ba01477
Info : SWD DPIDR 0x2ba01477
...
Info : SWD DPIDR 0x2ba01477
Info : SWD DPIDR 0x2ba01477
Info : SWD DPIDR 0x2ba01477
Error: Could not find MEM-AP to control the core

Then I tested it again using the Sensor Card connected to Reference Moto Mod and repeated the command. Now it worked as expected:

$ openocd -f board/moto_mdk_muc.cfg
Open On-Chip Debugger 0.10.0-dev-00346-gd3d86cc (2017-11-09-18:31)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : FTDI SWD mode enabled
srst_only separate srst_nogate srst_push_pull connect_deassert_srst
srst_only separate srst_nogate srst_push_pull connect_deassert_srst
adapter speed: 500 kHz
adapter_nsrst_delay: 100
srst_only separate srst_nogate srst_push_pull connect_deassert_srst
cortex_m reset_config sysresetreq
Info : clock speed 500 kHz
Info : SWD DPIDR 0x2ba01477
Info : stm32l4x.cpu: hardware has 6 breakpoints, 4 watchpoints

I decided to test the other board config script that should be used to reset the MCU:

$ openocd -f board/moto_mdk_muc_reset.cfg
Open On-Chip Debugger 0.10.0-dev-00346-gd3d86cc (2017-11-09-18:31)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : FTDI SWD mode enabled
srst_only separate srst_nogate srst_push_pull connect_deassert_srst
srst_only separate srst_nogate srst_push_pull connect_deassert_srst
adapter speed: 500 kHz
adapter_nsrst_delay: 100
srst_only separate srst_nogate srst_push_pull connect_deassert_srst
cortex_m reset_config sysresetreq
Info : clock speed 500 kHz
in procedure 'init' 
in procedure 'ocd_bouncer'

It doesn’t work, strange.
Update: It was not working to reset because the Dip Switch B3 was in the position ON, changing it to position OFF fixed the issue.

Next I tried openocd with the HSB but it didn’t work:

$ openocd -f board/moto_mdk_hsb.cfg
Open On-Chip Debugger 0.10.0-dev-00346-gd3d86cc (2017-11-09-18:31)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
trst_only separate trst_push_pull
adapter speed: 10000 kHz
Info : ftdi: if you experience problems at higher adapter clocks, try the command "ftdi_tdo_sample_edge falling"
Info : clock speed 10000 kHz
Error: JTAG scan chain interrogation failed: all ones
Error: Check JTAG interface, timings, target power, etc.
Error: Trying to use configured scan chain anyway...
Error: APBridge.cpu: IR capture error; saw 0x0f not 0x01
Warn : Bypassing JTAG setup events due to errors
Error: Invalid ACK (7) in DAP response
Error: JTAG-DP STICKY ERROR
Error: Invalid ACK (7) in DAP response
Error: JTAG-DP STICKY ERROR
Error: Invalid ACK (7) in DAP response
Error: JTAG-DP STICKY ERROR
Error: Invalid ACK (7) in DAP response
Error: JTAG-DP STICKY ERROR
Error: Invalid ACK (7) in DAP response
Error: JTAG-DP STICKY ERROR
Error: Invalid ACK (7) in DAP response
Error: JTAG-DP STICKY ERROR
Error: Invalid ACK (7) in DAP response
Error: JTAG-DP STICKY ERROR
Error: Invalid ACK (7) in DAP response
Error: JTAG-DP STICKY ERROR
Error: Invalid ACK (7) in DAP response
Error: JTAG-DP STICKY ERROR
Error: Invalid ACK (7) in DAP response
Error: JTAG-DP STICKY ERROR
Error: Could not initialize the debug port
Error: Target not examined yet

I decided to run the “openocd -f board/moto_mdk_muc.cfg” again and flash the firmware:

$ openocd -f board/moto_mdk_muc.cfg
Open On-Chip Debugger 0.10.0-dev-00346-gd3d86cc (2017-11-09-18:31)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : FTDI SWD mode enabled
srst_only separate srst_nogate srst_push_pull connect_deassert_srst
srst_only separate srst_nogate srst_push_pull connect_deassert_srst
adapter speed: 500 kHz
adapter_nsrst_delay: 100
srst_only separate srst_nogate srst_push_pull connect_deassert_srst
cortex_m reset_config sysresetreq
Info : clock speed 500 kHz
Info : SWD DPIDR 0x2ba01477
Info : stm32l4x.cpu: hardware has 6 breakpoints, 4 watchpoints

I opened a new Linux terminal and ran the telnet command to flash the firmware.

First the bootloader:

$ telnet localhost 4444

> halt
stm32l4x.cpu: target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x61000000 pc: 0x2000050c msp: 0x20016fe4

> flash write_image erase unlock boot_hdk.bin
auto erase enabled
auto unlock enabled
no flash bank found for address 0
wrote 0 bytes from file boot_hdk.bin in 0.000224s (0.000 KiB/s)

As you can see the “flash write_image” command failed, I need to pass the flash memory position where the firmware will be flashed:

> flash write_image erase unlock boot_hdk.bin 0x08000000
auto erase enabled
auto unlock enabled
block write succeeded
wrote 26624 bytes from file boot_hdk.bin in 1.142701s (22.753 KiB/s)
> 

It is important to note that the “boot_hdk.bin” file needs to be in the same directory where “openocd” command was executed, not in the directory where you executed the telnet command.

The next step is to flash the nuttx.tftf inside the SPI Flash that can be accessed by the MCU STM32L476 and the HSB (High Speed Bridge).

According to https://developer.motorola.com/build/tools/debug-and-log we have three options:

1) Flashing the firmware from MCU STM32L476 using standalone commands:

$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> halt
> hsb_flash_enable
> flash erase_sector 1 0 2047
flash bank 1 does not exist

This option failed!

Let see the banks:

> flash banks
#0 : stm32l4x.flash (stm32l4x) at 0x08000000, size 0x00100000, buswidth 0, chipwidth 0
> 

So, the OpenOCD is only able to see its internal flash, but the external SPI Flash.

2) Flashing the firmware from MCU STM32L476 using a specific command:

$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> halt
> hsb_flash_program nuttx.tftf
flash bank 1 does not exist

> 

This option also failed.

3) Flashing the HSB from HSB:

$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> halt
> flash erase_sector 0 0 2047
device id = 0x10076415
flash size = 1024kbytes
ERROR: last sector must be <= 511

Also failed. So there is some issue that is preventing OpenOCD to see external SPI Flash.

Some tricks:

1) Fixing “SWD DPIDR 0x2ba01477” error:

If you run “openocd” and still getting many “Info : SWD DPIDR 0x2ba01477” you can connect to nuttx shell over /dev/ttyUSB2 using minicom or your preferred serial console tool and type ENTER two times. You will get the “nsh>” prompt.

Then type “sleep 10000” to avoid the MCU to enter in the sleep mode again:

nsh> sleep 10000

2) Fixing the “error writing to flash”

$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger

> halt
stm32l4x.cpu: target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x61000000 pc: 0x080154e0 msp: 0x20001ec0

> flash write_image erase unlock boot_hdk.bin 0x08000000
auto erase enabled
auto unlock enabled
device id = 0x10076415
flash size = 1024kbytes
flash write algorithm aborted by target
error executing stm32l4 flash write algorithm
flash write failed = 000000a0 at address 08000008
block write failed
error writing to flash at address 0x08000000 at offset 0x00000000

In this case the “unlock” in the “flash write_image erase unlock boot_hdk.bin 0x08000000” wasn’t enough to fix the issue.

You can use the “stm32l4x unlock 0” :

> stm32l4x unlock 0
device id = 0x10076415
flash size = 1024kbytes
stm32l4x unlocked.
INFO: a reset or power cycle is required for the new settings to take effect.

> halt
stm32l4x.cpu: target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x2000171c msp: 0x20016fe4

> flash write_image erase unlock boot_hdk.tftf 0x08000000
auto erase enabled
auto unlock enabled
device id = 0x10076415
flash size = 1024kbytes
block write succeeded
wrote 26624 bytes from file boot_hdk.bin in 1.142701s (22.753 KiB/s)
> 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s