SparkFun Forums 

Where electronics enthusiasts find answers.

Everything ARM and LPC
By k_505@hotmail.com
#137113
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!):
Code: Select all
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:
Code: Select all
#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" :(

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

Help very much appreciated :|
By UhClem
#137115
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.
By k_505@hotmail.com
#137139
#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!
By UhClem
#137144
k_505@hotmail.com wrote:#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.
By UhClem
#137243
k_505@hotmail.com wrote: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.
By UhClem
#137267
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?
By k_505@hotmail.com
#137277
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:
Code: Select all
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 :?
By UhClem
#137278
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.
By k_505@hotmail.com
#137279
I tried
Code: Select all
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!?
By UhClem
#137280
k_505@hotmail.com wrote:I tried
Code: Select all
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.