[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[avr-chat] Variable Pinouts - How do you do it?
From: |
Johannes Bauer |
Subject: |
[avr-chat] Variable Pinouts - How do you do it? |
Date: |
Mon, 21 Aug 2006 16:16:41 +0200 |
User-agent: |
Mozilla Thunderbird 1.0.7 (X11/20051015) |
Hello list,
I've got a question on how you handle variable pinouts of you uC
hardware. As I wan't to be as flexible as possible, I've developed a
kind of practice which I'd like to discuss here (bad idea? How can I do
better?).
Currently, I'm creating a pinout.txt file, which looks like this:
PC6 LED_Red 1 1
PC7 LED_Green 1 1
PC5 LED_Yellow 1 -1
First column is the Portpin, second one is the description. The third
parameter tells my preprocessor to generate LowLevel-Function
(LED_Red_Output(), LED_Red_Input(), LED_Red_Set0(), LED_Read_Set1()),
the fourth parameter tells the preprocessor to also generate
HighLevel-Functions (_On(), _Off()). When the fourth argument is
negative it means that the Pin is Low-Active (e.g. a LED which is wired
agains +5V).
This is pretty neat and useful - porting on other uCs is really easy
that way. The problem is the generated code. Say I have
LED_Red_Output();
LED_Yellow_Output();
LED_Green_Output();
This translates ultimately to:
(*(volatile uint8_t *)((0x14) + 0x20)) |= (1<<6);
(*(volatile uint8_t *)((0x14) + 0x20)) |= (1<<5);
(*(volatile uint8_t *)((0x14) + 0x20)) |= (1<<7);
Which then gives:
5dc: a6 9a sbi 0x14, 6 ; 20
5de: a5 9a sbi 0x14, 5 ; 20
5e0: a7 9a sbi 0x14, 7 ; 20
Of course these two are different:
DDRD |= (1<<6) | (1<<5) | (1<<7);
and
DDRD |= (1<<6);
DDRD |= (1<<5);
DDRD |= (1<<7);
As in the latter case, each ORing of the bits is done in it's own
clockcycle. However, the thing the programmer usually _means_ IMHO is
the first one. Therefore, could an optimization be implemented which
upon getting some special switch like -fcombine-bitoperations combines
operations on the Registers <0x60 into something of the sort:
5e4: 81 b3 in r24, 0x11 ; 17
5e6: 80 6e ori r24, 0xE0 ; 224
5e8: 81 bb out 0x11, r24 ; 17
This doesn't make sense when there are only three instructions, but if
four instructions would be used, it would make sense.
Also code of the kind:
DDRD |= (1<<6) | (1<<7) | (1<<5);
DDRD &= ~((1<<3) | (1<<4));
Currently translates to:
5e4: 81 b3 in r24, 0x11 ; 17
5e6: 80 6e ori r24, 0xE0 ; 224
5e8: 81 bb out 0x11, r24 ; 17
5ea: 81 b3 in r24, 0x11 ; 17
5ec: 87 7e andi r24, 0xE7 ; 231
5ee: 81 bb out 0x11, r24 ; 17
(BTW, I don't know why actually there is the second "in" instruction in
there... isn't that useless?)
After this optimization, we'd have
5e4: 81 b3 in r24, 0x11 ; 17
5e6: 80 6e ori r24, 0xE0 ; 224
5ec: 87 7e andi r24, 0xE7 ; 231
5ee: 81 bb out 0x11, r24 ; 17
Also code would need to be rearranged for full use:
DDRD |= (1<<4); PORTD |= (1<<4);
DDRD |= (1<<5); PORTD |= (1<<5);
DDRD |= (1<<6); PORTD |= (1<<6);
DDRD |= (1<<7); PORTD |= (1<<7);
Currently becomes:
5e4: 8c 9a sbi 0x11, 4 ; 17
5e6: 94 9a sbi 0x12, 4 ; 18
5e8: 8d 9a sbi 0x11, 5 ; 17
5ea: 95 9a sbi 0x12, 5 ; 18
5ec: 8e 9a sbi 0x11, 6 ; 17
5ee: 96 9a sbi 0x12, 6 ; 18
5f0: 8f 9a sbi 0x11, 7 ; 17
5f2: 97 9a sbi 0x12, 7 ; 18
But could be optimized to:
5e4: 81 b3 in r24, 0x11 ; 17
5e6: 80 6f ori r24, 0xF0 ; 240
5e8: 81 bb out 0x11, r24 ; 17
5ea: 82 b3 in r24, 0x12 ; 18
5ec: 80 6f ori r24, 0xF0 ; 240
5ee: 82 bb out 0x12, r24 ; 18
I'd be really interested in how you keep your programs as portable as
possible. Please enlighten me on how you deal with that problem :-)
Greetings,
Johannes
- [avr-chat] Variable Pinouts - How do you do it?,
Johannes Bauer <=