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!
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:
That way I have tool tips help for each of the methods:
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:
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.
FatFS String Functions
Because MinIni uses the FatFS string functions f_gets() and f_puts(), make sure you have them enabled:
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); } } } #endifWith 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:
- Adding command line interface to the component
- Offer other storage than FatFS: microcontroller Flash memory, external EEPROM would be great!
PS: Thanks again to Marc!
List of Tutorials
- FRDM with Arduino Ethernet Shield R3, Part 1: SD Card
- FRDM with Arduino Ethernet Shield R3, Part 2: Ping
- FRDM with Arduino Ethernet Shield R3, Part 3: Embedded Web Server
- FRDM with Arduino Ethernet Shield R3, Part 4: MinIni
Happy MinIning 🙂
Pingback: FRDM with Arduino Ethernet Shield R3, Part 1: SD Card | MCU on Eclipse
Pingback: FRDM with Arduino Ethernet Shield R3, Part 2: Ping | MCU on Eclipse
Pingback: FRDM with Arduino Ethernet Shield R3, Part 3: Embedded Web Server | MCU on Eclipse
Hi Erich! Please help me!
I’m getting “The component minIni is not supported in this version of Processor Expert”
What is wrong?
LikeLike
Hi Cristian, hmm, strange. What version of Processor Expert are you using (Toolchain)?
LikeLike
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!
LikeLike
Hi Cristian,
I’m using MCU10.6 too, and don’t have any problem like you report?
What now?
Erich
LikeLike
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?
LikeLike
I have pushed new files two days ago (https://sourceforge.net/projects/mcuoneclipse/), dated 5-May-2014. So you have loaded the previous/old version? Can you check again?
LikeLike
aaa, the latest version is from 04.05.2014, let me install these ones….downloading….extracting archive…Import components…YES! It’s there!
LikeLike
Yes, it was not there in the previous package. Good that this one is resolved, uff!
LikeLike
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?
LikeLike
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
LikeLiked 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.
LikeLike
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.
LikeLike
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.
LikeLike
Hi rdmeneze,
I have added a property so you can configure if the buffers are on the stack (default) or in global memory):
https://github.com/ErichStyger/McuOnEclipse_PEx/commit/74600d6a5ba5bf809df403fde8976de4ad8dbad1
Let me know if you want to receive the component by email.
Thanks!
Erich
LikeLike
I’m using the IAR compiler, so I don’t can use your solution…
thank you very much, Erich.
Thanks,
Rafael Dias
LikeLike
Processor Expert can be used with IAR (I’m using it too).
LikeLike
IAR with Texas Instruments microcontroller? <:c)
LikeLike
ah, I missed that piece 😉
LikeLike
kkkk
c’est là vie, my friend
LikeLike
Pingback: McuOnEclipse Components: 22-Mar-2015 Release | MCU on Eclipse
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?
LikeLike
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.
LikeLike
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!
LikeLike
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
LikeLike
Hi Michael,
yes, that’s how I’m using the Minini module too: to make initializations from SD cards. Great to hear that this is of use for you.
And thank you very much for reporting that problem, I have it fixed now on GitHub:
https://github.com/ErichStyger/McuOnEclipse_PEx/commit/f1ea4c7e4098a00c007de5aad325abbfdf770bfd
It will be available with the next release.
Thanks again,
Erich
LikeLike
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
LikeLike
Hi Michael,
yes, indeed, the ini_browse() is a much better alternative than using individual file operations. I have followed your suggestions and added the ini_browse() to the interface in GitHub, and it will be available with the next release: https://github.com/ErichStyger/McuOnEclipse_PEx/commit/349477adf05e4463573ae13ed0440346f93d53a4
LikeLike
Hi Erich,
good news, thanks for your fast update. Progress is sequence of small steps.
Thanks again
Michael
LikeLike
Pingback: Different Ways of Software Configuration | MCU on Eclipse
Pingback: FatFS, MinIni, Shell and FreeRTOS for the NXP K22FN512 | MCU on Eclipse
Pingback: Using FatFS and MinINI with the NXP LPC55S16 EVK | MCU on Eclipse