Search by Tags

Using K20 Companion MCU on Apalis TK1


Article updated at 29 Oct 2021
Compare with Revision


Using Support Included in BSP


The ADC driver makes use of the Industrial Input/Output (IIO) framework.

MXM3 Pin K20 Input IIO Device IIO Channel
AD0 PTB0\ADC0_SE8 iio:device0 in_voltage0_raw
AD1 PTB1\ADC0_SE9 iio:device0 in_voltage1_raw
AD2 PTB2\ADC0_SE12 iio:device0 in_voltage2_raw
AD3 PTB3\ADC0_SE13 iio:device0 in_voltage3_raw

The IIO framework exposes those inputs through the sysfs interface:

# cd /sys/bus/iio/devices/iio:device0/
# ls in*
in_voltage0_raw    in_voltage0_scale  in_voltage1_raw    in_voltage1_scale  in_voltage2_raw    in_voltage2_scale  in_voltage3_raw    in_voltage3_scale
# cat /sys/bus/iio/devices/device0/in_voltage0_raw

More information about the IIO framework:


Touch Screen

Touch screen controller is implemented in K20 software using internal ADC and external switching. It supports 4-wire resistive touch screens. Input device driver is implemented in kernel.


K20 GPIOs are available via sysfs. Since it's not the only GPIO controller available on Apalis TK1 GPIO numbers start with 856. More information on using sysfs GPIO subsystem can be found here.

To calculate the GPIO number use the following formula:

856 + 32 x (Character - 'A') + Digit

So GPIO A0 becomes 856, A7 becomes 863, B0 becomes 888, ...

Not all of the K20 GPIOs can be used, here's the list of available ones with corresponding sysfs id and edge connector pin

GPIO Assignment and MXM3 Locations

Erase Chip Without Reprogramming

In order to erase K20 and leave it empty replace firmware file (/lib/firmware/apalis-tk1-k20.bin) with a 1-byte length file.

Easiest way of doing it is to use dd:

dd if=/dev/zero of=/lib/firmware/apalis-tk1-k20.bin bs=1 count=1

after firmware is replaced all you need to do is reload the kernel module or reboot the board.

You should see:

apalis-tk1-k20 spi1.1: Chip fully erased.

in kernel log.

Force Firmware Reflashing

To force the kernel module to reflash the K20 use force_fw_reload=1 module parameter when loading

Run Without Verifying FW in k20

Module parameter fw_ignore=1 makes the kernel module assume that k20 is running the valid up-to-date image.


  • Kernel modules sources can be found in our kernel git:

  • K20 firmware is located in our FreeRTOS git:

