On my last post where I posted an example, I also tacked on the comment at the end that the PORTBASE could be changed to the vport address. I then realized the spacing of those addresses (4) did not make sense and saw that these vport registers are just a minimal set. I deleted the comment, but you may have seen it before I deleted it. Didn't mean to send you on the wrong path with vport, although now you know.
I probably shouldn't cause more confusion, but...
Here's what (I think) can be done using vport addresses. This is the exact same code as I posted in my previous post, except now using vport addresses. The calculation of the vport port offset (a,b,c...) is different (>>3) and the register offsets are different ([1]=OUT, [2]=IN), but otherwise the its mostly the same except now the IN/OUT/CBI/SBI instructions are available.
I think this is correct, but not 100% certain.
//test.c
#include <stdint.h>
#include <stdbool.h>
typedef enum {
A0=0x00, A1, A2, A3, A4, A5, A6, A7,
B0=0x20, B1, B2, B3, B4, B5, B6, B7,
C0=0x40, C1, C2, C3, C4, C5, C6, C7,
D0=0x60, D1, D2, D3, D4, D5, D6, D7,
E0=0x80, E1, E2, E3, E4, E5, E6, E7,
F0=0xA0, F1, F2, F3, F4, F5, F6, F7,
//all my pin info here
SW1=A2, LED1=B3
} PIN_t;
//added VPORTBASE- also added 0x20 offset as
//vport addresses are IO addresses (in iom4809.h), seems we
//need to get vport address into a 'mem' address range
//so the compiler will see its in the IO address range (confusing, yes)
//go read srf_defs.h for a good time
enum { PORTBASE= 0x400, VPORTBASE = 0x20 };
static inline bool pin_get(PIN_t pin)
{
//VPORTBASE offset [2] is IN register
return ( (volatile uint8_t*)(VPORTBASE+(pin>>3)) )[2] & (1<<(pin&7));
}
static inline void pin_set(PIN_t pin, bool tf){
//VPORTBASE offset [1] is OUT register
if(tf)( (volatile uint8_t*)(VPORTBASE+(pin>>3)) )[1] |= 1<<(pin&7);
else ( (volatile uint8_t*)(VPORTBASE+(pin>>3)) )[1] &= ~(1<<(pin&7));
}
void main()
{
pin_set( LED1, pin_get(SW1) );
for(;;);
}
/*
./avr-gcc -C -Os test.c && ./avr-objdump -d a.out
Disassembly of section .text:
00000000 <main>:
0: 12 9b sbis 0x02, 2 ; 2
2: 02 c0 rjmp .+4 ; 0x8 <__zero_reg__+0x7>
4: 2b 9a sbi 0x05, 3 ; 5
6: 01 c0 rjmp .+2 ; 0xa <__zero_reg__+0x9>
8: 2b 98 cbi 0x05, 3 ; 5
a: ff cf rjmp .-2 ; 0xa <__zero_reg__+0x9>
*/
edit-
and to make it complete by setting the pin dirs, one could add
typedef enum { DIR_IN, DIR_OUT } DIR_t;
static inline void pin_dir(PIN_t pin, DIR_t dir)
{
//VPORTBASE offset [0] is DIR register
if(dir)( (volatile uint8_t*)(VPORTBASE+(pin>>3)) )[0] |= 1<<(pin&7);
else ( (volatile uint8_t*)(VPORTBASE+(pin>>3)) )[0] &= ~(1<<(pin&7));
}
with this added to main
pin_dir( LED1, DIR_OUT );
pin_dir( SW1, DIR_IN );
resulting in this additional code
0: 23 9a sbi 0x04, 3 ; 4
2: 02 98 cbi 0x00, 2 ; 0