Author Topic: How to read/write the digital I/O  (Read 10749 times)

Offline marcelo_

  • Newbie
  • *
  • Posts: 25
    • View Profile
How to read/write the digital I/O
« on: June 06, 2010, 02:52:21 PM »
Hi all
I was searching the demo project ( V 1.4 ) for the 5225 demo board and cannot find the place where the led is toggled on/off, to learn by example.

Also, I would like to wake up a task whenever some input is present. How can I do that?

Thank you in advance

Regards

Marcelo

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: How to read/write the digital I/O
« Reply #1 on: June 06, 2010, 04:16:08 PM »
Hi Marcelo

The blink LED is toggled in the watchdog task.
This calls fnRetriggerWatchdog() which triggers the HW watchdog and also toggles the LED (if defined).

fnRetriggerWatchdog() (in M5223X.c in your case) will contain:

TOGGLE_WATCHDOG_LED();

which is assigned in app_hw_m5223x.h (it can also be a dummy macro if it shouldn't do anything).

An example is:
#define TOGGLE_WATCHDOG_LED()      _TOGGLE_PORT(TC, PORT_TC_BIT0)

Note that port control usually uses the port macros which can be found in M5223x.h (just search port macros to see the complete list of macros available, which tend to make control easier and also porting between different HW simpler based on the fact that the macros are essentially the same for all processors meaning that only the port name and bit number needs to be changed to suit).


To wake a task on an input change you may like to use edge port interrupts. There is an example in Port_Interrupts.h.
Ensure that SUPPORT_EPORT is enabled in app_hw_m5223x.h and the local define IRQ_TEST is enabled and fnInitIRQ() will then be executed. This configures specified edge ports to generate interrupts on the programmed change.
For example IRQ5 will be configured for an interrupt on a rising edge. This interrupt will execute:

static void test_irq_5(void)
{
    fnInterruptMessage(OWN_TASK, IRQ5_EVENT);
}


This sends an event to the local task, which effectively wakes it, with information about why it was woken. This makes monitoring inputs which support interrupts very easy. This will also work in the uTasker simulator - by clicking on teh ports to toggle their state and changes will result in interrupts being generated (according to programming) and so allowing configurations and applications to be tested.

Regards

Mark



Offline marcelo_

  • Newbie
  • *
  • Posts: 25
    • View Profile
Re: How to read/write the digital I/O
« Reply #2 on: June 07, 2010, 12:36:47 PM »
Hi, Mark!
Thank you again!
Marcelo

Offline marcelo_

  • Newbie
  • *
  • Posts: 25
    • View Profile
Re: How to read/write the digital I/O
« Reply #3 on: June 07, 2010, 11:49:39 PM »
Hi Mark

Sorry about my new questions, but this is the most obscure part of microcontrollers for me.

After recompiling with input's interrupts enabled, I was following the relevant demo code ( under simulation ) and cannot understand some things.
Beforehand, I must tell you that I'm interested in the NQ port, specifically in the pins 1 and 5, because these are connected to buttons in the 52259 demo board.

But when I change "input state" on the "NQ port" window representation, only the bit 7 ( pin 7? ) goes through the test_nmi_7() handler. And I cannot see when the bit mask is set when executing fnInitIRQ(), so only this "bit" awakes the expected path.

Is't needed to associate a distinct IRQ to every distinct input pin I am interested in? Or can I have a unique handler for the IRQ and get from it which of the pins was triggered? If this were the case, how?

Sorry again the bunch of questions, but I am a little confused.

TIA, again

Regards
Marcelo

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: How to read/write the digital I/O
« Reply #4 on: June 08, 2010, 12:54:54 AM »
Hi Marcelo

The NQ port is multiplexed with edge port interrupts (IRQ1..IRQ7 - not all are available, depending on processor type).

Each interrupt input has its own handler. In the demo the IRQ7 (this is non-maskable interrupt) will cause the test_nmi_7() routine to be called.

If you would like to test IRQ1 and IRQ5 you will need to ensure that these are entered. The demo code actually doesn't do this because it assumes that the lines are used for other functions (like MII management) but you can easily override this (remove the defines which are excluding them in the initialisation) - then use test_irq_1() and test_irq_5() as handlers.

It is not possible to have a general handler since each pin has its own interrupt routine and an individual handler is easier anyway.

Regards

Mark

Offline marcelo_

  • Newbie
  • *
  • Posts: 25
    • View Profile
Re: How to read/write the digital I/O
« Reply #5 on: June 08, 2010, 10:13:14 AM »
Thank you again, Mark
I will try what you told me.
Regards
Marcelo

Offline marcelo_

  • Newbie
  • *
  • Posts: 25
    • View Profile
Re: How to read/write the digital I/O
« Reply #6 on: June 10, 2010, 05:19:46 PM »
Hi Mark
I have one more question.
I followed your advice, and have the NQ pins 1 and 5 triggering my handlers. Both are set to trigger on RISING_EDGE.
But for production code I would need the handler be called on both edges, but being able to know which of them was the awakener.
I was diving in the code, and I am guessing that it's not posible, at least in target code.
Is it correct? In other words, to know the edge I would need two handlers?
TIA
Regards
Marcelo

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: How to read/write the digital I/O
« Reply #7 on: June 10, 2010, 06:00:54 PM »
Hi Marcelo

It is possible to configure for interrupt on both edges by using IRQ_BOTH_EDGES.

In your routine you can keep a backup of the last state that triggered to get an idea this may be adequate - the limit is the interrupt reaction time and so any faster changes will not be "seen". If you know the fastest input change rate you can probably work out whether it will always be reliable or not.

Example.
1) Input is '1' and you know this because your backup variable says 1.
2) Interrupt occurs and you check the input level (by reading the edge port register). It says '0' so you assume that it was a falling edge and set the variable to '0'.
3) Another interrupt follows and you read the input as '1'. Again no problem since a rising edge is assumed and the variable is set back to 1.
4) Now you get another interrupt but read the input as '1'. This suggests that you had a falling edge followed by a rising edge but this happens so fast that you didn't see the '0' state. The variable can stay at '1' and your code handle the double change state if it wants or ignore the 'glitch'

