Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
Brutte
PostPosted: Aug 06, 2011 - 05:28 PM
Raving lunatic


Joined: Oct 05, 2006
Posts: 3286
Location: Poland

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):
Code:
.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:

Code:
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:
Code:
#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:

Code:
...
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?
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Aug 06, 2011 - 07:29 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71947
Location: (using avr-gcc in) Finchingfield, Essex, England

Does this help:
Code:
#define FOO __COUNTER__

int main (void)
{
   PORTB = FOO;
   PORTB = FOO;
   PORTB = FOO;
   PORTB = FOO;

Code:
   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:
Code:
#define __COUNTER__ 6

#define FOO __COUNTER__

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

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
sternst
PostPosted: Aug 06, 2011 - 07:40 PM
Raving lunatic


Joined: Jul 23, 2001
Posts: 2728
Location: Osnabrueck, Germany

Code:
#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
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Aug 06, 2011 - 07:49 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71947
Location: (using avr-gcc in) Finchingfield, Essex, England

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.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Brutte
PostPosted: Aug 06, 2011 - 09:26 PM
Raving lunatic


Joined: Oct 05, 2006
Posts: 3286
Location: Poland

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):

Code:
if((OCDR=__COUNTER__)>0xFE)

how to insert:
Code:
#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.
 
 View user's profile Send private message  
Reply with quote Back to top
skeeve
PostPosted: Aug 07, 2011 - 04:53 PM
Raving lunatic


Joined: Oct 29, 2006
Posts: 3279


Code:
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
"There will now be an unscheduled faith change." -- Tasha Lem
 
 View user's profile Send private message  
Reply with quote Back to top
Brutte
PostPosted: Aug 26, 2011 - 01:24 PM
Raving lunatic


Joined: Oct 05, 2006
Posts: 3286
Location: Poland

Some related ideas:
http://www.avrfreaks.net/index.php?name ... p;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




Code:
//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


Last edited by Brutte on Aug 26, 2011 - 01:32 PM; edited 1 time in total
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Aug 26, 2011 - 01:27 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71947
Location: (using avr-gcc in) Finchingfield, Essex, England

Try lo8() for low()

See: http://sourceware.org/binutils/docs-2.2 ... dModifiers

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:
Code:
__attribute__((section(".foo"))) char text[] = "Hello";

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

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Brutte
PostPosted: Aug 26, 2011 - 01:39 PM
Raving lunatic


Joined: Oct 05, 2006
Posts: 3286
Location: Poland

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!
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Aug 26, 2011 - 01:55 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71947
Location: (using avr-gcc in) Finchingfield, Essex, England

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.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Brutte
PostPosted: Aug 26, 2011 - 02:13 PM
Raving lunatic


Joined: Oct 05, 2006
Posts: 3286
Location: Poland

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:

Code:
   #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 Smile
 
 View user's profile Send private message  
Reply with quote Back to top
Brutte
PostPosted: Aug 26, 2011 - 02:33 PM
Raving lunatic


Joined: Oct 05, 2006
Posts: 3286
Location: Poland

I am answering to the question from this topic:
http://www.avrfreaks.net/index.php?name ... p;t=110946
clawson wrote:
That would require the PC side debugger to be modified to know to look up string 0x74 in the .elf? How do you plan to modify AVR Studio's internal debugger code?


I know that would be challenging to print in AS message window, but if I had a JTAG dongle driver, then I do not think that trick would be hard with GDB..

_________________
No RSTDISBL, no fun!
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Aug 26, 2011 - 02:36 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71947
Location: (using avr-gcc in) Finchingfield, Essex, England

Does avarice report OCDR events on to GDB? I presumed it just talks GDB's "serial protocol" - does that have a mechanism for something like this?

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Brutte
PostPosted: Aug 26, 2011 - 04:03 PM
Raving lunatic


Joined: Oct 05, 2006
Posts: 3286
Location: Poland

I am not sure about avarice functionality on this matter. But I do not see a problem to add it, if needed. It is open-source.

Never mind about Mk1 and all other Atmel's crippled tools. I was thinking about FT232H.

_________________
No RSTDISBL, no fun!
 
 View user's profile Send private message  
Reply with quote Back to top
Brutte
PostPosted: Jun 21, 2012 - 10:31 PM
Raving lunatic


