#redefine stamp (stamp+1)

22 posts / 0 new
Last post
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would like the preprocessor to run through my files (not to be confused with program flow) and to substitute all occurences of some #define with the next in sequence, starting from initial value.
So the question has nothing to do with CPU resources - just purely dumb precompiler's txt job.

Example 1 (avr asm, works):

.set my_stamp =6 ; initial value

.macro increment_stamp
 .if(my_stamp>0x5A)
  .error "Too many stamps"
 .else
  .set my_stamp (my_stamp+1)
 .endif
.endmacro ;increment_stamp

Whenever I need a stamp, I just insert it into the code and increment it later if necessary:

ldi temp,my_stamp ; ldi temp,6
increment_stamp ; .set my_stamp = 7 
...
subi pointer,my_stamp ;subi pointer,7
.org my_stamp*7 ; .org 49
increment_stamp ; .set my_stamp =8
...

Example 2 pseudocode in C:

#define OCDR_STAMP 1 //Initial value

#define DEBUG_PRINT(report_string) \
 #ifdef DEBUG
  #if(OCDR_STAMP > 0xFF) \
   #error "Too many OCDR stamps" \
  #else \
  { \
   //__attribute(section((.debug_str_section)) char my_string[]=report_string; \
   OCDR=OCDR_STAMP; \
   #redefine OCDR_STAMP (OCDR_STAMP+1) \
  } \
  #endif \
 #endif 

So that such code worked as I expect it to:

...
void Init_hardware(void){
 Enable_LDO();
 DEBUG_PRINT("LDO running"); //pushes 1 to OCDR
 Enable_PLL();
 DEBUG_PRINT("PLL running"); //pushes 2 to OCDR
 USB_Init();
}