This will probably work well in most cases. What it can't do is detect how many changes occurred. Eg. Case 1) could have been three edges (from '1' to '0' to '1' and back to '0') or it could have been even more edges... Since these would still be rather fast it is probably not a real problem in most applications.

What you can also do is connect two interrupts together, one falling edge and one rising edge sensitive. Then there is a handler for each edge. In this instance there can be another difficulty though. If one edge has interrupt priority 1 and the other priority 5 and a pulse arrives very quickly the priority 5 interrupt will be called first. This means that the pulse may be '1' to '0' to '1' but the interrupt handling order nevertheless be rising edge followed by falling edge, which could cause confusion and even errors.

A final trick may be to use a general purpose counter as interrupt input. Such a counter also generates interrupt when the count value is reached (this can also be one pulse with either rising or falling sensitivity). A potential advantage is that the counter can also count the number of pulses that took place to cause the interrupt to occur, this even detecting multiple edges that occur at very high speed.

Regards

Mark

Offline marcelo_

  • Newbie
  • *
  • Posts: 25
    • View Profile
Re: How to read/write the digital I/O
« Reply #8 on: June 11, 2010, 04:30:16 PM »
Hi Mark
After some struggling with I/O interrupt awakening, I gave it up, because I take into account I need lots of digital inputs, so I'm turning to poll techniques.
But I cannot read them, or are doing the wrong thing.
At test stage, I are trying to "read" the NQ and DD ports. So, awakened by a timer, I'm showing in the telnet screen the PORTIN_SETNQ and PORTIN_SETDD values, which are allways 0xff, regardless of the state of the bits in the screen.
Also, I see that when changing some of the DD bits, it takes a lot of time to show the change at the screen.
Why may be the reason?
TIA, again.
Marcelo