Can I use libopencm3 to write an i2c program on my STM32L0? - arm

I am trying to create a very simple i2c test program to run on my STM32L0 (discovery kit). I have modified the miniblink program in libopencm3-examples/examples/stm32/l0/stm32l0538-disco.
But if I just include the i2c header file:
#include <libopencm3/stm32/i2c.h>
And run make I get the error:
../../../../../libopencm3//include/libopencm3/stm32/i2c.h:36:9: error: #error "stm32 family not defined."
Upon investigating this file it appears that there are rules defined for each of the other models but not for the l0, why is this? Does libopencm3 not support i2c on the STM32L0 series?
#if defined(STM32F0)
# include <libopencm3/stm32/f0/i2c.h>
#elif defined(STM32F1)
# include <libopencm3/stm32/f1/i2c.h>
#elif defined(STM32F2)
# include <libopencm3/stm32/f2/i2c.h>
#elif defined(STM32F3)
# include <libopencm3/stm32/f3/i2c.h>
#elif defined(STM32F4)
# include <libopencm3/stm32/f4/i2c.h>
#elif defined(STM32L1)
# include <libopencm3/stm32/l1/i2c.h>
#else
# error "stm32 family not defined."
#endif
I had a look at libopencm3/stm32/l1/i2c.h and all it seems to do is import the common i2c library anyway. Is there any way I can just use the i2c library for the l1?
Thanks

STM32L0 specific header need to be added.
though (i2c common header file can probebly be used).
the common header's are not intended to be directly included (for safty and less headache). (it has includer check)
solution:
you should check "i2c_common_all.h" if it is has correct register defination for l0 (probebly yes), then copy stm32/l1/i2c.h to stm32/l0/i2c.h and added (the last two lines) to stm32/i2c.h
#elif defined(STM32L1)
# include <libopencm3/stm32/l1/i2c.h>
#elif defined(STM32L0)
# include <libopencm3/stm32/l0/i2c.h>
and make modification to lib/stm32/l0/Makefile OBJS += i2c_common_all.o
if you want, send a pull request
hack: (not recommended)
#include <libopencm3/cm3/common.h>
#include <libopencm3/stm32/memorymap.h>
#define LIBOPENCM3_I2C_H
#include <libopencm3/stm32/i2c_common_all.h>
and include the source file lib/stm32/common/i2c_common_all.c manually.

Related

Get a warning with #ifndef foo #def foo #warning foo is n defined #endif

EDIT : reformulate my question :
In file like delay.h (for avr programming in embedded system) you find this kind of pre-processor define :
#ifndef F_CPU
/* prevent compiler error by supplying a default */
# warning "F_CPU not defined for <util/delay.h>"
# define F_CPU 1000000UL
#endif
It seems quite simple. If nobody defined a value for F_CPU, this will declare 10000000 for it and continue compilation. There is no .c file only a .h file.
Now I have a couple of .c and .h file of my own. And when I try to implement this kind of protection for another value. I get a warning even if I previously declared the value in mu main.c file.
main.c file :
#define BAUDE_RATE_SPEED 115200
#include "uart_ctrl.h"
void main(){
}
uart_ctrl.h file :
#ifndef __UART_CTRL_H__
#define __UART_CTRL_H__
#ifndef BAUDE_RATE_SPEED
#define BAUDE_RATE_SPEED 9600
#warning "BAUDE_RATE_SPEED defined at 9600 in uart_ctrl.h"
#endif
void uart_config();
#endif
uart_ctrl.c file :
#include "uart_ctrl.h"
void uart_config(){
MCU_REGISTER.UART = BAUDE_RATE_SPEED;
}
build error :
Warning #warning "BAUDE_RATE_SPEED defined at 9600 in uart_ctrl.h" [-Wcpp] \uart_ctrl.h Build 1
Why this rise me a warning ? Is it normal and i don't understand behaviours or I missed something ?
Thanks again for your help.
------------- Previous question
Ok, I didn't exactly how to ask this questions. Let me know if you see a better option than the title I set.
On embedded system is very common to declare the mcu frequency with this statement for 20Mhz frequency.
#define F_CPU 20000000UL
And it's common too, to have this kind of check, in files using it. Let say delay.h :
#ifndef F_CPU
/* prevent compiler error by supplying a default */
# warning "F_CPU not defined for <util/delay.h>"
# define F_CPU 1000000UL
#endif
If I define F_CPU in my main or anywhere before including my delay.h the warning does not appear and the the first declared F_CPU value is used.
Now I'm writing my own library, I'm trying to do the same, with the same structure. For example :
#ifndef UART_BAUD_SPEED
/* prevent compiler error by supplying a default */
# warning "UART_BAUD_SPEED not defined bla bla"
# define UART_BAUD_SPEED 115200
#endif
But it trig warning anyway. If my library is .H file only or if this is couple h/c file.
How can I implement the same warning/error protection in my library ? What i'm missing ?
Thanks in advance for your help.
The compiler compiles each file separately. When it compiles main.c, main.c defines BAUDE_RATE_SPEED before it includes uart_ctrl.h. When it compiles uart_ctrl.c, nothing defines BAUDE_RATE_SPEED before uart_ctrl.h, so it is not defined and it gives the warning.
When you run the compiler it has an option to define things automatically before compiling the file, which might be where F_CPU comes from. It would be typical to add -DBAUDE_RATE_SPEED=9600 to the compiler command for all files in the project, instead of defining it separately in each file. If you are using an IDE, you may have to figure out where to enter this in the IDE.
Ok, I found where is my miss-understanding.
as #user253751 said, each files is compiled separately. But this only apply to file with couple .h/.c file. Because the delay.h file is header only file, it is never compiler alone. Only included. So the warning never triggered.
Thanks for your help.

