FRDM with Arduino Ethernet Shield R3, Part 4: MinIni


I admit: my Ethernet Shield project got stuck because of too many urgent other priorities. I was not happy with the way the project was using configuration data from FLASH memory: I have now multiple ethernet shields in use, and configuring the IP address for each shield is a pain. I have not got DHCP working (yet), so why not using the SD card on the shield for configuration data? And right on time I received a tip from Marc about MinIni: perfect, exactly what I need!

Ethernet Shield with SD card

Ethernet Shield with SD card

MinIni

MinIni (see http://www.compuphase.com/minini.htm) is a programmers library to read and write INI files for embedded systems. INI files are text files with ‘sections’ and ‘keys’, like this one:

[W5100]
Gateway = 192.168.1.1
NetMask = 255.255.255.0
MAC     = 90-A2-DA-0D-42-DD
IP      = 192.168.0.90

The MinIni library is small and efficient, basically is only one source and one header file, and is used with ‘glue’ files for different memory systems. One of it is FatFS which I already use a lot. So MinIni is just perfect for what I need.

MinIni Component

While it the MinIni sources can be used ‘as is’, I wanted to bring it to the next level, so I have created a MinIni Processor Expert component for it:

MinIni Component Methods

MinIni Component Methods

That way I have tool tips help for each of the methods:

MinIni Tooltip help

MinIni Tooltip help

It does not stop here: right-click on the component and use ‘Help on Component‘, and you have access to the user manual (PDF) too:

Component Help with miniIni User Manual

Component Help with miniIni User Manual

Below is a screenshot of the properties of the component:

  • Portable strnicmp(): if enabled, the library has a library for strnicmp().
  • Use Real: if enabled, the library enables reading and writing floating point values.
  • Read Only: if enabled, it only reads from the configuration file, and all write methods are disabled.
  • No Debug: if enabled, assert() in the library is not used. If you disable it, make sure assert() is provided either in your application code or in the standard library.
  • FatFS Buffer Size: this size (in bytes) defines the maximum file name size and the size of a configuration line item. The library does not use any global variables, so make sure that your stack has enough space available.
MinIni Component Properites

MinIni Component Properites

FatFS String Functions

Because MinIni uses the FatFS string functions f_gets() and f_puts(), make sure you have them enabled:

Enabled String Functions in FatFS

U Enabled String Functions in FatFS

Usage

The following code shows how I read configuration data from the SD card to configure the WizNet 5100 chip:

#if PL_USE_INI
  {
    uint8_t buf[32];
    int val;
    const unsigned char *p;
    uint8_t res;

    CLS1_SendStr((unsigned char*)"Loading values from " INI_FILE_NAME "\r\n", CLS1_GetStdio()->stdOut);
    /* Gateway */
    val = MINI1_ini_gets(INI_SECTION_NAME, "Gateway", "192.168.1.1", (char*)buf, sizeof(buf), INI_FILE_NAME);
    CLS1_SendStr((unsigned char*)"Gateway: ", CLS1_GetStdio()->stdOut);
    CLS1_SendStr(buf, CLS1_GetStdio()->stdOut);
    CLS1_SendStr((unsigned char*)"\r\n", CLS1_GetStdio()->stdOut);
    if (val!=0) {
      p = &buf[0];
      res = UTIL1_ScanSeparatedNumbers(&p, &W5100_config.gateway[0], sizeof(W5100_config.gateway), '.', UTIL1_SEP_NUM_TYPE_UINT8);
      if (res!=ERR_OK) {
        CLS1_SendStr((unsigned char*)"Gateway FAILED!\r\n", CLS1_GetStdio()->stdOut);
      }
    }
    /* NetMask */
    val = MINI1_ini_gets(INI_SECTION_NAME, "NetMask", "255.255.255.0", (char*)buf, sizeof(buf), INI_FILE_NAME);
    CLS1_SendStr((unsigned char*)"NetMask: ", CLS1_GetStdio()->stdOut);
    CLS1_SendStr(buf, CLS1_GetStdio()->stdOut);
    CLS1_SendStr((unsigned char*)"\r\n", CLS1_GetStdio()->stdOut);
    if (val!=0) {
      p = &buf[0];
      res = UTIL1_ScanSeparatedNumbers(&p, &W5100_config.netmask[0], sizeof(W5100_config.netmask), '.', UTIL1_SEP_NUM_TYPE_UINT8);
      if (res!=ERR_OK) {
        CLS1_SendStr((unsigned char*)"Netmask FAILED!\r\n", CLS1_GetStdio()->stdOut);
      }
    }
    /* IP */
    val = MINI1_ini_gets(INI_SECTION_NAME, "IP", "192.168.0.1", (char*)buf, sizeof(buf), INI_FILE_NAME);
    CLS1_SendStr((unsigned char*)"IP: ", CLS1_GetStdio()->stdOut);
    CLS1_SendStr(buf, CLS1_GetStdio()->stdOut);
    CLS1_SendStr((unsigned char*)"\r\n", CLS1_GetStdio()->stdOut);
    if (val!=0) {
      p = &buf[0];
      res = UTIL1_ScanSeparatedNumbers(&p, &W5100_config.ipaddr[0], sizeof(W5100_config.ipaddr), '.', UTIL1_SEP_NUM_TYPE_UINT8);
      if (res!=ERR_OK) {
        CLS1_SendStr((unsigned char*)"IP FAILED!\r\n", CLS1_GetStdio()->stdOut);
      }
    }
    /* IP */
    val = MINI1_ini_gets(INI_SECTION_NAME, "MAC", "FF-FF-FF-FF-FF-FF", (char*)buf, sizeof(buf), INI_FILE_NAME);
    CLS1_SendStr((unsigned char*)"MAC: ", CLS1_GetStdio()->stdOut);
    CLS1_SendStr(buf, CLS1_GetStdio()->stdOut);
    CLS1_SendStr((unsigned char*)"\r\n", CLS1_GetStdio()->stdOut);
    if (val!=0) {
      p = &buf[0];
      res = UTIL1_ScanSeparatedNumbers(&p, &W5100_config.hwaddr[0], sizeof(W5100_config.hwaddr), '-', UTIL1_SEP_NUM_TYPE_UINT8_HEX_NO_PREFIX);
      if (res!=ERR_OK) {
        CLS1_SendStr((unsigned char*)"MAC FAILED!\r\n", CLS1_GetStdio()->stdOut);
      }
    }
  }
#endif

With this, the output to the shell in my application is as below:

Reset W5100.
Configure network.
Loading values from config.ini
Gateway: 192.168.1.1
NetMask: 255.255.255.0
IP: 192.168.0.90
MAC: 90-A2-DA-0D-42-DD
Configure RX/TX memory.
done!
Running web server...

The full source code can be found in the GitHub project link at the end of this article.

Summary

With MinIni I have a convenient way to configure my projects based on FatFS and MinIni. Having both parts as Processor Expert components makes things even simpler and faster to use. My Ethernet project for the FRDM-KL25Z has been updated on GitHub to use MinIni. The component sources are on GitHub too and will be released with the next *.PEupd update.

And of course I have some more ideas:

  1. Adding command line interface to the component
  2. Offer other storage than FatFS: microcontroller Flash memory, external EEPROM would be great!

PS: Thanks again to Marc!

List of Tutorials

  1. FRDM with Arduino Ethernet Shield R3, Part 1: SD Card
  2. FRDM with Arduino Ethernet Shield R3, Part 2: Ping
  3. FRDM with Arduino Ethernet Shield R3, Part 3: Embedded Web Server
  4. FRDM with Arduino Ethernet Shield R3, Part 4: MinIni

Happy MinIning 🙂

31 thoughts on “FRDM with Arduino Ethernet Shield R3, Part 4: MinIni

  1. Pingback: FRDM with Arduino Ethernet Shield R3, Part 1: SD Card | MCU on Eclipse

  2. Pingback: FRDM with Arduino Ethernet Shield R3, Part 2: Ping | MCU on Eclipse

  3. Pingback: FRDM with Arduino Ethernet Shield R3, Part 3: Embedded Web Server | MCU on Eclipse

  4. Hi Erich! Please help me!
    I’m getting “The component minIni is not supported in this version of Processor Expert”
    What is wrong?

    Like

      • This is what I have under Help-About CodeWarrior Dev. Studio:
        CodeWarrior Development Studio for Microcontrollers
        Version: 10.6
        Build: 140329

        Processor Expert Core
        Version 1.0.0
        Build: RT6_b1411-0406

        Processor Expert for MCU
        Version 10.6.0
        Build: RT6_b1411-0406

        Toolchain…this is a small problem, I was not able to follow any of your instructions for installing toolchains, …
        I was lost after several steps. I don’t know what toolchain I’m using, I just downloaded and installed CW 10.6 expecting to have also the latest PE

        Thank you for reply!

        Like

      • Now I see that I don’t have minIni in the list of available components.
        I installed the last version of components from Github: Part1_Beans_15.04.2014.PEupd and Part2_Beans_15.04.2014.PEupd

        minIni should be there?

        Like

  5. aaa, the latest version is from 04.05.2014, let me install these ones….downloading….extracting archive…Import components…YES! It’s there!

    Like

  6. Hi!
    I’m from Brazil and I’m working in a project with a texas TIVA M4F microcontroller.
    One of the tasks of my project is read and save configurations on a SD card.
    I started use the FatFS and the minIni libraries for a couple of weeks ago and I noticed that this solution is good but unstable.

    Why this solution is unstable?
    Because I formatted a SD Card in FAT format and started use. After some days I observed the behaviour:
    the first interaction with the SD Card is OK but the following interactions, both for reading and writing, is returning an error.

    Following the call stack and with a couple of debugging work I observed that the function dir_find, who’s called from follow_path is returning the error FR_NO_PATH for a same directory tree that I’m using for the first requisitions (the configuration file is the same). Sometimes the library works fine and sometimes don’t works.

    Now, I want to ask you: did you experienced problems with the Minini library in Freescale world?

    Like

    • Hello,
      no, I have not observed something like this. But I had one case where strange things happened because of not having enough stack space allocated. Can you try increase the stack size for your application to see if the problem goes away?
      Erich

      Liked by 1 person

      • Hi!
        Thank you for the help!

        I don’t know how I can change the stack on IAR compiler, so I changed the minIni code.

        On the ini_browse, ini_puts e getkeystring functions there are a LocalBuffer os INI_BUFFERSIZE bytes. If I change the value of INI_BUFFERSIZE, the minIni works, but it isn’t usefull for me because this length if shorter than the parameters that I need to get on the ini file.

        So, I created a global buffer and changed the functions listed above to use this buffer and everything started to work.

        Like

      • Hi rdmeneze,
        right now buffers are on the stack, as
        TCHAR LocalBuffer[INI_BUFFERSIZE];
        How big of a INI_BUFFERSIZE do you need?
        I could add a setting to make it static (local) like
        static TCHAR LocalBuffer[INI_BUFFERSIZE];
        but this would increase the global memory usage (3 times, as used in three places).
        Or to use a single global buffer.
        But of course all these changes will make it non-reentrant, which might be problematic.

        Like

      • I need a buffer of 128 bytes to hold the entire information.

        Analysing the source code you can notice that the functions ini_puts and getkeystring aren’t reentrant. I don’t use the ini_browse in my solution, that is the only who is a reentrant function.

        How I don’t need the ini_browse function I think that this approach (of global buffer) is enough for me.

        Like

  7. Pingback: McuOnEclipse Components: 22-Mar-2015 Release | MCU on Eclipse

  8. Been trying the KL25L_Eth project but the 2015-03-22 components gives an error. SD1_SetSlowMode calls SD1_SPI_Disable which is a macro to SM1_Disable which doesn’t exist in the SPIMaster_LDD 😦 Any ideas?

    Like

    • Looks I have not updated the project on GitHub, sorry about that. To solve the problem, iin the SM1 (SPIMaster_LDD component) enable both the ‘Enable’ and ‘Disable’ methods (right click on method and use ‘Toggle Enable/Disable’). Then regenerate code and you should be fine. I have updated the projects on GitHub. Sorry again, and thanks for reporting the problem.

      Like

      • Argh, I looked for that before as that was the obvious solution but hadn’t noticed Component Inspector was set to Basic. Once I set to Advanced the two methods appeared and I could then enable them. Thanks for making me look again!

        Like

  9. Hi Erich, thanks for your really great blog and your passion to share your knowledge.
    I use the FRDM-K64F board to control some LED strips. To get same conditions after power up I need a configuration memory to restore some integer variables for the last used brightness, colors, … . Due to controller and board have no EEPROM included I use the SD-card instead. MinIni is a practical solution for that. I use your Processor Expert minIni component with the methods MINI1_ini_putl() and MINI1_ini_getl() to store and restore the integer values in the .ini file.
    During compilation of the Processor Expert generated file MIN1.h with the GNU compiler I got the error message “expected expression for long” in the macro:

    #define MINI1_ini_putl(Section, Key, Value, Filename) \
    ini_putl(Section, Key, long Value, Filename) of MINI1_ini_putl()

    After removing the data type “long” before parameter Value in the second line the macro was translated without error. Maybe this is a case for your next minIni component update.
    Thanks, Michael

    Like

  10. Hi Erich,
    after successful implementation of the ini_putx() and ini_getx() methods I made some tests and found that there is room for improvement. It is not a good idea to use ini_getx(), if many variables have to be restored from the .ini file after power up.
    The disadvantage is, with each call of ini_getx(), the file will be opened to get access to a key-value pair and then the file will be closed. This generates much overhead and needs time. This overhead can be prevented if ini_browse() is used instead. Ini_browse() is part of minIni.c. With the method ini_browse() the whole contents of the .ini file can be restored in one step and the .ini file is opened and closed only once, which saves much time. A small disadvantage is the user has to write his own callback() function, which will be invoked for each key-value pair in the .ini file.
    Ini_browse() would be a good candidate as interface method to improve the minIni Processor Exppert component.
    Thanks, Michael

    Like

What do you think?

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 )

Google+ photo

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

Connecting to %s