Over a million developers have joined DZone.

Tutorial: DIY Kinetis SDK Project with Eclipse – Board Configuration

· IoT Zone

Access the survey results 'State of Industrial Internet Application Development' to learn about latest challenges, trends and opportunities with Industrial IoT, brought to you in partnership with GE Digital.

In “Tutorial: DIY Kinetis SDK Project with Eclipse – Startup” I showed how to create a Kinetis SDK project from scratch. In this post it is about adding the board initialization files. With the board initialization the peripheral clocks and pin muxing is configured.

MK64FN1M0VLL12 on FRDM-K64F

MK64FN1M0VLL12 on FRDM-K64F

Clocks and Pin Muxing

As outlined in “Tutorial: DIY Kinetis SDK Project with Eclipse – Startup“, up to main() I have already a basic configuration:

  1. Stack and Heap are defined
  2. ‘Critical’ hardware like Watchdog/COP and basic CPU clocks are configured
  3. C/C++ variables are initialized
  4. Any ANSI library runtime settings are done

But for many modern microcontroller, there is yet another hardware configuration needed, which usually is done from main() as one of the first steps: to configure the clock gating and pin muxing.

Clock Gating‘ means that clocks are configured as such that the peripherals used are clocked. By default on ARM cores, peripheral clocks need to be enabled, and accessing a peripheral like I/O pins which are not clocked will very likely result in an exception or hard fault.

The other thing is ‘Pin Muxing': on modern microcontroller an external pin on the processor package can be used by different peripherals. For example the picture below shows the ‘Processor’ view in Processor Expert. The pin No 7 can be used for I/O, UART, I2S, FTM or even for USB. And it is now configured and routed to PTE6 as I/O pin:

PTE6 Routing

PTE6 Routing

Pin Muxing or Routing can be in many cases changed at runtime, but it is important to configure it properly at the beginning before doing the driver initialization, as the muxin is ‘shared’ between the peripherals and drivers.

SDK Board Files

I’m adding my board to the project with the files in ${KSDK_PATH}\boards:

Added board support for FRDM-K64F

Added board support for FRDM-K64F

And I make sure the compiler knows the include path to the boards folder. But as the board files are using a bunch of other include files of the SDK, I need to add some extra compiler include paths:

"${KSDK_PATH}/boards/frdmk64f120m"
"${KSDK_PATH}/platform/drivers/gpio"
"${KSDK_PATH}/platform/hal/port"
"${KSDK_PATH}/platform/hal/gpio"
"${KSDK_PATH}/platform/drivers/clock"
"${KSDK_PATH}/platform/utilities"
"${KSDK_PATH}/platform/hal/sim"

With this, I’m able to compile and link the board files :-).

Initializing the Board

To initialize the board, I include the header file:

#include "board.h"

and call the initialization function:

hardware_init(); /* initialize the hardware */

My application does now ‘nothing': it only calls main() and there I initialize the hardware:

main() with hardware_init()

main() with hardware_init()

But it will complain about missing clock_manager_set_gate():

Missing clock_manager_set_gate

Missing clock_manager_set_gate

This means I need to add the needed files to configure clocks and the SIM (System Integration Module). So I add more files: clock and sim:

Added clock and sim folders

Added clock and sim folders

And again, I need to add an include path for the compiler:

"${KSDK_PATH}/platform/drivers/interrupt"

Unfortunately, there is a bug in the current SDK V1.0.0-Beta: fsl_sim_features.h reports that it does not know my correctly specified “CPU_MK64FN1M0VLL12″  :-(:

Description    Resource    Path    Location    Type
#error "No valid CPU defined"    fsl_sim_features.h    /FRDM-K64F_Bare_SDK/SDK/platform/hal/sim    line 279    C/C++ Problem

So I need to add the following to my compiler preprocessor settings to make the compiler happy:

"CPU_MK64FN1M0VMD12"

And with this I can build:

   text       data        bss        dec        hex    filename
  17912       2476        260      20648       50a8    FRDM-K64F_Bare_SDK.elf

newlib-nano

Well, that’s a lot of code size! Time to switch to the smaller newlib-nano library. So I add

-specs=nano.specs

to my linker settings:

newlib-nano linker option

newlib-nano linker option

With this, the code size gets cut by half :-):

   text       data        bss        dec        hex    filename
   8376        152         44       8572       217c    FRDM-K64F_Bare_SDK.elf

Now, that 8 KByte (yikes!) code is still a *lot*, given what our application does: it does *nothing* (yet). The reason is how the SDK is architected: it uses a lot of tables and internal data structures, and does a lot of things dynamically (e.g. hardware initialization). Therefore the code (and speed) overhead compared to a ‘traditional’ project is not small. Even ‘pure’ Processor Expert projects are much smaller for ‘doing nothing’ because Processor Expert can just generate the code needed, and does not need to carry on all the extra stuff. The same thing with a Processor Expert project would be less than 4 KByte code!

hardware_init()

But what is hardware_init() doing? Not that much, but a very important thing: to setup the clocks and pin muxing:

void hardware_init(void)
{
    int32_t i;
 
    /* enable clock for PORTs */
    for (i = 0; i < HW_PORT_INSTANCE_COUNT; i++)
    {
        clock_manager_set_gate(kClockModulePORT, i, true);
    }
 
    /* init the general pinmux */
    configure_enet_pin_mux(0);
 
    for (i = 0; i < HW_PORT_INSTANCE_COUNT; i++)
    {
        configure_gpio_pin_mux(i);
    }
 
    configure_i2c_pin_mux(0);
    configure_i2c_pin_mux(1);
    configure_sdhc_pin_mux(0);
    configure_spi_pin_mux(0);
    configure_uart_pin_mux(0);
}

The first for loop enables the clock gates (passes the clocks to the peripherals) for the PORT (GPIO) peripherals. I recommend that you use the debugger and step through the code (e.g. go into clock_manager_set_gate(). Then you can see what contributes to the code size).

Next it configures the ethernet pin muxing with configure_enet_pin_mux(), followed by a for loop which does the same for the general purpose I/O pins. As we have two I2C on microcontroller, there are two calls to configure_i2c_pin_mux().

Summary

Before I can run my application code, the microcontroller needs to be initialized properly. Basically this means configuring the pin muxing and clock gates. As this is usually depending on the board or what is attached to the pins, this is named ‘board configuration’ too. The Kinetis SDK has preconfigured board configuration, e.g. for the FRDM-K64F. The configuration is done with the function hardware_init() which needs to be called right after main(). With the Kinetis SDK I can initialize my hardware and board in programmatic way and do my custom board configuration. However, with the way how the SDK is architected, be ready for overhead. For microcontroller with a lot of FLASH like the K64F this does not matter much, but for smaller microcontroller saving every byte is important.

The project is available on GitHub. So what’s next? Blinking a LED!

Happy Boarding :-)

The IoT Zone is brought to you in partnership with GE Digital.  Discover how IoT developers are using Predix to disrupt traditional industrial development models.

Topics:

Published at DZone with permission of Erich Styger, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}