Show Posts
Pages: 1 2 3 [4] 5 6
46  Using Arduino / Programming Questions / How to give a C++ variable name to an asm statement? on: February 07, 2012, 07:45:05 pm
Hello,

I am trying to do something like this:

Code:
asm volatile("sts %0, r0" : "+M" (PCintPort::curr) );

But the error I'm getting is:

Code:
error: impossible constraint in 'asm'

I find that it's easy to do a c-style asm statment, like:

Code:
uint8_t myvariable;

asm volatile("sts myvariable, r0");

But using a static C++ class variable is confounding me.  The variable is declared thus:

Code:
class PCintPort {
public:
    static  uint8_t curr;
}

Thanks.
47  Using Arduino / Programming Questions / Re: Mixing C with Assembler: Assembly code before push instructions in a function on: February 07, 2012, 07:40:11 pm
Good point.  I may use r0, but I'll push/pop it.  Thanks- 1 push instruction won't hurt.

Not good enough.  You have to preserve the registers used by your function before the function is called.

I understand about r0 (which I'll use) and SREG, but doesn't the compiler push all registers it's concerned with?  I've been rummaging around in avr-objdump and I observe that the compiler preserves registers upon entry into the function, not before functions are called.

I am setting ISR_NAKED for the ISR, but when the ISR calls another function that will not be naked.
48  Using Arduino / Programming Questions / Re: Mixing C with Assembler: Assembly code before push instructions in a function on: February 07, 2012, 03:31:44 pm
Good point.  I may use r0, but I'll push/pop it.  Thanks- 1 push instruction won't hurt.
49  Using Arduino / Programming Questions / Re: Mixing C with Assembler: Assembly code before push instructions in a function on: February 07, 2012, 10:37:57 am
... if they're trampled by a push operation then using one of these as a scratch area while you do the push would not work very well.

... write your ISR handler in assembler, have this save your I/O register in your temp register and then call a 'C'/C++ function for whatever logic you want to code in higher level languages. You sound as if you're comfortable writing in assembler, but if you aren't you could get a starting point by listing the assembler generated for your existing handler.
Excellent suggestion, thanks for the tips!  I am not comfortable writing in assembler, so I am going to list the assembler generated and work from there :-) .  But, I am comfortable living life on the edge!  So I'm going to try it.

My intention is to get the heck out of the way of the compiler as quickly as possible, so I'm thinking I might need 2 assembly instructions:  1 to read the register, the other to save it to a C variable (ie, RAM).

I notice that my idea is not so far fetched, as a matter of fact I found this link: http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html .  The ISR_NAKED is what I want.  So, my idea is the following, pseudo-code:

Code:
ISR(PCINT0_vect, ISR_NAKED)
{
    asm (read_in_register_to_r0)
    asm (store_to_ram)
    // The following function call will preserve the registers on the stack.  Since I haven't
    // mucked with any but r0 thus far in my ISR, I should be ok.  The function call will
    // also restore the necessary registers.
    C_function_call();
    asm (reti);
}

I notice that the ISR pushes a whole bunch of registers on the stack.  Function calls do not necessarily save the same large set.  I assume that's because the compiler is smart enough to know that a function may not stomp on all the registers, so it's judicious in its saving.  Thus, it seems to me the ISR is storing such a large set because it doesn't have any foreknowledge of what it should or should not preserve, so it paints with a large brush.

But if the *only* thing my ISR does is as listed:  1. my assembly, 2. call a C function, 3. return, then I assume that the heavy lifting of pushing and popping the necessary registers, if handled solely by the C function call in the ISR, should be sufficient. There are no other dragons lying about out, are there?  Again, assuming my ISR is just that lean.

Right now my ISR looks like this:
Code:
ISR(PCINT0_vect) {
        portD.PCint();
}
...so it's doing two bunches of push/pop operations:  The entry into the ISR, and the entry into the function call, which is overkill.

...Just checking my assumptions...
50  Using Arduino / Programming Questions / Re: Mixing C with Assembler: Assembly code before push instructions in a function on: February 07, 2012, 09:35:33 am
I would like to preserve the state of a register very quickly when the interrupt takes place.

I guess you mean you want to preserve the state of an I/O register at the earliest possible point in an ISR.
Exactly!  You hit the nail on the head.  I am writing a library and I am preserving the state of an I/O register- ostensibly at the time of the interrupt- but with all the push instructions, it takes place some 4 microseconds (I figure) after the actual interrupt.

Quote
Have you thought of a way to do that without using any processor registers? Since you can't know what processor registers are in use you mustn't use them until you have preserved their state so that they can be restored afterwards.
Not really.  I am aware of this:
Quote
Register r0 may be freely used by your assembler code and need not be restored at the end of your code. It's a good idea to use __tmp_reg__ and __zero_reg__ instead of r0 or r1, just in case a new compiler version changes the register usage definitions.
So I believe I can safely use r0.  All I need is to use the in instruction, then save that register to RAM, and I should be good to go.
51  Using Arduino / Programming Questions / Re: Mixing C with Assembler: Assembly code before push instructions in a function on: February 07, 2012, 09:31:00 am

Do you understand the purpose of the push instructions?

Quote
I want to insert some assembler which is to be run before those registers are preserved.

Does the "some assembler" include an in instruction (like your pseudo-code)?


Yes, and yes.  I plan on taking advantage of this:

