0

I have a header file. It contains the value of various constants(as pre-processor macro definitions---hash defines) that I use in my embedded systems project(IDE is Keil MicroVision, Microcontroller is STM32 and programming language is C). I want to convert that header file to a hex file, so that I can separately write it to flash memory of the microcontroller. Hence, for a single general software code, I wish to to change the constants and run it for specific (around 10-15 different types) hardware.

My approach: I am trying to find a way to convert the header file to a binary file first, and then use some utility(srecorder from sourceforge) to convert the .bin to .hex

Is this approach right?

Or can anyone please suggest an alternate and effective way to achieve my goal? Thanks

3
  • Normal C programs never contain any variable instances in header files, so it is definitely not the right approach - your C project seems incorrectly designed. Also when you say constants do you mean const variable definitions or pre-processor #define or enum? Commented Jan 4, 2022 at 8:48
  • pre-processor macro definitions(hash defines) Commented Jan 4, 2022 at 11:50
  • 1
    No, it is not the right approach (and makes no sense; declarations in a header file are instructions to the compiler not instantiations of data, and data location is determined by the linker.) This is an X-Y problem and your solution X makes little sense. Ask about your problem Y instead. There are many possible solutions. STM32 covers a wide range of parts from those with many 2Kb flash blocks throughout to others with fewer, larger and variable sized flash pages. This makes a difference to what constitutes a viable solution, of which there are many - so you may need to be more specific. Commented Jan 4, 2022 at 15:35

2 Answers 2

2

Preprocessor defines aren't stored in data flash but in program flash (.text), together with the code using them, integrated in the machine code. They aren't stored at any specific or fixed address. So your request doesn't make any sense - you simply cannot program them to flash separately.

In order to achieve that you need const uint32_t or similar variables stored at fixed memory locations. These need to be declared in a .c file, though it is sometimes acceptable to expose read-only variables "globally" with extern references from a corresponding .h file.

To allocate a variable at a specific address you typically need to change the linker script and use non-standard compiler extensions.

Sign up to request clarification or add additional context in comments.

Comments

1

Understanding where you're coming from, I would not recommend going down the road you suggested. Let me show you two ways to solve your problem which I believe are much better.

I'll assume your constants are macros, but, it should not be different if they are enums or something else.

First option is to use the preprocessor to select your platform. Something like:

#if defined(PLATFORM_A)
#define CONSTANT_X 111
#define CONSTANT_Y 222
#elif defined(PLATFORM_B)
#define CONSTANT_X 112
#define CONSTANT_Y 221
#else
#error Need to define a platform
#endif

Of course, if you have a lot of constants, maybe keeping each platform in its own header would be better (easier to read).

#if defined(PLATFORM_A)
#include "platform_a_constants.h"
#elif defined(PLATFORM_B)
#include "platform_b_constants.h"
#else
#error Need to define a platform
#endif

This option is the only way if you use these constants to, say, dimension an array.

I don't have experience with Keil IDE's, so, I'm not sure how to configure it to build different binaries with different macro definitions, but, it's a common C thing, there should be way to do it.

Another option would be to make these globals. In that case, you would have a single header like:

extern int const constant_x;
extern int const constant_y;

And then a separate source file for each platform:

// platform_a.c
int const constant_x = 111;
int const constant_y = 222;

// platform_b.c
int const constant_x = 112;
int const constant_y = 221;

Again, how to link in only the source file that you need for a particular target depends on your build system and I'm not familiar with Keil IDE, but it should not be hard to do.

In general, this option is a little easier to maintain, as it's just setting up the linker, you don't mess up with source code in any way (and defining a preprocessor constant is messing up with the source code in potentially ugly ways).

Also, with this option it's simple to turn a constant into a runtime parameter, which can be changed during the execution of the program, if need be - just drop the const from the declaration and definitions.

2 Comments

The question is clearly an X-Y problem and this is a solution to the (real) problem X rather then to the nonsense question Y. That is fine (and useful to the OP), but he OP should be encouraged to ask specifically X for this answer to be valid and to then better serve the SO community. That is to say you have answered the question he should have asked rather than the question he has asked which is about an implausible solution.
@Clifford Like you said, trying to help the guy out, as he did ask if his idea was the right approach. I did edit to make it more clear that his idea is not the right approach.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.