port I/O abstraction macros

Everyone,

Earlier I posted some macros that allow you to easily define binary constants in C (see

formatting link
Playing similar tricks with the preprocessor, I now created some macros that allow you to make easy abstraction of port I/O's. It's written for the MSP430 but the concept can be applied to other embedded architectures.

You simply define your signal location like: #define LED P1,0 and then use them like: SETDIR(LED); CLR(LED); TOGGLE(LED);

The obvious advantage, besides readability, is that in the next hardware design or layout iteration - when most of the signals have shifted to different pins on different ports - all you need to change is one simple and readable #define in a central location.

Header file (or

formatting link

/* Port I/O abstraction macros - by Tom Torfs, 2006 * MSP430 implementation * Donated to the public domain. No warranties whatsoever. * * These macros allow you to make easy abstraction of I/O port & pin numbers. * You simply define your signal location like: * #define LED P1,0 * and then use them like: * SETDIR(LED); * CLR(LED); * TOGGLE(LED); * ... * * The obvious advantage, besides readability, is that in the next * hardware design or layout iteration - when most of the signals have * shifted to different pins on different ports - all you need to change * is one simple and readable #define in a central location * * In addition, nothing stops you from porting this header to other * microcontroller families. The specifics such as direction and interrupt * registers may be different but the basic concepts hold. * * Overview of user macros: * - Reading from port registers: (these are meant to be used in expressions) * x = IN(signal), OUTBUF(signal), DIR(signal), SEL(signal), IE(signal), IES(signal), IFG(signal) * - Writing to port registers: (these are meant to be used as statements) * output bit manipulation: SET(signal); CLR(signal); TOGGLE(signal); * direction bit manipulation: SETDIR(signal); CLRDIR(signal); * special function bit manipulation: SETSEL(signal); CLRSEL(signal); * interrupt bits manipulation: SETIE(signal); CLRIE(signal); SETIES(signal); CLRIES(signal); * interrupt flag manipulation: SETIFG(signal); CLRIFG(signal); * copy 1 or 0 into output bit: CPYBIT(signal,bitvalue) * - Getting the port name (string) or bit number (integer literal) corresponding to a signal: * const char s[] = PORTNAME(name); * x = BITNUM(name); * - Interrupt vector for port corresponding to a signal: (requires compiler-specific mapping) * INTVECTOR(name) */

/********** HELPER MACROS **********/

#define POUT_(Pn) Pn##OUT #define PIN_(Pn) Pn##IN #define PDIR_(Pn) Pn##DIR #define PSEL_(Pn) Pn##SEL #define PIE_(Pn) Pn##IE #define PIES_(Pn) Pn##IES #define PIFG_(Pn) Pn##IFG

#define IN_(p,b) (PIN_(p)&(1

Reply to
Tom Torfs
Loading thread data ...

I prefer to go a step further, because these types of macros require you to embed the hardware's logic state throughout your code. I use macros like:

#define LED_ON(led) LED_ ## led = 1 #define LED_OFF(led) LED_ ## led = 0

#define LED_GREEN some_port_pin_name

LED_ON(GREEN);

which I find more readable (neither I nor the person reading my code needs to remember whether a logic high or a logic low turns on an LED), and more maintainable (when the hardware changes and the LEDs become active low, I just have to make a change in a header).

This doesn't work when some LEDs are active high and others are active low, but in that case I'll use something like:

#define LED_GREEN some_port_pin_name #define LED_GREEN_ON LED_GREEN = 1 #define LED_GREEN_OFF LED_GREEN = 0

which still keeps the logic state of the hardware in one place.

--
John W. Temples, III
Reply to
John Temples

I do that too, using my macros that would become then:

#define LED_ON(led) CLR(led) #define LED_OFF(led) SET(led)

However, often you need more complicated operations than just setting or clearing the bit - manipulating corresponding interrupt flags, direction registers, associated interrupt vectors etc. For these operations, the macros I posted automatically map the correct port registers for the signal (e.g. for P2.3 on MSP430 this would pick out bit 3 of P2OUT, P2IN, P2DIR, P2SEL, P2IE, P2IES and P2IFG, respectively).

greetings, Tom

Reply to
Tom Torfs

We take on alot of intern students and student projects etc. and I have always found their ability to do bitwise manipulation in C to be completely hopeless. What are universities teaching them these days? Its the year 2006 and they still come out knowing how to program an 8051 in assembly but not knowing what c &= ~(1

Reply to
DAC

DAC,

Reply to
Tom Torfs

Reply to
Mark McDougall

Reply to
Tom Lucas

... snip ...

Please tell us where you took this course, so we are at least warned that their graduates are uneducated. Bit manipulation is tied into binary numbers, and is not in the least hard to understand. Ladder diagrams are something else.

--
 "Our enemies are innovative and resourceful, and so are we. 
  They never stop thinking about new ways to harm our country
  and our people, and neither do we."          -- G. W. Bush.
 "The people can always be brought to the bidding of the
  leaders.  All you have to do is tell them they are being
  attacked and denounce the pacifists for lack of patriotism
  and exposing the country to danger. It works the same way
  in any country."                         --Hermann Goering.
Reply to
CBFalconer

This was Cardiff University and their standard of education is actually very good. Binary arithmetic was certainly covered and so all the students would certainly have understood bit manipulation from that side but my point was that it was rarely, if ever, linked to embedded programming. I'm sure the class could tell you what "c &= ~(1

Reply to
Tom Lucas

I just had a protracted argument about hiring someone who claimed to have device driver writing experience, but did not know how to divide and integer by 32 using bit shifting. The other members of the team did not think this was something that a Senior Software Engineer should know.

I know of at least 3 technical universities that will not let you get a B.S.E.E. without knowing how to write a compiler, and will not let you get a B.S.C.S without knowing how to design an FM radio. The idea is to quash any possibility that you might subsequently misrepresent your university as an idiot who cannot divide a number by 32 using bit-shifting.

-Le Chaud Lapin-

Reply to
Le Chaud Lapin

... snip ...

Well, the primary function of a university is to teach how to learn. The details of what to learn are somewhat secondary. The emphasis in a technical school is somewhat more concentrated on subject matter. So the key thing in an interview is how fast does the interviewee catch on, rather than the detailed knowledge.

--
 "Our enemies are innovative and resourceful, and so are we. 
  They never stop thinking about new ways to harm our country
  and our people, and neither do we."          -- G. W. Bush.
 "The people can always be brought to the bidding of the
  leaders.  All you have to do is tell them they are being
  attacked and denounce the pacifists for lack of patriotism
  and exposing the country to danger. It works the same way
  in any country."                         --Hermann Goering.
Reply to
CBFalconer

How do you elegantly divide a _signed_ integer by 32 using shifts in systems that are using 2's complement representation ?

Paul

Reply to
Paul Keinanen

You use arithmetic shifts where the MSB is duplicated rather than using a logical shift.

In C and C++ the >> operator has implementation-defined results on a signed integer, so it isn't going to be very elegant if it is written to be portable. So I guess you could use Java which uses >> for arithmetic and >>> for logical.

Best regards, Spehro Pefhany

--
"it's the network..."                          "The Journey is the reward"
speff@interlog.com             Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog  Info for designers:  http://www.speff.com
Reply to
Spehro Pefhany

Not sure if this is elegant or correct (no time to check), but I would just shift if the value is non-negative and shift-plus-or-in-1's if it is negative:

x = x & (1 > 5) | ~((~0U) >> 5)) : (x

Also I guess I failed to mention - in the exam that I gave the interviewee, I told him up front that the value to be divided was unsigned, and that he could ignore any round-off errors.

You braved Java. I'm impressed. :)

-Le Chaud Lapin-

Reply to
Le Chaud Lapin

Any decent compiler (for any language) should do that for a signed data type.

That does not solve the problem.

What do you get even with MSB duplication in 2's complement notation, when you shift -3 one position to the right ? I got -2.

Now we have to discuss, what INT(-3/2) should be. At least I learned in primary school that this should be -1, not -2.

Paul

Reply to
Paul Keinanen

I certainly agree.

That's why I interview people on multiple axes to give them an opportunity to show their value. I look for

  1. intelligence
  2. knowledge
  3. passion

If a person seems to be lacking in knowledge, I attempt to check intelligence/passion by asking questions that the person should know. For example, one recent candidate had studied geophysics for undergraduate (not electrical engineering or computer science), and was having trouble with his knowledge domain on Windows. So I asked him questions about geophysics (based on what little I knew). Because he did not answer these questions very well, I had to conclude that he was just looking for a job to have a salary.

I also started making generic exams to be used during interviews in our (multi-billion $US) company (yes, strange, i know). The idea is to create a separation between the interviewer and the interviewee. Some candidates have cling - they cling to you like a charged sock - when you try to get them to answer a question. With paper exams, some degree of objectivity can be maintained.

Incidentally, this person who did not know how to divide by 32 using >>

scored the lowest on the C++ exam of all candidates I interviewed. During a heated post-interview discussion with HR, the HR rep implied that the introduction of paper exams is less objective than what we were doing before - ad hoc, hand-waiving qualifications with no notes whatsover, just personal opinions.

-Le Chaud Lapin-

Reply to
Le Chaud Lapin

But it's *not* guaranteed.

ISO/IEC 9899:1999 (E) 3.4.1

1 implementation-defined behavior unspecified behavior where each implementation documents how the choice is made 2 EXAMPLE An example of implementation-defined behavior is the propagation of the high-order bit when a signed integer is shifted right.

In this case, both answers have an |error| = 0.5

If you take INT(-7/4) you get -1 using the division operator, and -2 using two arithmetic shifts. The former has an |error| of 0.75 vs 0.25 for the >> operator. In enjineering school I learned that smaller errors are better. ;-)

Best regards, Spehro Pefhany

--
"it's the network..."                          "The Journey is the reward"
speff@interlog.com             Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog  Info for designers:  http://www.speff.com
Reply to
Spehro Pefhany

#define DIVBY32(i) (i>5):i>>5) // Will not work with the lowest negative number

i = DIVBY32(i);

--
Best Regards,
Ulf Samuelsson
ulf@a-t-m-e-l.com
This message is intended to be my own personal view and it
may or may not be shared by my employer Atmel Nordic AB
Reply to
Ulf Samuelsson

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.