Quote
Register r0 may be freely used by your assembler code and need not be restored at the end of your code. It's a good idea to use __tmp_reg__ ... instead of r0 or r1, just in case a new compiler version changes the register usage definitions.
52  Using Arduino / Programming Questions / Mixing C with Assembler: Assembly code before push instructions in a function on: February 07, 2012, 01:02:00 am
Hello,
I am calling a function from an interrupt, and due to timing issues I would like to preserve the state of a register very quickly when the interrupt takes place.

The C compiler generates a bunch of code to preserve registers when the ISR (or any function) is called.  I want to insert some assembler which is to be run before those registers are preserved.  Is this possible?  Is there some directive I can add to my asm line to tell it exactly where to inject itself in the C code?  Thanks.

The code looks iike this.  I know- the push instructions are there to preserve registers.  Consider my asm to be pseudo-code; I will figure out how to use __tmp_reg__ if I decide that my efforts are worth it.  Thanks:
Code:
ISR(PCINT2_vect) {
    uint8_t value;
    // I want this to take place before the compiler-created push instructions.
    asm volatile("in %0, %1" : "=r" (value) : "I" (_SFR_IO_ADDR(PORTD)));
    portD.PCint();
}
53  Community / Exhibition / Gallery / Re: PinChangeInt library- To attach interrupts to multiple Arduino (Uno/Due) pins on: February 06, 2012, 12:45:57 am
...aaaand, version 1.51 is out.  Fixes a bug in 1.5, that caused the pinState to be incorrectly reported  smiley-roll-sweat  .  It appears to work correctly now.  Apologies for the messup.
54  Community / Exhibition / Gallery / Re: PinChangeInt library- To attach interrupts to multiple Arduino (Uno/Due) pins on: February 03, 2012, 10:41:45 pm
I just posted version 1.5.  From the notes:

Code:
Version 1.5 Thu Feb  2 18:09:49 CST 2012
Added the PCintPort::pinState static variable to allow the programmer to query the state
of the pin at the time of interrupt.

Added two new #defines, NO_PIN_STATE and NO_PIN_NUMBER so as to reduce the code
size by 20-50 bytes,and to speed up the interrupt routine slightly by declaring that you
don't care if the static variables PCintPort::pinState and/or PCintPort::arduinoPin are set
and made available to your interrupt routine.
// #define NO_PIN_STATE        // to indicate that you don't need the pinState
// #define NO_PIN_NUMBER       // to indicate that you don't need the arduinoPin
55  Using Arduino / Programming Questions / Re: How to give an Object as an Argument to a Function? (...not to a class method) on: January 21, 2012, 11:30:43 am
Ok, yes that makes sense now I suppose.  I'm not totally happy about it, but at least I understand.

Thanks again!
56  Using Arduino / Programming Questions / Re: How to give an Object as an Argument to a Function? (...not to a class method) on: January 21, 2012, 10:32:18 am
Ok, thanks... I got it now.  But I don't get the separation of files.  I have created classes in the sketch without issue.

My understanding of including files goes like this:  The C preprocessor finds the directive, and for all intents and purposes, what the C++ compiler is presented with is essentially the entire text of the included files, along with the file that contains the include directive, in one flow of textual data.

What difference does pulling the class out of the sketch make?  ...I mean, technically.  What is going on under the covers that we don't see?

Thanks again for your response(s).
57  Using Arduino / Programming Questions / How to give an Object as an Argument to a Function? (...not to a class method) on: January 21, 2012, 09:32:47 am
Hi,
I am trying to give an object as an argument to a function, but I am getting an error:
Code:
class myclass
{
  public:
 
  void yo() {
    Serial.println("Hello");
  }
};

myclass pbs=myclass();

void reportit(pbs& i) {
  //i.yo(); // If this didn't give an error, I would uncomment this method call.ß
  Serial.print("test");
};

void setup()
{
  Serial.begin(115200); Serial.println("---------------------------------------");
};

void loop() {
};

but I get this error:

tmp:-1: error: variable or field 'reportit' declared void
tmp:-1: error: 'pbs' was not declared in this scope
tmp:-1: error: 'i' was not declared in this scope
tmp:11: error: variable or field 'reportit' declared void
tmp:11: error: 'i' was not declared in this scope

...Can you tell me why?
58  Development / Suggestions for the Arduino Project / Re: How to give an Object as an Argument to a Function? (...not to a class method) on: January 21, 2012, 09:29:23 am
OOps, drat- I got a typo and confused the issue.  I will ask this in the programming forum section.

I don't know why people think you can't define classes in the sketch.  I do it all the time, with no issues.
59  Development / Suggestions for the Arduino Project / How to give an Object as an Argument to a Function? (...not to a class method) on: January 21, 2012, 01:38:08 am
Hi,
I am trying to give an object as an argument to a function, but I am getting an error:

Code:
class myclass
{
  public:
 
  void yo() {
    Serial.println("Hello");
  }
};

void reportit(pbs& i) {
  //i.yo(); // If this didn't give an error, I would uncomment this method call.
  Serial.print("test");
};


void setup()
{
  Serial.begin(115200); Serial.println("---------------------------------------");
};

void loop() {
};

But it gives:

tmp:-1: error: variable or field 'reportit' declared void
tmp:-1: error: 'pbs' was not declared in this scope
tmp:-1: error: 'i' was not declared in this scope
tmp:10: error: variable or field 'reportit' declared void
tmp:10: error: 'pbs' was not declared in this scope
tmp:10: error: 'i' was not declared in this scope

Can anyone help?  Thanks.
60  Development / Suggestions for the Arduino Project / Re: Delegate system for member function pointers on: January 21, 2012, 01:34:00 am
Very useful indeed.  Thanks for posting.
Pages: 1 2 3 [4] 5 6