STM32F10x + I2C + OPENOCD & Eclipse building problem

Hi All,

I am having trouble building a project in the Eclipse IDE (OPENOCD) to use the I2C, I am using the ST standard library, the olimex ARM-USB-OCD JTAG and the Olimex H103 board with STM32F103 chip. After a lot of tweaking around after receiving many errors, building now seems to fail with only the below error (many of it though!):

D:\OlimexODS\projects_STM32\STM32-H103_flash-I2C/lib/stm32f10x_i2c.c:165: undefined reference to `assert_param'
main.o: In function `I2C_Init':
D:\OlimexODS\projects_STM32\STM32-H103_flash-I2C/lib/stm32f10x_i2c.c:198: undefined reference to `assert_param'
D:\OlimexODS\projects_STM32\STM32-H103_flash-I2C/lib/stm32f10x_i2c.c:199: undefined reference to `assert_param'
D:\OlimexODS\projects_STM32\STM32-H103_flash-I2C/lib/stm32f10x_i2c.c:200: undefined reference to `assert_param'
D:\OlimexODS\projects_STM32\STM32-H103_flash-I2C/lib/stm32f10x_i2c.c:201: undefined reference to `assert_param'
main.o:D:\OlimexODS\projects_STM32\STM32-H103_flash-I2C/lib/stm32f10x_i2c.c:202: more undefined references to `assert_param' follow
make: *** [main.out] Error 1

After some searching, I found people recommending including the file “stm32f10x_conf.h” in every “.c” file, which didn’t sound right for me, and didn’t work as well! I have found though that the definition for this “assert_param” is mentioned in the “stm32f10x_conf.h” file as:

#ifdef  DEBUG
/*******************************************************************************
* Macro Name     : assert_param
* Description    : The assert_param macro is used for function's parameters check.
*                  It is used only if the library is compiled in DEBUG mode. 
* Input          : - expr: If expr is false, it calls assert_failed function
*                    which reports the name of the source file and the source
*                    line number of the call that failed. 
*                    If expr is true, it returns no value.
* Return         : None
*******************************************************************************/ 
  #define assert_param(expr) ((expr) ? (void)0 : assert_failed((u8 *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
  void assert_failed();//u8* file, u32 line);
#else
  #define assert_param(expr) ((void)0)
#endif /* DEBUG */

As i said, I tried including the file, but it still insists that it’s “undefined reference” :frowning:

I had worked the board with USART with no problems, I am not sure why the I2C is such a trouble! :frowning: :frowning:

Help very much appreciated :expressionless:

Do you have a “#define DEBUG” somewhere ahead of where these files are included? If so, delete it so the that the preprocessor symbol DEBUG is undefined. If you are paranoid you could toss in “#undef DEBUG”. Then any references to assert_param() should get replaced with essentially nothing.

#define DEBUG is declared, I tried “#undef DEBUG” but the error still remains!

Also if the function assert_param() is not that important, why is it mentioned everywhere (thus the several errors) and why is it causing an error in the first place! oh such a headache!

k_505@hotmail.com:
#define DEBUG is declared, I tried “#undef DEBUG” but the error still remains!

Also if the function assert_param() is not that important, why is it mentioned everywhere (thus the several errors) and why is it causing an error in the first place! oh such a headache!

Assert_param is not a function but a preprocessor macro. It should be replaced by the preprocessor with either a call to assert_failed() if DEBUG is defined or ((void)0) otherwise. If your linker is whining that it can’t find assert_param(), then the problem is that the macro was not defined before it was invoked. Check the order of your include files.

I have checked that, the includes are in order…

I wonder if the problem can be in the makefile?! I am using the same makefile (copied from an example project) with this new project?

k_505@hotmail.com:
I have checked that, the includes are in order…

Then you should look at the preprocessor output which gcc will give you with the -E option. Then you can see in what order files are processed and why the macro isn’t defined before it is invoked.

I am kind of lost of what you said! :slight_smile: I would appreciate a little more clarification on that. I am new to makefiles, gcc, and STM32 as well…

I’ve also tried copying the line ```
#define assert_param(expr) ((void)0)

The STM32 is also new to me although I am getting to know the STM32F407 on the discovery board. But I have been using C since the mid 80’s.

Adding that #define to your main.c will not help. Looking at your errors again I see that it is one of the support files, stm32f10x_i2c.c, that is having this problem. That file is compiled separately from your code and linked later. So the problem isn’t in your code.

So the first question is are you using any of the support functions in this file or are you accessing the I2C registers directly? If you aren’t using them you can delete stm32f10x_i2c.c from the list of source files in your makefile.

In looking at the I2C file included with the STM32F4 peripheral library I can’t see where it is finding the assert_param() macro. It must be there but it isn’t obvious. I invoked gcc with -E to get the preprocessor output and that is over 120K so I will not include it here.