Joined: Oct 05, 2006
Posts: 3286
Location: Poland

I have just found out that a similar functionality is already implemented on Code Red's LPCXpresso using ARM's system debug ITM:
http://knowledgebase.nxp.com/showthread.php?t=461
It is called hoststrings and:
Code Red wrote:
(..)However with hoststrings, the message is actually read by the debugger from within your project structure - and all that the MCU has to do is send a reference to the debugger as to which message it wants printing, (..)
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Jun 22, 2012 - 09:18 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71947
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

is already implemented on Code Red's LPCXpresso using ARM's

Yes it's a great facility. In fact it's actually more complex to work out how to get printf() redirected to go via a real UART Wink

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Brutte
PostPosted: Jun 22, 2012 - 12:04 PM
Raving lunatic


Joined: Oct 05, 2006
Posts: 3286
Location: Poland

Quote:
Yes it's a great facility.

Did you try it? AFAIK only Red Probe dongle (150$) supports it and Red Suite is required. Perhaps other vendors have similar features like hoststrings but as far as I know the naming convention is not standardized.
Anyone knows these names so I could read more about it?
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Jun 22, 2012 - 12:37 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71947
Location: (using avr-gcc in) Finchingfield, Essex, England

Sorry I thought you simply meant the printing of printf() output to the debugger. You get that with a $20 LPCXpresso. I take it you meant he further extension of this to simply pass a single byte token to identify which host side held string to print? I have no experience of that and don't know if Code Red for LPCXpresso has that or not. But apart from debug link bandwidth what's wrong with the app passing the strings or do you mean you don't want the app size bloated by the local storage of the strings? (not usually a problem in LPCXpresso as they are relatively huge compared to AVRs).

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Brutte
PostPosted: Jun 22, 2012 - 01:39 PM
Raving lunatic


Joined: Oct 05, 2006
Posts: 3286
Location: Poland

Quote:
Sorry I thought you simply meant the printing of printf() output to the debugger.

This printf is called semihosting on ARMs and uses unique asm("bkpt 0xAB")=0xBEAB opcode to halt the target. When the dongle sniffs that target is stopped and it happened 0xBEAB was the cause, it polls memory space pointed in r0 to r3 register set (which contains your printf content) and prints on your console. When dongle is done, it forces the target to continue(run). These steps are automated, but process is controlled by the host/dongle and purely in Halting mode so it is intrusive (target is stopped in the meantime -> overflows, overruns etc, because peripherals are not being stopped then).
OTOH hoststrings use ITM from system debug (Instruction Trace Macrocell, this is a low cost tracing interface implemented inside the core) which does not halt the target at all - it is a dedicated (typically 32 channel) hardware with FIFOs, priorities, timestamps and what not. It can emit PC snapshots, accessed data read, written or both, etc.

LPCXpresso does not support ITM interface.

Quote:
I take it you meant he further extension of this to simply pass a single byte token to identify which host side held string to print?

You would not gain much with that - shorter timings, but still intrusive Halting mode on ARMs.

Quote:
But apart from debug link bandwidth what's wrong with the app passing the strings

AVR halts peripherals when halted (all but some). ARMs do not do that*.

Seems that on AVRs writing to OCDR register does not halt the target at all. But OCDR has some (unknown) limited depth and no overwrite detection so a care should be taken with that. I do not plan to continue the development as today I know my dongle (JTAGICE Mk1) does not support this feature.

I am just curious how other vendors (Keil, IAR, Segger etc) implemented and named hoststrings Smile

*EDIT: Behaviour is implementation dependent actually. Some chips ( for example STM32F40X) have the option to halt peripherals when the core is halted. But some do not (LPC17XX can only halt RIT, but not regular timers).


Last edited by Brutte on Jul 07, 2012 - 09:04 AM; edited 2 times in total
 
 View user's profile Send private message  
Reply with quote Back to top
jayjay1974
PostPosted: Jun 22, 2012 - 04:04 PM
Raving lunatic


Joined: Oct 30, 2002
Posts: 5769
Location: The Netherlands

http://www.atmel.no/webdoc/jtagicemkii/jtagicemkii.special_considerations_mega.html

Mentions the OCDR register, it's polled every 100ms. No queuing it seems.
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits