ACS Kryten How-to Guide
A guide to running Flightkit software on the AAC Clyde Space Kryten onboard computer.
1. Introduction
The AAC Clyde Space (ACS) Kryten onboard computer (OBC) is built around an ARM Cortex-M3-based system-on-chip (SoC) with integrated flash, I2C, SPI, UART, CAN and GPIO peripherals. The board hosts additional persistent memory and telemetry peripherals.
Flightkit supports all of the key parts of the OBC.
This guide provides an overview of:
-
How images are stored on the Kryten.
-
How images are run on the Kryten.
-
The main component types included in the
FlightkitFoundationbundle which enable you to interact with the board’s drivers. -
How to build missions for the Kryten.
-
How to program the Kryten.
-
How to run unit tests on the Kryten.
-
How to troubleshoot the Kryten.
2. Technical Background
In this section we give an overview of the Kryten support provided with
FlightkitFoundation. This includes details on how the Kryten’s onboard memory
is used, how different software images are managed, and the different component
types we provide for interacting with the board’s peripherals.
2.1. The Memory Map
The memory map of the Kryten is an extension of the standard map created by the SmartFusion2 device that the OBC is based on (which is in turn a specialisation of the standard ARM Cortex-M3 memory map).
The main code execution area is at the bottom of the memory map. This region is actually a mirror of either the internal flash, or the MRAM code space, depending on whether the Kryten is running a failsafe or primary image.
|
Older Kryten computers only had 256KiB of onboard flash - Flightkit supports
this via the |
| Range | Size | Usage | MPU Attributes |
|---|---|---|---|
0x00000000 |
512 KiB (failsafe) |
Execution mirror. Code is executed from this section. At boot the relevant code section (either failsafe, primary1 or primary2) is "mirrored" here by the board support package. |
RO |
The internal 64KiB SRAM is used for critical code and data which must survive an MRAM error (and therefore an MRAM power cycle). Additionally, the system interrupt stack is also placed in SRAM.
| Range | Size | Usage | MPU Attributes |
|---|---|---|---|
0x20000000 |
16 KiB |
SRAM code. Code which must be executable when the MRAM is not available is loaded here at boot. e.g. code to control formatting of the MRAM devices |
RO |
0x20004000 |
16 KiB |
SRAM data, including from CRT. Used for special data which must be accessible when the MRAM is not available. |
RW, XN |
0x20008000 |
32 KiB |
Main stack (used only for interrupt handling) |
RW, XN |
The internal non-volatile flash memory is used to hold the failsafe image.
| Range | Size | Usage | MPU Attributes |
|---|---|---|---|
0x60000000 |
512 KiB |
On board flash. Used for storing the failsafe software image. Execution is from the mirrored section starting at 0x00000000. |
RW, XN |
The non-volatile MRAM is used for four distinct purposes:
-
Primary image storage
-
Main working memory (overwritten on each boot)
-
Record stores for critical data and event logging
-
Persistent component configuration data
| Range | Size | Usage | MPU Attributes |
|---|---|---|---|
0xA0000000 |
1 MiB |
Primary1 software image storage. Execution is from the mirrored section starting at 0x00000000. |
RO, XN |
0xA0100000 |
1 MiB |
Primary2 software image storage. Execution is from the mirrored section starting at 0x00000000. |
RO, XN |
0xA0200000 |
2 MiB |
Working MRAM. This area is used for .data and .bss sections, whether running failsafe, primary1 or primary2. |
RW, XN |
0xA0400000 |
3.5 MiB |
Persistent MRAM used for data logging |
RW, XN |
0xA0780000 |
512 KiB |
Persistent MRAM used for configuration data |
RW, XN |
Additionally, the Kryten provides 4 GiB of flash but this is not directly memory mapped. This is typically used to host a file system.
2.2. The Boot Process
As indicated in the previous section, the Kryten hardware has two distinct memories which can be used to hold flight software. A single failsafe image can be stored in the SoC’s embedded flash memory, and two primary images can be stored in its EDAC-protected MRAM.
The flash memory is more limited than MRAM, so in practice, failsafe images tend to be cut down versions of the primary images.
Failsafe images should not be used for nominal operations during a mission, they should only be used as a means to recover the satellite if the primary images become corrupted or unstable. They should therefore be kept simple to ensure correct operation.
Primary images on the other hand are upgradeable, so they can safely include more complex functionality. These images are typically responsible for carrying out the mission.
The following procedure is used to select and boot flight software images:
-
From hard reset:
-
Execute the bootloader code in the failsafe image.
-
-
Select the next boot image:
-
Iterate through each of the images' boot configuration records.
-
Select the image which is stable and has the highest priority as the next boot image.
-
Verify the next boot image’s data against its stored CRC. The failsafe image is immutable and always passes this check.
-
If the CRC mismatches, mark the image as unstable and select another next boot image.
-
-
Prepare image for boot
-
If the next boot image is not the failsafe image, mark it as unstable. The booted image may mark itself as stable again after booting. The stability flag mechanism prevents boot loops of unstable primary images.
-
-
Boot the image
-
If the next image is not the failsafe image, boot to it. Otherwise continue execution from the failsafe image.
-
The drivers.kryten.periph.OBC component type can be used to control the
contents of the primary images, and to manipulate the boot configuration
records to control which image will be booted next. This will be discussed
further in the following sections.
2.3. Component Types
The FlightkitFoundation bundle includes a number of Kryten-specific component
types which can be used by your flight software to interact with the peripherals
and drivers on board the computer.
2.3.1. The OBC Component Type
The drivers.kryten.periph.OBC component type provides access to various core
functions of the Kryten hardware. This includes powering on and off onboard
subsystems, querying firmware and revision information, and controlling the
running of flight software images.
Given the latter point, it is vital that you include an instance of this component type in your failsafe image slot if you wish to be able to switch images during operation.
The component type uses the following convention when referring to the different image slots:
-
0: The failsafe image
-
1: The primary1 image
-
2: The primary2 image
To prevent boot loops from occurring, primary images are marked as unstable during the boot process. This prevents them being considered during the next boot cycle. Automation can be set up in the deployment type to mark them as stable again following a successful boot. Alternatively, the operator can carry this out manually when contact with the spacecraft is achieved.
2.3.2. The Watchdog Component Type
The Watchdog component manages the Kryten’s onboard 555 timer-based watchdog circuit.
It has two periodic tasks, a restore task and a kick task.
The restore task resets the number of times the watchdog timer must be kicked
before a watchdog reset is performed. This must be set to the lowest task
priority in the deployment type.
The kick task handles the kicking of the watchdog timer. This must be set to
the highest task priority in the deployment type.
This combination of task priorities ensures that the watchdog timer continues to be kicked so long as there is enough "credit" available. If you wish to learn more, refer to the component type’s documentation.
2.3.3. Pin Configuration, GPIO and Peripherals
The Kryten’s IO pins on the CSK can be configured for many different functions. At start up, the flight software configures all pins on the CSK to be inputs. During the deployment initialisation phase, pin functions may be altered depending on which driver component instances exist within the deployment instance, and how they have been initialised. Some instances may require the use of specific pins to fulfil their obligations:
-
drivers.kryten.io.bus.Serialanddrivers.kryten.io.bus.FastSerialmay claim pins for serial TX and RX. -
drivers.kryten.io.bus.SPIControlleranddrivers.kryten.io.bus.SPIPeripheralmay claim pins for MISO, MOSI, SCLK and SS. -
drivers.kryten.io.GPIOmay claim pins for general I/O purposes. -
drivers.kryten.periph.PPSmay claim pins for use as PPS input and output.
Note that pins are claimed by component instances unconditionally. If component instance B is instantiated after component instance A, then B’s local initialisation will happen after A’s. This means that any pins that B claims which A has already claimed will end up having B’s settings applied. Debug output during deployment initialisation can be used to check for collisions in pin allocation.
The Kryten board provided in the FlightkitFoundation bundle references pins
by their position on the CSK as opposed to the inconsistent numbering and
naming provided by ACS. For example H1.1 is referred to using the pin identifier
BOARD_PINMUX_PINID_H1_1 as opposed to GPIO_0. Similarly H1.17 is referred
to as BOARD_PINMUX_PINID_H1_17 as opposed to GPIO_10.
The available pin configuration options are determined by the version of firmware that is running on the Kryten.
The Kryten board provided in the FlightkitFoundation bundle is configured
such that it targets Kryten firmware 7725 RevG m2p0 by default. This setting
can be overwritten for your own missions by redefining the
BOARD_CONFIG_FIRMWARE_ID symbol in your mission’s lib_config/meson.build
file to your desired version number. Note that you must set this variable using
hex directly. To target 7725 RevI m1p0 firmware, add the following line to your
lib_config/meson.build file:
boards_Kryten_c_args += '-DBOARD_CONFIG_FIRMWARE_ID=0x1E2D0910'
The first 4 characters (1E2D) are the part number (7725), the next 2 (09)
are the major revision (RevI) and the final two (1 and 0) are the minor and
patch revisions (1 and 0).
3. Working With the Kryten
This section outlines various procedures which you will need to use when working with the Kryten.
3.1. Installing the Toolchain
Flightkit support for the ACS Kryten requires you to install version
10.3-2021.10 of ARM’s arm-none-eabi toolchain.
|
This is the same version as required to use Flightkit’s EnduroSat OBC support, so if you have already installed it via the EnduroSat OBC How-to Guide then you can skip this section. |
|
A very similar version of this toolchain is available directly from the Ubuntu package repositories. However, it supplies a C standard library which is built without support for features which our Kryten board support code uses. As a result you should not use the toolchain in the Ubuntu package repositories. |
Once downloaded:
-
Extract the archive. The
/optdirectory is a common location used for storing external toolchains. -
Add the extracted
…/gcc-arm-none-eabi-10.3-2021.10/bindirectory containing the toolchain executables to yourPATH. -
Verify that the toolchain was successfully added to the path by restarting your shell and running the following command:
arm-none-eabi-gcc --version
3.2. Building the Demo Mission
With the tooling successfully installed, you can build flight software to run
on the Kryten. The following steps will guide you through the process for
building the KrytenDemo mission from the FlightkitFoundation bundle:
-
Create a new workspace for building the mission in.
-
Require the
FlightkitFoundationbundle so that the tooling can access its contents by running the following command:hfk workspace bundle require FlightkitFoundation -
Build the
KrytenDemomission from theFlightkitFoundationbundle by running the following command:hfk mission build KrytenDemo
This builds all the deployment instances in the mission, and generates a mission
database for interacting with them via Helix Lab. The binaries and database can
be found in output/bundles/FlightkitFoundation/X.Y.Z/missions/KrytenDemo/,
where X.Y.Z is the version of FlightkitFoundation you are using.
The KrytenDemo mission is configured to build deployment instances for each
of the Kryten’s image slots.
When developing missions of your own, you can configure them to target whichever
image slots you desire by setting your deployment instances' <BuildConfig>
elements accordingly.
The list of available build configurations provided by a particular bundle can be determined by inspecting the bundle’s documentation.
3.3. Connecting to the Kryten
There are three main connections that you will need to set up when working with the Kryten: the telemetry and telecommand (TMTC) link, the debug link and the programmer.
The following sections will explain how to set up each one.
3.3.1. TMTC Link
The TMTC link is used to transport telemetry and telecommand (TMTC) packets between the Kryten and the PC running Helix Lab.
The deployment instances within the KrytenDemo mission are configured to
provide the TMTC link using UART A with LVTLL signal levels.
To set up the TMTC link for the KrytenDemo deployment instances:
-
Connect the TX line of a suitable serial to USB adapter to pin 33 of the H1 header.
-
Connect the RX line of the same serial to USB adapter to pin 35 of the H1 header.
-
Connect the ground line of the same serial to USB adapter to one of the ground pins on the H1 header.
-
Connect the USB side of the serial to USB adapter to the host PC running Helix Lab.
The deployment instances in the KrytenDemo mission are configured with the
following TMTC serial settings:
-
57600 baud
-
8 data bits
-
No parity bit
-
1 stop bit
-
No flow control
Helix Lab is only capable of exchanging TMTC packets with a spacecraft via a
TCP server. For this reason, you will also need to configure your host PC to
forward packets destined for the TCP port that Helix Lab transmits to to the
serial port that your TMTC link is connected to, and vice versa. There are many
ways this can be achieved, however we recommend you use a tool such as
ser2net or socat. If you are unfamiliar with how to use these tools, refer
to their documentation online.
3.3.2. Debug Link
The debug link is used for transporting debug information from the Kryten to the PC where it can be displayed.
The deployment instances within the KrytenDemo mission are configured to use
UARTD with LVTTL voltage levels for debug output.
To set up the debug link for the KrytenDemo deployment instances:
-
Connect the RX line of a suitable serial to USB adapter to pin 8 of the J6 header.
-
Connect the ground line of the same serial to USB adapter to one of the ground pins on the J6 header.
-
Connect the USB side of the serial to USB adapter to the host PC.
To view the debug produced by the board on the host PC run a terminal emulator,
such as minicom.
The deployment instances in the KrytenDemo mission are configured with the
following debug serial settings:
-
57600 baud
-
8 data bits
-
No parity bit
-
1 stop bit
-
No flow control
You must apply these settings to your terminal emulator so that it interprets the incoming data correctly. The debug produced by the board uses linux line endings, so you may also need to enable implicit carriage returns in your terminal emulator to view the data properly.
3.3.3. Programmer
The programmer is used to program binaries to the board.
Either an Olimex ARM-USB-TINY-H JTAG or a SEGGER JLink programmer can be used to program the ACS Kryten.
Both programmers come with their own set of hardware which consists of a USB-A to USB-B cable, the programmer itself, and a female to female JTAG ribbon cable.
To set up the programmer link:
-
Connect the USB-A side of the USB-A to USB-B cable to the host PC that the binaries are being programmed from.
-
Connect the USB-B side of the USB-A to USB-B cable to the programmer.
-
Connect one side of the female to female JTAG ribbon cable into the programmer.
-
Connect each of the required pins from the other side of the female to female JTAG ribbon cable to their respective pins on the Kryten’s J5 header.
3.4. Programming the Kryten
Failsafe and primary images must be programmed via the Olimex ARM-USB-TINY-H JTAG or SEGGER JLink programmer. Flightkit includes a programming script for the Kryten which provides a simple front-end to the OpenOCD tool. OpenOCD is installed when you install Flightkit.
|
Primary images cannot yet be uplinked using Helix Lab via the TMTC link. Support for uplinking primary images with Helix Lab will be added in future. |
The following sections explain how to program failsafe and primary images. The instructions provided assume that you are programming the board from the same machine that you have used to build the binaries.
3.4.1. Programming a Failsafe Image
There must always be a failsafe image programmed on the Kryten platform. To boot into a primary image, a failsafe image is required both as the starting point, and a fall-back.
The following procedure demonstrates how to program a failsafe image using the
KrytenDemo mission’s OBCDemo deployment instance. The same approach can be
used for programming any binary that has been built for the failsafe image slot.
To program a binary to the failsafe image slot:
-
Make sure your Kryten is powered from a stable power supply. If you are powering the Kryten via an ACS EPS make sure the EPS watchdog timer is increased to avoid power interruptions during programming.
-
Program the binary using the following command, ensuring to replace
X.Y.Zwith the version ofFlightkitFoundationyou are using. If using the SEGGER JLink programmer, include--debugger=jlinkwithin the command:hfk-kryten-program failsafe output/bundles/FlightkitFoundation/X.Y.Z/missions/KrytenDemo/OBCDemo/Default/Default.bin -
To verify that the image has been programmed successfully:
-
Open a terminal emulator, such as
minicom, on the host PC to display the board’s debug output. -
Power cycle the board to force a reboot.
-
Inspect the debug output displayed on the terminal emulator. If programmed successfully, it should show similar output to what is shown below.
INF: Deployment.c:599 Running deployment: INF: Deployment.c:600 - Deployment instance: Default INF: Deployment.c:601 - Deployment type: acs.kryten.OBCDemo INF: Deployment.c:602 - Target: OBCDemo INF: Deployment.c:603 - Mission: KrytenDemo INF: Deployment.c:773 Deployment initialisation successful
-
3.4.2. Programming a Primary Image
Primary images can be programmed using a similar approach to programming failsafe images, with the addition of one extra step.
The following procedure demonstrates this by programming the Primary1 deployment
from the KrytenDemo mission’s OBCDemo target into the Kryten’s primary1 slot.
This mission is found in the FlightkitFoundation bundle.
Note that binaries programmed to the primary1 slot must be built for that slot.
We provide the KrytenPrimary1 build configuration for this purpose. To program a
binary to the primary2 slot, the KrytenPrimary2 build configuration must be used
instead. Build configurations are set on a per-deployment basis in the mission.xml.
To program a binary to the primary1 image slot:
-
Generate a tag file for the binary by running the following command. The purpose of the tag file is to provide additional metadata such as binary length and CRC, which is required when programming to the primary image slots:
hfk-kryten-gen-crc --realign --tag output/bundles/FlightkitFoundation/X.Y.Z/missions/KrytenDemo/OBCDemo/Primary1/Primary1.bin -
Program the binary using the following command, ensuring to replace
X.Y.Zwith the version ofFlightkitFoundationyou are using. If using the SEGGER JLink programmer, include--debugger=jlinkwithin the command. Also ensure the slot which you are programming to corresponds with the build config that was used to build the binary:hfk-kryten-program primary1 output/bundles/FlightkitFoundation/X.Y.Z/missions/KrytenDemo/OBCDemo/Primary1/Primary1.bin
3.5. Switching Images
The following section details the procedure for switching between different images during operation. It explains how you can switch from a failsafe image to a primary1 image, however the same process can be applied to switch between any two images.
Once a valid primary image has been successfully programmed/uplinked to the primary1 slot, it can then be booted into by completing the following steps:
-
Ensure the Kryten board is running the failsafe image, and connect to it using Lab.
-
(Optional) Find the
drivers.kryten.periph.OBCinstance’simageValidparameter. Set both the first row and last row fields to1, then perform a get on the parameter. This will return a flag indicating if the stored CRC for the image in the primary1 slot matches its expected value. In other words, it will confirm whether the image is valid. If it is found to be invalid, any attempt to boot into it will fail. -
Find the
drivers.kryten.periph.OBCinstance’simageIsStableparameter. Set both the first row and last row fields to1, then perform a set on the parameter, passing the value1. This marks the image in the primary1 slot as stable. Images must be marked as stable for them to be considered during the boot process. The failsafe image is permanently marked as stable, so it will always be booted into if none of the other images are marked as stable. -
Find the
drivers.kryten.periph.OBCinstance’simagePriorityparameter. Set both the first row and last row fields to1, then perform a set on the parameter, passing the value2. This sets the priority value of the image in the primary1 slot to2. The image with the highest priority value will be booted into during the boot process, so long as it is also marked as stable. The priority value of the failsafe image is always set to1, so if a primary image is intended to be booted into, its priority value must be set to a value greater than1. -
(Optional) Find the
drivers.kryten.periph.OBCinstance’snextBootImageparameter. Perform a get on the parameter. This will return the index of the image that the bootloader will attempt to boot into during the next boot cycle. It does not guarantee that the specified image will be booted into as it may fail if the image is not valid. -
Find the
drivers.kryten.periph.OBCinstance’sresetaction and invoke it. This will trigger the boot process resulting in thenextBootImagebeing booted into. If it fails to boot into thenextBootImagefor whatever reason, the boot process will fall back onto booting the next image in the list that has the highest priority, is found to be valid and is marked as stable. This process will repeat until an image is successfully booted into, ending with the failsafe image if required. -
(Optional) When booting into a primary image, the boot process will automatically clear the stability flag of the image it is booting into to prevent boot loops from occurring in the event that the primary image is corrupt or faulty. If you would like the same image to be booted into again during the next boot process, it can be marked as stable again by invoking the
markCurrentImageStableaction.
3.6. Running Unit Tests on the Kryten
When building unit tests in Flightkit, the tooling produces a binary which can be run on the platform in the same way that deployment instances can. The main difference is that unit tests are built on a 'per component type' basis, whereas deployment instances are built on a 'per mission basis'. This small detail requires unit tests to be built using a slightly different process to deployment instances, the steps of which are shown below.
The following steps demonstrate how unit tests for the Counter component type
can be built and run on the Kryten platform. The same process can be followed
for any component type:
-
Build the component type’s unit tests by running the following command. Notice that this example builds them for running in the primary1 image slot. Unit tests can be built to run in any image slot, however the primary slots can be programmed more quickly since they are stored in MRAM as opposed to the failsafe slot which is stored in flash, so we recommend taking this approach:
hfk component-type test Counter --build-config="KrytenPrimary1" --build-only -
Since the binary is going to be run in a primary image slot, a tag file must be generated for it. When generating the tag file, we can also mark the image as stable and set its priority to be greater than the failsafe image so that it is booted into instantly during start up. Run the following command to accomplish this, ensuring to replace
X.Y.Zwith the version ofFlightkitFoundationyou are using:hfk-kryten-gen-crc --realign --tag --priority=2 --stable output/bundles/FlightkitFoundation/X.Y.Z/library/component_types/Counter/KrytenPrimary1/CounterTest.bin -
Open a terminal emulator, such as
minicom, to display the debug output from the board. This will be used to display the unit test results. -
Program the binary using the following command, ensuring to replace
X.Y.Zwith the version ofFlightkitFoundationyou are using. If using the SEGGER JLink programmer, include--debugger=jlinkwithin the command:hfk-kryten-program primary1 output/bundles/FlightkitFoundation/X.Y.Z/library/component_types/Counter/KrytenPrimary1/CounterTest.bin
The unit tests should run automatically once programming is complete. Output similar to what is shown below should be displayed on your terminal emulator indicating the tests that have been run and their completion status.
library/component_types/Counter/test/Counter_Test.c:134:Counter_Test_initAndFini:PASS
DBG: Counter.c:215 CounterUnderTest: Reset action called
library/component_types/Counter/test/Counter_Test.c:141:Counter_Test_resetSuccessful:PASS
DBG: Counter.c:215 CounterUnderTest: Reset action called
library/component_types/Counter/test/Counter_Test.c:159:Counter_Test_incrementSuccessful:PASS
DBG: Counter.c:215 CounterUnderTest: Reset action called
library/component_types/Counter/test/Counter_Test.c:177:Counter_Test_decrementSuccessful:PASS
library/component_types/Counter/test/Counter_Test.c:203:Counter_Test_getConfigInsufficientResources:PASS
library/component_types/Counter/test/Counter_Test.c:218:Counter_Test_getConfigSuccess:PASS
library/component_types/Counter/test/Counter_Test.c:233:Counter_Test_setConfigInvalidParam:PASS
library/component_types/Counter/test/Counter_Test.c:249:Counter_Test_setConfigNewSuccess:PASS
library/component_types/Counter/test/Counter_Test.c:272:Counter_Test_setConfigDefaultSuccess:PASS
-----------------------
9 Tests 0 Failures 0 Ignored
OK
You may notice that the board performs a reboot after running the tests. This happens because the unit test binary has completed execution. Following the reboot, the failsafe image is then booted into since the unit test image will have been marked as unstable during its own boot process. This is expected behaviour.
If however, you chose to build the unit test binary for the failsafe slot, and programmed it to that slot, the unit tests would instead be executed repeatedly in an infinite loop since the image would continue to be rebooted, and the tests rerun, after each execution.
4. Troubleshooting
4.1. Faults
If you experience faults when running code on the Kryten, the information printed can help locate where the issue lies. Always include any fault output when contacting Bright Ascension support.
4.2. Wiping Corrupted MRAM
ACS run factory tests on each Kryten before it is shipped out. These tests can sometimes leave the MRAM corrupted. Corrupted MRAM will cause the memory controller to raise an exception within the CPU. This will result in the board boot looping. It’s possible to tell that this is the cause of boot looping by observing the debug output. In this case the debug output will show the EDAC MRAM error count to be non-zero. For example:
...
Flash EDAC non-correctable errors = 0
MRAM EDAC correctable errors = 12 (last at 0xA00FFFE0)
MRAM EDAC non-correctable errors = 36 (last at 0xA00FFFE4)
...
If this occurs, you can attempt to clear the errors by erasing the board’s MRAM. This can be done using the programming script, as follows:
hfk-kryten-program erase_mram