While stm32f10x_i2c.c only includes two headers, those two trigger a long cascading list of included files. Including:

stm32f4xx.h

stdint.h

core_cm4.h

core_cmInstr.h

core_cmFunc.h

core_cm4_simd.h

etc.

At the tail end of stm32f4xx.h I found:

ifdef USE_STDPERIPH_DRIVER

#include “stm32f4xx_conf.h”

#endif /* USE_STDPERIPH_DRIVER */

I had noticed the rather byzantine nature of the include files before but this is insane. This, as you might recall, is where the assert_param() macro is defined. The Makefile I am using includes the line:

CDEFS+=-DUSE_STDPERIPH_DRIVER

This value is included in the invocation of gcc:

/sat/bin/arm-none-eabi-gcc -O2 -g -Wall -Werror -mcpu=cortex-m4 -mthumb -I"/home/dsc560/stm32vldiscovery_root/STM32F4-Discovery_FW_V1.1.0/Project/Peripheral_Examples/IO_Toggle" -I"/home/dsc560/stm32vldiscovery_root/STM32F4-Discovery_FW_V1.1.0/Libraries/CMSIS/Include" -I"/home/dsc560/stm32vldiscovery_root/STM32F4-Discovery_FW_V1.1.0/Libraries/CMSIS/ST/STM32F4xx/Include" -I"/home/dsc560/stm32vldiscovery_root/STM32F4-Discovery_FW_V1.1.0/Libraries/STM32F4xx_StdPeriph_Driver/inc" -I"/home/dsc560/stm32vldiscovery_root/STM32F4-Discovery_FW_V1.1.0/Utilities/STM32F4-Discovery" -DSTM32F10X_MD_VL -DUSE_STDPERIPH_DRIVER -c -o stm32f4xx_i2c.o /home/dsc560/stm32vldiscovery_root/STM32F4-Discovery_FW_V1.1.0/Libraries/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_i2c.c

So does your makefile do this?

Thanks for the detailed reply, things are a little bit clearer now, as I mentioned the concept of makefile is new to me, and I am copying the whole LED project every time I try and make a new project (I know, it’s not the smartest thing to do!) I also have the macro for assert_param() defined in the “stm32f10x_conf.h” file

My makefile looks like this:

NAME   = demoh103_blink_rom

CC      = arm-none-eabi-gcc
LD      = arm-none-eabi-ld -v
AR      = arm-none-eabi-ar
AS      = arm-none-eabi-as
CP      = arm-none-eabi-objcopy
OD	  = arm-none-eabi-objdump
  
CFLAGS  = -I./ -c -fno-common -O0 -g -mcpu=cortex-m3 -mthumb 
AFLAGS  = -ahls -mapcs-32 -o crt.o
LFLAGS  = -Tstm_h103_blink_rom.cmd -nostartfiles
CPFLAGS = -Obinary
ODFLAGS	= -S

all: test

clean:
	-rm -f main.lst crt.o main.o main.out main.hex main.map stm32f10x_rcc.o stm32f10x_gpio.o

test: main.out
	@ echo "...copying"
	$(CP) $(CPFLAGS) main.out main.bin
	$(OD) $(ODFLAGS) main.out > main.list

main.out: main.o stm32f10x_rcc.o stm32f10x_gpio.o stm_h103_blink_rom.cmd 
	@ echo "..linking"
	$(LD) $(LFLAGS) -o main.out main.o stm32f10x_rcc.o stm32f10x_gpio.o

stm32f10x_rcc.o: ..\lib\stm32f10x_rcc.c 
	@ echo ".compiling"
	 $(CC) $(CFLAGS) ..\lib\stm32f10x_rcc.c 
	 
stm32f10x_gpio.o: ..\lib\stm32f10x_gpio.c
	@ echo ".compiling"
	 $(CC) $(CFLAGS) ..\lib\stm32f10x_gpio.c 
	 	 
main.o: main.c
	@ echo ".compiling"
	 $(CC) $(CFLAGS) main.c

The point where you said that

That file is compiled separately from your code and linked later. So the problem isn’t in your code.

makes me look at the makefile differently, I am guessing it’s trying to compile these files apart from the main.c file which has the includes in order…

So I am thinking maybe I should change the makefile and remove those .c files, however, I do not know any other way to include other source (.c files) in the eclipse IDE and OpenCD other than this…and #include a .c file doesn’t sound right :?

In your makefile you have this line:

CFLAGS = -I./ -c -fno-common -O0 -g -mcpu=cortex-m3 -mthumb

change it to:

CFLAGS = -I./ -c -fno-common -O0 -g -mcpu=cortex-m3 -mthumb -DUSE_STDPERIPH_DRIVER

This is equivalent to adding:

#define USE_STDPERIPH_DRIVER

At the beginning of every file compiled. Even ones like stm32f10x_gpio.c that you shouldn’t be editing. You should also consider changing “-O0” to “-O2”. I know that these chips have an excess of memory but there are not too many reasons to turn off optimization. One is so that a debugger will not get too confused when single stepping through your program.

I tried ```
CFLAGS = -I./ -c -fno-common -O0 -g -mcpu=cortex-m3 -mthumb -DUSE_STDPERIPH_DRIVER

but without luck, same error remains, it wasn't really a surprise as I am not familiar with "-DUSE_STDPERIPH_DRIVER" or "#define USE_STDPERIPH_DRIVER"... maybe there's something else for STM32F103?? Maybe if we rather add something that is equivalent to defining "assert_param" itself!?

k_505@hotmail.com:
I tried ```
CFLAGS = -I./ -c -fno-common -O0 -g -mcpu=cortex-m3 -mthumb -DUSE_STDPERIPH_DRIVER

but without luck, same error remains, it wasn't really a surprise as I am not familiar with "-DUSE_STDPERIPH_DRIVER" or "#define USE_STDPERIPH_DRIVER"... maybe there's something else for STM32F103?? Maybe if we rather add something that is equivalent to defining "assert_param" itself!?

I don’t know about your tool environment but you may need to delete the object files (*.o). The make program looks at the time stamps of the source and object files and only if the source is newer than the object will it compile. This saves a lot of unnecessary thrashing about which isn’t as big a deal now but back when my compiler was on a 5.25" floppy it made a really big difference. Changing the makefile does not effect that so you may need to delete the objects. Some IDEs have a build all option which is effectively the same.

You should be able to Google up tutorials on using C, make, and the other bintutils. Knowing how the tools work really helps.

Which IDE/toolchain are you using with the STM32?

What exactly are you trying to accomplish? If you want to work with STM32 on an Eclipse based platform, then take a look at the free [Atollic TrueStudio Lite for STM32. You can be up and running in half an hour or less.](http://atollic.com/index.php/download)

I have OpenOCD, it is actually working, the problem is I am not able to work out the I2C! and not because of a problem with the I2C itself, it’s because I am using the STM32 standard library, and for some reason it is giving the assert_param problem…

I will try and download the TrueStudio, did it cause any problems for you? have you tried using I2C before?

I did download TrueStudio and it worked fine for me. However, I have settled on [CrossWorks for ARM for all my development work as it supports a wide variety of devices (and debuggers/programmers as well) [CrossWorks for ARM Support Packges. I have not yet used I2C but I would suggest asking [here.](https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/AllItems.aspx)](http://www.rowley.co.uk/arm/Support_Packages.htm)](CrossWorks for ARM - C/C++ Compiler for ARM and Cortex Micros)

UhClem:
I don’t know about your tool environment but you may need to delete the object files (*.o). The make program looks at the time stamps of the source and object files and only if the source is newer than the object will it compile.

I usually use “Clean Project” before I build every now and then, that usually removes the .o files

rmteo1:
However, I have settled on [CrossWorks for ARM for all my development work as it supports a wide variety of devices (and debuggers/programmers as well) [CrossWorks for ARM Support Packges.[/quote]

I remember downloading Crossworks, but it totally refused connecting to my Olimex ARM-USB-OCD JTAG :(](http://www.rowley.co.uk/arm/Support_Packages.htm)](CrossWorks for ARM - C/C++ Compiler for ARM and Cortex Micros)

k_505@hotmail.com:
I remember downloading Crossworks, but it totally refused connecting to my Olimex ARM-USB-OCD JTAG :frowning:

I see Olimex ARM-USB-OCD listed as a supported target in CrossWorks, however I have never used one. I suggest that you get the ST-LINK debugger ($25) as it works really well with CrossWorks and TrueStudio. Alternatively, get this [[STM32VLDISCOVERY](http://search.digikey.com/us/en/cat/programmers-development-systems/general-embedded-dev-boards-and-kits-mcu-dsp-fpga-cpld/2621773?k=st-link) development board for <$12 and use its **embedded ST-LINK** debugger.

On a side note, get one of these [STM32F103RBT6 with 2.8" TFT and Touch Screen and you have a nicely featured and portable development system for <$32 shipped.

http://img.auctiva.com/imgdata/1/4/0/7/ … 3072_o.jpg](http://www.ebay.com/itm/STM32F103RBT6-development-board-2-8-TFT-module-true-color-touch-screen-/330618886100?pt=LH_DefaultDomain_0&hash=item4cfa6bd7d4)](http://search.digikey.com/us/en/cat/programmers-development-systems/general-embedded-dev-boards-and-kits-mcu-dsp-fpga-cpld/2621773?k=st-link)