int
main(void){
 DEBUG_PRINT("Entering main()"); //pushes 3 to OCDR
 Init_hardware();
 DEBUG_PRINT("USB Initializatin completed"); //pushes 4 to OCDR
 PORTB=LED_ON;
...

Occurences of DEBUG_PRINT should also place some strings into some elf section to be read out by debugger later but never mind that now - just how to make a define increment/redefine inside of a macro in C?

No RSTDISBL, no fun!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does this help:

#define FOO __COUNTER__

int main (void)
{
   PORTB = FOO;
   PORTB = FOO;
   PORTB = FOO;
   PORTB = FOO;
   PORTB = FOO;
  ce:	15 b8       	out	0x05, r1	; 5
   PORTB = FOO;
  d0:	81 e0       	ldi	r24, 0x01	; 1
  d2:	85 b9       	out	0x05, r24	; 5
   PORTB = FOO;
  d4:	82 e0       	ldi	r24, 0x02	; 2
  d6:	85 b9       	out	0x05, r24	; 5
   PORTB = FOO;
  d8:	83 e0       	ldi	r24, 0x03	; 3
  da:	85 b9       	out	0x05, r24	; 5

But this is just an incrementing variable each time it is used and is not available for all C compilers (but as you see it is in GCC).

Cliff

PS I thought:

#define __COUNTER__ 6

#define FOO __COUNTER__

might allow you to initialise the counter but this just resulted in all 4 uses being 6.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define OCDR_STAMP_INIT 1 //Initial value

#define OCDR_STAMP_CAT(a,b) (a##+##b)
#define OCDR_STAMP  OCDR_STAMP_CAT(OCDR_STAMP_INIT,__COUNTER__)

(untested, possibly an intermediate step is needed for the concatenation)

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

BTW as well as __COUNTER__ some Google results show __LINE__ being used on the basis that each line where it's used is going to have a unique number.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The __COUNTER__ seems to be working!
It always starts from 0, so the offset must be added but I will try sternst's trick later if I go that far..
I thought of some general idea of #define "variables", but for now __COUNTER__ helps in what I need actually.

As you can see each time I must check if __COUNTER__ didn't hit 0x100 which would mean an overflow on OCDR.

I cannot test the value of __COUNTER__ in the code, nor use its value more than once as this increments __COUNTER__.. But even when I use(wasting last write):

if((OCDR=__COUNTER__)>0xFE) 

how to insert:

#error "Too many OCDR stamps"

in a macro function (same as in a pseudocode example)? That # generates a compile time error..

Quote:
__LINE__ (...) is going to have a unique number.

OCDR accepts values from 0x00 to 0xFF so __func__, __FILE__, __LINE__ is good with assert() but not with OCDR/DWDR.

No RSTDISBL, no fun!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
static const int foo=__COUNTER__;
static const int bar=__COUNTER__;

foo and bar will have consecutive values known at compiler-time.
In C++, they can even be used in constant expressions.
They cannot be used in preprocessor expressions.

Michael Hennebry
"Religious obligations are absolute." -- Relg

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Some related ideas:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=110946

I have problems with several things in here:

    A. I do not know how to pass a warning string from asm("") macro into .warning in case the count of debug strings is exceeded
    B. How to send only low(debug_message_index)? LOW() macro does not work..
    C. I do not want additional "ldi r16,0" in the code if a compiler already has some register==0 with appropriate value.. How to tell it to the compiler?
    D. How to create new section in elf and put string there? Obviously I do not want to place those strings in .progmem
    and other

//substitute percent sign..

//initialization of ".set" variable
asm("debug_message_index=0 \n");	

#define DEBUG_IO_REGISTER OCDR //JTAG
//#define DEBUG_IO_REGISTER DIDR //dW

#ifndef NDEBUG
	#define debug_print(string) {								\
	/*__attribute__ ((section (".progmem"))) char report_str[]=string;*/\
		uint8_t value;											\
		asm volatile(	".if(debug_message_index==0x100)\n\t"	\
						"	.warning /*add warning*/ \n\t"		\
						".endif \n\t"							\
						"	ldi percent0,debug_message_index \n\t"	\
						"	out  percent1,percent0 \n\t"					\
						"	/*add string to elf secton*/ \n\t"	\
						"	debug_message_index = debug_message_index+1 \n\t"	\
						: "=d" (value) \
						: "I" (_SFR_IO_ADDR(DEBUG_IO_REGISTER))\
						);\
						}
		
#else
	#define debug_print(string) //prevent compile warnings
#endif

No RSTDISBL, no fun!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try lo8() for low()

See: http://sourceware.org/binutils/docs-2.21/as/AVR_002dModifiers.html#AVR_002dModifiers

The compiler keeps 0 in R1.

Quote:
How to create new section in elf and put string there? Obviously I do not want to place those strings in .progmem
and other

Do it in C then see the .s file:

__attribute__((section(".foo"))) char text[] = "Hello";

yields:

.global	text
	.section	.foo,"aw",@progbits
	.type	text, @object
	.size	text, 6
text:
	.string	"Hello"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ad. B: lo8 does the job, problem solved.

Ad. C: But I do not know which values it has in which registers - I would like to tell it:
"If you have 0x74 in r7 currently, be so kind and write it to OCDR".

What I did right now is asm volatile so even when it has 0 in r0, it is still pushing ldi temp,0 as I told it..

Ad. D:
But foo:

Quote:
../compiler_pitfalls.c:136: error: section attribute cannot be specified for local variables

cannot be local. Unfortunately the debug macro must be local..

No RSTDISBL, no fun!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Ad. C: But I do not know which values it has in which registers - I would like to tell it:
"If you have 0x74 in r7 currently, be so kind and write it to OCDR".

I'll defer to others but I don't know how (short of compile time simulation of the running code) the assembler could possibly know what values may be in any registers at any given time.

Clearly a local (unless 'static') cannot be located at a given address (or within a given section placed by the linker) because it's dynamically created and destroyed on the stack. So I'm afraid that's never going to be possible.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I don't know how

I am sure it is aware of r0. If so, it can also be aware of other values. Anyway, that "C" problem is a minor problem.

Now coming back to "D" - foo section. It must be local as all of those strings have the same name(which I do not need at all). But when I define those as static, "string" macro argument does not seem to be appended correctly:

	#define debug_print(string) {								\
	 static __attribute__((section(".foo"))) char report_str[] = string; \
	}

and there is no .foo section in .s file (not mentioning it warns about unused report_str)

The strings are global and are not to be placed on the stack. Actually these are in the section which is neither allocable nor loadable.
The linker script is a problem close to "K" in here :)

No RSTDISBL, no fun!

Pages