Open Source modular IPM Controller firmware
Documentation: https://lnls-dig.github.io/openMMC
The following packages are needed in your system in order to compile the firmware:
- gcc-arm-none-eabi
- cmake
- cmake-gui (Optional)
gcc-arm-none-eabi can be installed from the pre-compiled files found at: https://launchpad.net/gcc-arm-embedded/+download or you can run the following command under Ubuntu:
sudo apt-get install gcc-arm-none-eabi
Next step is to clone this repository into your workspace.
git clone https://github.com/lnls-dig/openMMC
Create a new folder wherever is suitable
cd <build_folder>
Run CMake using the path to the repository folder as an direct argument and the flag -DBOARD=<board_name>
(at this moment, only afc
can be selected) ,-DVERSION=<board_version>
(3.1
or 4.0
) and -DBOARD_RTM=<rtm_name>
(8sfp
or lamp
) to configure the compilation scripts to your specific board hardware.
cmake <path_to_source> -DBOARD=<board_name> -DVERSION=<board_version> -DBOARD_RTM=<rtm_name>
Example:
cmake ~/openmmc/ -DBOARD=afc -DVERSION=3.1 -DBOARD_RTM=8sfp
After creating the build files with CMake, you can compile the firmware using make
, optionally setting the VERBOSE flag to 1 if you wish to see all the compilation commands
make [VERBOSE=1]
Both a .elf
file and a .bin
file will be generated in the out
folder. You can use any one you prefer to program your processor.
To clean the compilation files (binaries, objects and dependence files), just run
make clean
To make a debug build (to include symbols into elf file, turn off optimizations, etc.) add -DCMAKE_BUILD_TYPE=Debug
option to cmake
command. Example:
cmake ~/openmmc/ -DBOARD=afc -DVERSION=3.1 -DCMAKE_BUILD_TYPE=Debug
Flashing the MMC microcontroller via SWD/JTAG is supported for CMSIS-DAP and Jlink compatible probes through OpenOCD. You can specify the debug probe with the flag -DDEBUG_PROBE=<probe_name>
, valid options are cmsis-dap
(default), jlink
, digilent_jtag_hs3
and xvc
(support is not merged to the official OpenOCD source yet, so you build our patched version: https://github.com/lnls-dig/openocd/tree/fix-afcv3-flashing).
If you want to use the JTAG protocol instead of SWD, you can use -DOPENOCD_TRANSPORT=jtag
.
cmake ~/openmmc/ -DBOARD=afc -DVERSION=3.1 -DDEBUG_PROBE=cmsis-dap -DOPENOCD_TRANSPORT=swd
This will create a openocd.cfg
file in <build_dir>/out
.
To flash the application firmware only, run
make program_app
To flash the bootloader firmware only, run
make program_boot
If you want to erase the whole Flash and flash both firmwares:
make program_all
It is possible to flash the MMC microcontroller with the LPC-Link1 adapter by using the probe/lpclink1-flash.sh
script. You will need to have MCUXpresso IDE installed in your computer. This script assumes that the MCUXpresso binaries are located in /usr/local/mcuxpressoide/ide/binaries/
by default, you can change this path by setting the MCUXPRESSOIDE_BIN
environment variable.
./probe/lpclink1-flash.sh firmware.bin LPC1764 0x0000
⚠️ Disclaimer: Due to f06f69f, this alternative is deprecated and ipmitool should be used instead, except when updating the OpenMMC application from older versions.
Another option to program the MMC microcontroler is through HPM-Downloader. First, download and compile the HPM. In it's root directory, in order to load the firmware, run
./bin/hpm-downloader --no-retries --ip <MCH_IP_address> --slot <slots_to_be_updated> --component 1 <path_to_openMMC.bin>
Due to timeout on sending packets, it may fails sometimes, with the Completion Code 0xc3
in the ACTIVATE_FIRMWARE_UPLOAD
process. If it occurs, just try the same command again, until you receive the Upgrade success
message.
Now, you have to upload the bootloader, since the old bootloader is incompatible. To succeed this, run
./bin/hpm-downloader --ignore-component-check --ip <MCH_IP_address> --slot <slots_to_be_updated> --component 0 <path_to_newboot.bin>
It's also important to mention that you can use the --help
command in case of doubt about how to use the HPM commands. Run
./bin/hpm-downloader --help
⚠️ Disclaimer: Due to e88b30b, the ipmitool may fail when trying to upgrade the firmware from v1.5.0. You can use a modified ipmitool utility as a workaround, setting the variablemax_rq_size
to 20.
After 5631857, it's possible to program the firmware and the bootloader through ipmitool, for previous releases, you still need to use hpm-downloader. In order to use it, you have to install the ipmitool, and then generate .hpm files from OpenMMC.bin
and newboot.bin
. To generate .hpm
files, you will need to use bin2hpm. If you have bin2hpm in your $PATH
, the .hpm
files will be automatically generated for you, provided you build from 0095b14 or more recent versions.
After generate the files, you can use the following commands to program the MMC microcontroller.
To upgrade the firmware, use
ipmitool -I lan -H host_name_mch -A none -T 0x82 -m 0x20 -t (112 + num_slot*2 in hexadecimal) hpm upgrade openMMC.hpm activate
To upgrade the bootloader, use
ipmitool -I lan -H host_name_mch -A none -T 0x82 -m 0x20 -t (112 + num_slot*2 in hexadecimal) hpm upgrade newboot.hpm activate
⚠️ Disclaimer: Only supported in AFCv4.0.2
In AFCv4, it's possible to program the firmware and bootloader via serial port using nxpprog. In order to use it, install nxpprog and then execute the following commands: To upgrade the application, use
./nxpprog.py <serial_device> <path_to_openMMC.bin> --addr 0x20000 --control
To upgrade the bootloader, use
./nxpprog.py <serial_device> <path_to_newboot.bin> --control
It is possible to debug the MMC firmware using OpenOCD and GDB. First, connect OpenOCD with the debug probe using the out/openocd.cfg
file generated by cmake in the build directory:
openocd -f out/openocd.cfg
Then open GDB:
$ arm-none-eabi-gdb out/openMMC.elf -ex "target extended-remote localhost:3333"
Now you can use the typical GDB commands to inspect the program flow and variables. Some useful commands when interacting with a microcontroller trough OpenOCD are listed below:
(gdb) monitor reset halt # Resets the microcontroller and immediately halts
(gdb) monitor reset run # Resets the microcontroller and starts executing
(gdb) load # Reload the firmware into flash
The IPMI allow us to create custom commands according to the project needs. ipmitool can be used to send the commands
It is possible to monitor the MMC's memory usage via IPMI. To obtain the total free heap use command 0x01, netfn_id 0x32. The returned data will be the number of free heap bytes, encoded as a 32 bits unsigned integer, little-endian.
ipmitool -I lan -H mch_host_name -A none -T 0x82 -m 0x20 -t (112 + num_slot*2) raw 0x32 0x01
After loading a new firmware, you can use an ipmi command to read its commit hash to ensure that the running version is the one you want. The command is the above:
ipmitool -I lan -H mch_host_name -A none -T 0x82 -m 0x20 -t (112 + num_slot*2) raw 0x32 0x02
After 7a919489 the clock switch configuration is no longer hardcoded for each board. Instead, it must be configured through an IPMI command.
For the AFC v3.1 (ADN4604ASVZ) you can use the script for generate the configuration, and use the json configuration for AFCv3.1-BPM or AFCv3.1-Timing. If you want to generate a new configuration, use the following scheme:
- Port I/O (bit 7): Use it to configure the port as an input ('0') or output ('1'). Unused ports should be left configured as inputs;
- Output Port Signal Source (bits 0 to 3): Select the input port for the respective output port.
For the AFC v4 (IDT 8V54816) you can use the following scheme: For the AFC v4.0 (IDT 8V54816) you can use the script for generate the configuration, and use the json configuration for AFCv4.0-FOFB. If you want to generate a new configuration, use the following scheme:
- Port I/O (bit 7): Use it to configure the port as an input ('0') or output ('1'). Unused ports should be left configured as inputs;
-
Termination On/Off (bit 6): Use to set the internal termination. '0' is off (high-impedance), '1' is on (100
$\Omega$ ) - Polarity (bit 5): Set the channel polarity. '0' for inverted, '1' for non-inverted
- Output Port Signal Source (bits 0 to 3): Select the input port for the respective output port.
The command to write the configuration is the above:
ipmitool -I lan -H mch_host_name -A none -T 0x82 -m 0x20 -t (112 + num_slot*2) raw 0x32 0x03 <configuration_array_in_hex>
To read the actual configuration, use:
ipmitool -I lan -H mch_host_name -A none -T 0x82 -m 0x20 -t (112 + num_slot*2) raw 0x32 0x04