GP2X Gp2x Demo Development Part 3


This is good stuff, thanks synkro. I see there is some clean up code in there now, I had been playing with a bit of th original code and had some SD mem card probs, turns out the mem file was not closed, which it is now.

I'm still experimenting but hope to create (unless someone has already done it) a struct defining the regs. So that you can map address 0xc0000000 to it and start messing about. Still early days so may not be the way to go. :unsure: I've done the UART ones, but my tests using them have failed, i'm being a bit nieve there I think. Here it is to give you an idea of what i'm thinking about.

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;

(formatting gone to pot a bit)

struct UART
{
struct
{
u16 word_len :2;
u16 stopbit :1;
u16 parity_mode :3;
u16 sir_mode :1;
u16 reserved :9;
}lcon; //line control register

struct
{
u16 receive_mode :2;
u16 trans_mode :2;
u16 send_break :1;
u16 loopback_mode :1;
u16 rx_errstatus :1;
u16 rx_timeout :1;
u16 rx_int :1;
u16 tx_int :1;
u16 reserved :6;
}ucon; //control register

struct
{
u16 fifo_en :1;
u16 rx_fifo_reset :1;
u16 tx_fifo_reset :1;
u16 reserved0 :1;
u16 rx_fifo_trigger :2;
u16 tx_fifo_trigger :2;
u16 reserved1 :8;
}fcon; //FIFO control register

struct
{
u16 rts_active :1;
u16 dtr_active :1;
u16 reserved0 :1;
u16 modem_int :1;
u16 afc :1;
u16 reserved1 :11;
}mcon; //Modem control register

struct
{
u16 receive_buffer_data_ready :1;
u16 transmit_buffer_data_empty :1;
u16 transmitter_empty :1;
u16 reserved :13;
}trstatus; //TR/TX Status register

struct
{
u16 overrun_error :1;
u16 parity_error :1;
u16 frame_error :1;
u16 break_detect :1;
u16 reserved :12;
}estatus; //Error status register

struct
{
u16 rx_fifo_count :4;
u16 tx_fifo_count :4;
u16 rx_fifo_full :1;
u16 tx_fifo_full :1;
u16 rx_fifo_error :1;
u16 reserved :5;
}fstatus; //FIFO Status register

struct
{
u16 cts :1;
u16 dsr :1;
u16 ri :1;
u16 dcd :1;
u16 delta_cts :1;
u16 delta_dsr :1;
u16 delta_ri :1;
u16 delta_dcd :1;
u16 reserved :8;
}mstatus; //Modem status register

struct
{
char value :8;
u8 reserved :8;
}thb; //Transmit buffer register (holding register & fifo register)

struct
{
char value :8;
u8 reserved :8;
}rhb; //Receive buffer register (holding register & fifo register)

u16 brd; //Baud rate divisor;
u16 timeoutreg; //Recieve timeout.

};
 
MadDog: I've seen similar structures defined for other processor/environments, it is very useful! Good luck with it.

Oh, the original code did clean up.

Synkro: thanks for your efforts!
 
Dzz posted on Apr 27 2006 at 08:12 PM said:
MadDog: I've seen similar structures defined for other processor/environments, it is very useful! Good luck with it.

Yer, there was loads of it with the Sony sdk's i've used over the years, its where I got the idea. ;)


Dzz posted on Apr 27 2006 at 08:12 PM said:
Oh, the original code did clean up.

Did it, cut'n'paste error on my part then, whoops. :D
 
Last edited by a moderator:
Hi,

MadDog posted on Apr 27 2006 at 07:46 PM said:
struct UART
{
...

struct
{
char value :8;
u8 reserved :8;​
}rhb; //Receive buffer register (holding register & fifo register)

...
}

Looks like a good idea, and I think the kernel source does it in a similar, but not quite so elegant way.

You may be running into structure alignment and packing issues. I had some major problems with this until I discovered a few things:

By default, a structure is padded at the end to make the structure size a multiple of the machine's preferred alignment size (in this case, 1 word, or 4 bytes). I also found that individual items within a structure can have padding inserted so that each element is word-aligned. Needless to say, this was great fun with a structure which defined a 24-bit RGB triplet...

If you put " __attribute__ ((packed))" at the end of your structure definition, it will eliminate the padding that occurs between structure elements.

If you use "#pragma pack(push,n)" (where 'n' is your preferred alignment in bytes) before your structure definitions, and "#pragma pack(pop)" afterwards, then the structure alignment and padding at the very end will be adjusted to 'n' bytes, which by default is 4.

So, in your example above, I think your 2-byte 'rhb' structure is being turned into an 8-byte structure, because there is a 3-byte padding between 'value' and 'reserved', and also a 3-byte padding at the end.

To fix this, I would try the following:

#pragma pack(push,1)
struct UART {
struct {
char value :8;
u8 reserved :8;​
} __attribute__ ((packed)) rhb; //Receive buffer register (holding register & fifo register)​
] __attribute__ ((packed));
#pragma pack(pop)


The padding at the very end is probably not much of an issue in your case, but it does become important if you have a multiple-structure array addressed by a pointer, where the actual sizes of the structures are not multiples of 4-bytes.

Note that structures within structures will also need to have the packed attribute defined if it's needed, as they don't seem to inherit their parent's attribute.

NB. I'm not sure how this affects bitfields, as I never use them, but I think it might be worth examining. I guess the best way to check would be if you declare a pointer to your structure, and see what happens to the pointer address when you do an increment (i.e. ptr++), as that will show you exactly how the structure is aligned and what size it is. I usually use "objdump -x -d -S" to generate a listing of the binary, so that I can have a look at the assembler source and see how the pointer arithmetic is working out.
 
Last edited by a moderator:
Back