Jump to content
Sign in to follow this  
Peabody

Converting MPS430 assembler code to Energia

Recommended Posts

I'm working on a reflow controller with a G2553 driving a solid state relay to control power.  It also includes a rotary encoder with push button and two 7-segment displays to adjust and display the duty cycle.  I've written it in assembler, and all of the activity takes place within the interrupt service routine triggered every 2ms by the watchdog timer in interval timer mode.  Between interrupts, the processor sleeps.  In assembler, the service routine does its magic in about 0.1ms, or 1/20th of the total time, so there's no danger of an overrun into the next trigger.  There are no pin interrupts because the encoder and push button are serviced by polling.

I'm thinking about converting the software to Energia to make it more accessible to others, and possibly also to Arduino for the same reason.  But I'm having trouble finding Energia or Arduino examples of setting up timer-based interrupts other than fiddling directly with the registers.  If anyone can point me to information on any higher-level commands that implement timer interrupts, I would appreciate it.

One other general question I have concerns pin interrupts.  My understanding is that MSP430 parts can do rising or falling edge interrupts, but I've seen examples of people using "change" interrupts as are available on Atmel parts.  Can someone explain how an on-change interrupt is actually implemented for MSP430 parts?

Thanks very much.

 

Share this post


Link to post
Share on other sites
6 hours ago, Peabody said:

One other general question I have concerns pin interrupts.  My understanding is that MSP430 parts can do rising or falling edge interrupts, but I've seen examples of people using "change" interrupts as are available on Atmel parts.  Can someone explain how an on-change interrupt is actually implemented for MSP430 parts?

12.2.7.2 Interrupt Edge Select Registers (PxIES)
Each PxIES bit selects the interrupt edge for the corresponding I/O pin.
• Bit = 0: Respective PxIFG flag is set with a low-to-high transition
• Bit = 1: Respective PxIFG flag is set with a high-to-low transition
 

as for example code, it depends on what you are trying to detect.

lets say you know the initial state, then you can toggle the PxIES bit on each interrupt call.

or if you dont know the initial state, then you can toggle PxIES in your main code, but may miss a change.

or you can poll the pin for the change in SW

.

 

 

 

Share this post


Link to post
Share on other sites

I found this code for a rotary encoder providing fine and coarse adjusment:

https://forum.43oh.com/topic/9306-energia-library-rotary-encoder-with-coarse-fine-adustment/?tab=comments#comment-70635

Included in the .ino file on Github is the following:

----------------------------------------------------------

void setup() {

Serial.begin (115200);

pinMode(buttonPin, INPUT_PULLUP);

pinMode(encoderPin1, INPUT_PULLUP);

pinMode(encoderPin2, INPUT_PULLUP);

attachInterrupt(encoderPin1, ISR_Encoder1, CHANGE); // interrupt for encoderPin1

attachInterrupt(encoderPin2, ISR_Encoder2, CHANGE); // interrupt for encoderPin2

attachInterrupt(buttonPin, ISR_Button, FALLING); // interrupt for encoder button

------------------------------------

And I'm having trouble understanding the "CHANGE" interrupts.  My understanding is that MSP430 I/O pins don't have a "change" interrrupt.

What am I missing here?

 

Share this post


Link to post
Share on other sites

Hmmm... that code looks familiar. Energia implements an interrupt with change, probably by the method that jsolarski suggests above.  I don’t use Energia much anymore but it is open source so you can have a look at that if you are interested. 

Share this post


Link to post
Share on other sites
1 hour ago, Fmilburn said:

Hmmm... that code looks familiar. Energia implements an interrupt with change, probably by the method that jsolarski suggests above.  I don’t use Energia much anymore but it is open source so you can have a look at that if you are interested. 

I wouldn't know how to find it.  In any case, your code compiled ok, and ran ok, with the on CHANGE interrupt?  Well, it's a mystery.

Share this post


Link to post
Share on other sites

the code for the attach interrupt -- the magic that makes it work....lol

 

void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
	uint8_t bit = digitalPinToBitMask(interruptNum);
	uint8_t port = digitalPinToPort(interruptNum);

	if ((port == NOT_A_PIN) || !((mode == FALLING) || (mode == RISING)
		|| (mode == CHANGE))) return;

	__dint();
	switch(port) {
	case P1:
		if(mode != CHANGE) {
			P1IES = mode ? P1IES | bit : P1IES & ~bit;
		} else {
			intChangeVectP1 |= bit;
			P1IES = (P1IN & bit) ? (P1IES | bit) : (P1IES & ~bit);
		}
		P1IFG &= ~bit;
		intFuncP1[bit_pos(bit)] = userFunc;
		P1IE |= bit;
		break;

 

 

 

Share this post


Link to post
Share on other sites

even if you are no good at C, you can start reading and understanding it, it will help in all your projects. it will give you an understanding of what the code is actually doing.

 

just start with learning bitwise operators.

|,^,~,&...etc  you can do fancy things like toggle a pin on and off with few lines of code.

 

1 hour ago, Peabody said:

I think I will not attempt to use an interrupt on CHANGE.

 

I do agree not to use CHANGE, and just look for rising or falling edges.

Share this post


Link to post
Share on other sites

Aside from the interrupt on change issue, I haven't found any way to set up a timer interrupt in Energia other than fiddling with the registers.  But as it turned out, all I had to do was put the entire loop() code in an IF statement that tests whether the required number of millis had passed.  So basically it just does that test over and over, but only executes the code every 2ms.  In assembler, I put the processor to sleep between interrupts, but haven't found a way to do that in Energia.  Anyway, I've finished porting the assembler code into an Energia .ino, and it works fine.  The hex file is about twice as large as the assembler version, which is actually less than I expected.

 

 

Share this post


Link to post
Share on other sites

Energia may not have all the options implemented, you are probably going to have to setup the timer manually and hope it doesnt conflict with what energia sets up.

what kind of timer interrupt are you looking for?   WDT? TIMER0A? periodic or one time? and are you planning to put the CPU to sleep?

I can help to get a basic code setup for you.

Share this post


Link to post
Share on other sites

I have everything done that I need at this point.  As the original post described, the assembler code did everything inside the interrupt service routine.  I was looking for a way to do that in Energia, but using millis and the IF statement accomplishes the same thing.  The only difference is that in assembler I was able to turn the processor off between interrupts, which saves some power, but probably not all that much since the oscillator is still running.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...