| Author |
Message |
|
|
Posted: Aug 06, 2011 - 05:28 PM |
|

Joined: Oct 05, 2006
Posts: 2297
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? |
|
|
| |
|
|
|
|
|
Posted: Aug 06, 2011 - 07:29 PM |
|


Joined: Jul 18, 2005
Posts: 62944
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. |
_________________
|
| |
|
|
|
|
|
Posted: Aug 06, 2011 - 07:40 PM |
|


Joined: Jul 23, 2001
Posts: 2471
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
|
| |
|
|
|
|
|
Posted: Aug 06, 2011 - 07:49 PM |
|


Joined: Jul 18, 2005
Posts: 62944
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. |
_________________
|
| |
|
|
|
|
|
Posted: Aug 06, 2011 - 09:26 PM |
|

Joined: Oct 05, 2006
Posts: 2297
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. |
|
|
| |
|
|
|
|
|
Posted: Aug 07, 2011 - 04:53 PM |
|

Joined: Oct 29, 2006
Posts: 2690
|
|
|
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
Iluvatar is the better part of Valar.
|
| |
|
|
|
|
|
Posted: Aug 26, 2011 - 01:24 PM |
|

Joined: Oct 05, 2006
Posts: 2297
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
|
| |
|
|
|
|
|
Posted: Aug 26, 2011 - 01:27 PM |
|


Joined: Jul 18, 2005
Posts: 62944
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"
|
_________________
|
| |
|
|
|
|
|
Posted: Aug 26, 2011 - 01:39 PM |
|

Joined: Oct 05, 2006
Posts: 2297
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!
|
| |
|
|
|
|
|
Posted: Aug 26, 2011 - 01:55 PM |
|


Joined: Jul 18, 2005
Posts: 62944
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. |
_________________
|
| |
|
|
|
|
|
Posted: Aug 26, 2011 - 02:13 PM |
|

Joined: Oct 05, 2006
Posts: 2297
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  |
|
|
| |
|
|
|
|
|
Posted: Aug 26, 2011 - 02:33 PM |
|

Joined: Oct 05, 2006
Posts: 2297
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!
|
| |
|
|
|
|
|
Posted: Aug 26, 2011 - 02:36 PM |
|


Joined: Jul 18, 2005
Posts: 62944
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? |
_________________
|
| |
|
|
|
|
|
Posted: Aug 26, 2011 - 04:03 PM |
|

Joined: Oct 05, 2006
Posts: 2297
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!
|
| |
|
|
|
|
|
Posted: Jun 21, 2012 - 10:31 PM |
|

Joined: Oct 05, 2006
Posts: 2297
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, (..)
|
|
|
| |
|
|
|
|
|
Posted: Jun 22, 2012 - 09:18 AM |
|


Joined: Jul 18, 2005
Posts: 62944
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  |
_________________
|
| |
|
|
|
|
|
Posted: Jun 22, 2012 - 12:04 PM |
|

Joined: Oct 05, 2006
Posts: 2297
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? |
|
|
| |
|
|
|
|
|
Posted: Jun 22, 2012 - 12:37 PM |
|


Joined: Jul 18, 2005
Posts: 62944
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). |
_________________
|
| |
|
|
|
|
|
Posted: Jun 22, 2012 - 01:39 PM |
|

Joined: Oct 05, 2006
Posts: 2297
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
*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
|
| |
|
|
|
|
|
Posted: Jun 22, 2012 - 04:04 PM |
|


Joined: Oct 30, 2002
Posts: 5727
Location: The Netherlands
|
|
|
|
|
|
|