Can't use "__has_include" preprocessor in Keil IDE

I'm using Keil to code for STM32 microcontrollers. In main.h file, I use this code:
#if defined __has_include //Keil recognizes this preprocessor. If it was unavailable, Keil would have marked it as gray
#if __has_include("Debugg.h")
#include "Debugg.h"
#endif
#endif
This, checks if the Debugg.h file exists. Let's imagine I have a #define in Debugg.h file:
#define DEBUGGING 1
Now, I expect that in main.h, the DEBUGGING is defined. Again main.h:
#if defined __has_include //Keil recognizes this preprocessor. If it was unavailable, Keil would have marked it as gray
#if __has_include("Debugg.h")
#include "Debugg.h"
#endif
#endif
#ifdef DEBUGGING
#define MAIN_DEBUG 1 //This line runs
#else
#define MAIN_DEBUG 0 //Keil IDE mark this line as gray, meaning "unavailable code"
#endif
But, whenever I try to print MAIN_DEBUG or use it, it is 0!
NOTE:
It seems that Keil IDE recognizes the __has_include preprocessor, but the compiler DOES NOT; because when I comment out these lines:
//#if defined __has_include
#if __has_include("Debugg.h")
#include "Debugg.h"
#endif
//#endif
I get these errors:
compiling main.c...
..\Library\main.h(5): error: #59: function call is not allowed in a constant expression
#if __has_include("Debugg.h")
..\Library\main.h(5): error: #31: expression must have integral type
#if __has_include("Debugg.h")
..\Library\main.c: 0 warnings, 2 errors
I also use the default ARM compiler version 5. Any suggestions?
Thanks.
Any suggestions?
Do not use non-portable extensions like __has_include. Build systems are used to detect information about environment, like available headers.
For example, CMake build system has check_include_file that you can check if an include file exists. Then if the include file Debugg.h (why upper+lower case mix?) exists, then add a macro HAS_DEBUGG_H to compilation and if that macro is defined, then include the header.
a libX.c, a libX.h and libX_conf.h file. the checking for Debugg.h is in config file. If it was available, it checks for the prints of a specific thread. If not, debugging is deactivated
That should be done with a macro, not with "detecting header file". There should be a macro, called like LIBX_DEBUG_ENABLE and if defined, libX should output debugging information. I.e. it is a user configuration setting done with a macro, not with deleting a file.

stdint.h include_next'd from stdint.h not found

I have been putting together a m68k cross compile "environment/toolchain" of sorts for some upcoming projects I have planned, and I'm having an issue when using it on macOS (my native environment) specifically.
If I follow my own instructions to install on Linux (https://github.com/tomstorey/m68k_bare_metal/blob/master/INSTALL-Debian-Ubuntu.md), then in my code I am able to use types such as uint8_t etc through #include <stdint.h>.
But if I install on macOS and attempt to do the same thing I am greeted with this error:
In file included from main.c:1:
/Users/tstorey/m68k/m68k-unknown-elf/lib/gcc/m68k-unknown-elf/9.3.0/include/stdint.h:9:16: fatal error: stdint.h: No such file or directory
9 | # include_next <stdint.h>
| ^~~~~~~~~~
compilation terminated.
make: *** [main.o] Error 1
I've done a little searching around, but I'm not having much luck finding an answer, perhaps because I don't really know what to search for other than "stdint.h not found".
One topic I did find suggested that include_next shouldnt really be used, but that same person wouldnt recommended modifying the original stdint.h file to work around it. Presumably since in that case it is including <stdint.h> then this file should be located somewhere "system wise", and gcc should know where to look to find it? But presumably that location doesnt exist.
In the same directory where the the stdint.h file I am trying to include is located there is a stdint-gcc.h file which, if I include this in my code, it will compile fine, no worries.
The original stdint.h file does seem to attempt to include this file, but only if __STDC_HOSTED__ is not defined:
$ cat stdint.h
#ifndef _GCC_WRAP_STDINT_H
#if __STDC_HOSTED__
# if defined __cplusplus && __cplusplus >= 201103L
# undef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
# undef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
# endif
# include_next <stdint.h>
#else
# include "stdint-gcc.h"
#endif
#define _GCC_WRAP_STDINT_H
#endif
Sorry if this post is a bit wofty, but I am not experienced enough with gcc etc to really be able to work this out and I'm still learning a lot about setting all of this up, so I'm wondering if anyone knows what I have missed.
Thanks
When your particular version of gcc has been built, it was apparently not built for a hosted environment (i.e. full availability of a standard C library, for example newlib). When this is the case, you cannot expect standard library support and are on your own.
You probably want to re-build gcc with newlib support.

Prevent inclusion of headers into same file in C

I'm looking for a way to enforce that certain headers cannot be included into the same file.
To explain the situation further, assume I have the headers
a_1.h, b_1.h
and
a_2.h, b_2.h
I want to prevent the inclusion of _1 and _2 files into the same file, regardless of if they were
a_ or b_
Assuming that mixing the _1 and _2 headers is a mistake that needs to be caught, a simple way of catching it is to define and check guard macros to check for mixed usage of these headers and use the #error directive to report errors.
For example, the a_1.h header can include this code:
#ifndef A_1_H__INCLUDED
#define A_1_H__INCLUDED
/* Define header set as 1 if not already defined. */
#ifndef HEADER_SET
#define HEADER_SET 1
#endif
/* Check for consistent header set usage. */
#if HEADER_SET != 1
#error "Inconsistent header sets"
#endif
/* Other header stuff ... */
#endif /* A_1_H__INCLUDED */
The other headers will be similar but the _2 headers will have #define HEADER_SET 2 and #if HEADER_SET != 2.
Remember that ANY other file in the build process can include a header. With the typical include guard: #ifndef MYHEADER \n #include MYHEADER, the header code is only inserted on the first instance. After that, the compiler has eaten it and remembers and doesn't need to include it again. Think of compiling as putting ALL the source code into one file and turning that into a binary. (you know, "compiling" as in putting it all in a pile). So it's not "into the same file" it's "into the same build".
You want a header file to be mutually exclusive with another header file. (Like, say, if you've got code that targets specific hardware via includes, and you obviously can't build towards two chips at the same time.) First off, if that's an issue, you should really have a single place where such things are defined (like the build script) so that's not a problem. But if you want a simple safeguard:
#ifndef PPC_e6500
#define PPC_e6500
#ifdef LINUX
#error This processor ain't big enough for the both of us, Tux. This here's 8548 territory!
#endif
That will fail to build and you can figure out who did whatever horrible thing that tried to build towards two targets at once.

Why might need include a source file that?

I am to port h264 codec in an embedded device. The ffmpeg source code uses the following construction:
#undef CHROMA_IDC
#define CHROMA_IDC 3
#include "h264_mc_template.c"
static av_noinline void FUNC(hl_decode_mb_444)(const H264Context *h, H264SliceContext *sl)
{
...
}
Why do I need to include such a source file? Isn't that used only for the header?
the "template" suffix hints at the fact that the code depends on some preprocessor directives.
I checked the source and at the beginning there's
#if CHROMA_IDC == 1
# define MCFUNC(n) FUNC(n ## _420)
#elif CHROMA_IDC == 2
# define MCFUNC(n) FUNC(n ## _422)
#elif CHROMA_IDC == 3
# define MCFUNC(n) FUNC(n ## _444)
#endif
note that you have #define CHROMA_IDC 3 before including this file.
This tells the preprocessor to use define MCFUNC(n) FUNC(n ## _444) in the included file.
the source could have been left alone in the makefile but with a -DCHROMA_IDC=3 directive, and in that case, the template cannot be reused for other source files because of multiple redefinition (the functions in this source file are static to avoid multiple redefinition if the template is instanciated more than once)
Why using a template? probably for performance issues, to avoid a call chain and some tests to branch on the required behaviour. ffmpeg cannot afford to be slow on the encoding functions.

Resources