Note: The previous git repository ( was retired and replaced by the new repository on github

Custom Firmware

It is possible to use custom software instead of the one provided by us.

Build System Setup

Source code provided on our Git is based on KSDK 2.0.0 (provided by NXP), that was updated to use FreeRTOS 10.1.1. To compile the code you'll need an armv7m GCC toolchain in your search path, you can get it directly from ARM here.

git clone --recursive -b master
cd FreeRTOS-Apalis-TK1-K20

For the older repo location use the following line to do the clone:

git clone git:// -b apalis-tk1-k20-freertos-v10
cd freertos-toradex

To build the checked out code:

mkdir build
cd build

Now you should have apalis-tk1-k20.bin binary file that can be flashed to the k20 via EzPort. File apalis-tk1-k20 should also be present, it's an elf file that is useful for debugging.


K20 and TK1 share single SPI bus and 4 GPIO lines as well as SPI CS and EzPort CS.

TK1 Has control over K20 reset line.

Loading Firmware

Using TK1 SPI with K20 EzPort

Here is an example of how to flash a new binary file into the K20 via EzPort directly from the TK1. You will have to use the gcc in the TK1 or cross-compile it from the host machine (and then send it to the device). Take into account that you may have to make some changes in the source code before compiling (Like changing the binary filename).

Example C file

Using TK1 GPIOs for JTAG

It is possible to use GPIO lines on TK1 with OpenOCD bitbang mode to program\erase the MCU. It's especially useful if you manage to lock EZPort mode.


TMS pin (MXM3 197) needs to be connected to the GPIO1 outside the module, optionally you can connect TRST pin (MXM195) to GPIO2. OpenOCD package can be build using our OE setup (more in OpenEmbedded (core)) and installed using opkg.

Warning: Make sure that your firmware is not configuring any of the K20 JTAG pins for other functions. Note: Toradex stock firmware configures pin PTA3 as a GPIO. Just uncomment #define USE_SWO in utilities/fsl_debug_console.h to build a firmware that can be debugged via JTAG/SWD .


After installing OpenOCD and making necessary connections run:

rmmod gpio_apalis_tk1_k20 apalis_tk1_k20_ts apalis_tk1_k20_can apalis_tk1_k20_adc apalis_tk1_k20

echo 222 > /sys/class/gpio/export
echo low > /sys/class/gpio/gpio222/direction
openocd -f <interface config file> -f target/kx.cfg

If K20's reset vector is invalid you'll see (don't be alarmed by other reported errors):

Warn : **** Your Kinetis MCU is probably locked-up in RESET/WDOG loop. **** Warn : **** Common reason is a blank flash (at least a reset vector). **** Warn : **** Issue 'kinetis mdm halt' command or if SRST is connected **** Warn : **** and configured, use 'reset halt' **** Warn : **** If MCU cannot be halted, it is likely secured and running **** Warn : **** in RESET/WDOG loop. Issue 'kinetis mdm mass_erase' ****

Just follow K20 clearing instructions below and try again Otherwise:

Info : SysfsGPIO JTAG/SWD bitbang driver Info : JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode) Info : This adapter doesn't support configurable speed Info : JTAG tap: kx.cpu tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x4) Info : kx.cpu: hardware has 6 breakpoints, 4 watchpoints

now you should be able to connect gdb over the network:

target remote <APALIS_TK1_IP>:3333
monitor srst_deasserted
monitor kinetis mdm halt

To clear K20 run in a separate shell:

telnet <APALIS_TK1_IP> 4444

kinetis mdm halt
kinetis mdm mass_erase

now K20 should be completely empty with EzPort operations enabled.

Known Issues

Since K20 SPI pins are connected to JTAG pins (JTAG pins funcion as EzPort pins). If you're application uses SPI for communication with TK1 SoC you can't use this port and debug at the same time. One possible workaround is to use one of the Apalis standard SPIs, an alternate muxing for SPI2 on K20 and connect them externally. Since JTAG is bitbanged via GPIO TCK is ~100kHz, so operation is a bit sluggish.

OpenOCD interface config file

# # Config for debugging K20 MCU on Apalis TK1 #

interface sysfsgpio

# Each of the JTAG lines need a gpio number set: tck tms tdi tdo # TCK -> GPIO_PX5 (sysfs 189) # TMS -> GPIO_PFF2(sysfs 250) external loop MXM197(CAM1_HSYNC) to MXM3(GPIO1) # TDI -> GPIO_PX4 (sysfs 188) # TDO -> GPIO_PX7 (sysfs 191) sysfsgpio_jtag_nums 189 250 188 191

# At least one of srst or trst needs to be specified # MCU_RESET -> GPIO_PBB6 (sysfs 222) # (optional) JTAG TRST -> GPIO_FF0 (sysfs 248) external loop MXM195(CAM1_VSYNC) to MXM5(GPIO2) sysfsgpio_trst_num 248 sysfsgpio_srst_num 222

reset_config trst_and_srst separate reset_config srst_nogate reset_config connect_assert_srst

External Debugger

In order to use external debugger for development or flashing hardware modifications are required. Both SWD and JTAG can be used with proper modifications.

Warning: Make sure that your firmware is not configuring any of the K20 JTAG pins for other functions. Note: Toradex stock firmware configures pin PTA3 as a GPIO. Just uncomment #define USE_SWO in utilities/fsl_debug_console.h to build a firmware that can be debugged via JTAG/SWD.