diff options
Diffstat (limited to 'playground_05-25-2011.c')
-rw-r--r-- | playground_05-25-2011.c | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/playground_05-25-2011.c b/playground_05-25-2011.c new file mode 100644 index 0000000..20249a7 --- /dev/null +++ b/playground_05-25-2011.c @@ -0,0 +1,141 @@ +/* + * playground_05-25-2011.c + * + * + * Playing around with unions and macros, and how both + * of these things look in the memory + * + */ + +#include <stdio.h> +#include <stdint.h> + +#define EXP(base, exp, ret) do { \ + int i; \ + int acc = 1; \ + for (i = 0; i < exp; i++) \ + acc *= base; \ + ret = acc; \ + } while(0) \ + +#define MUL(base, mult, ret) do { \ + int i; \ + int acc = 0; \ + for (i = 0; i < mult; i++) \ + acc += base; \ + ret = acc; \ + } while(0) \ + +/* trace a variable, requires ANSI compliant compiler */ +#define TRACE(var, fmt) \ + printf("TRACE: " #var " = " #fmt ", %s:%d\n", var, __FILE__, __LINE__) + +#pragma pack(1) +struct UART_tag +{ + union + { + struct + { + uint32_t baud_rate; /* bits [0:31] */ + + uint8_t tx_en : 1; + uint8_t rx_en : 1; + uint8_t parity : 1; /* bit [34], 35th */ + + uint32_t : 29; + + } B; + + uint64_t R; + } SET; + +}; +typedef struct UART_tag UART_t; + +void UART_info(UART_t *dev) +{ + printf("baud rate: %u\n" + "tx enabled: %s\n" + "rx enabled: %s\n" + "parity enabled: %s\n", dev->SET.B.baud_rate, + dev->SET.B.tx_en ? "yes" : "no", + dev->SET.B.rx_en ? "yes" : "no", + dev->SET.B.parity ? "yes" : "no"); +} + +void dumpHex(UART_t *p, unsigned int sz) +{ + int i; + for (i = 0; i < sz; i++) + { + if (i % 4 == 0) + printf("%s0x%08x: ", i == 0 ? "" : "\n", i); + + printf(" 0x%02x", ((unsigned char *) p)[i] ); + } + printf("\n\n"); +} + +int main(int argc, char **argv) +{ + /* assigning a struct within the union */ + puts("\t assigning a struct within the union"); + UART_t myUart; + myUart.SET.R = 0; + myUart.SET.B.baud_rate = 19200; + myUart.SET.B.tx_en = 1; + myUart.SET.B.rx_en = 1; + myUart.SET.B.parity = 0; + + UART_info(&myUart); + puts(""); + + puts("\t this is how UART_t looks in the memory"); + dumpHex(&myUart, sizeof(UART_t)); + + /* disable a flag within the struct */ + puts("\t disable a flag within the struct"); + myUart.SET.B.tx_en = 0; + UART_info(&myUart); + puts(""); + + /* modifying the whole structure at once */ + puts("\t modifying the whole structure at once"); + myUart.SET.R = 0; + UART_info(&myUart); + puts(""); + + /* enable the parity bit */ + myUart.SET.R |= (uint64_t) \ + ((uint64_t) 1 << (64 - 30)); /* this is inverted compared + * to how it would be done on + * a register */ + + puts("\t setting the parity bit to ON using logical OR operator"); + UART_info(&myUart); + puts(""); + + printf("size of UART_t is: %lu bytes\n", sizeof(UART_t)); + printf("size of UART_tag is: %lu bytes\n", sizeof(myUart.SET.B)); + + int x; + EXP(2, 20, x); + printf("a megabyte is %d bytes\n", x); + + int y; + MUL(x, 4, y); + printf("4 megabytes is %d bytes\n", y); + + /* endianess */ + int z = 1; + if (*((unsigned char *) &z) == 1) + puts("machine has a little-endian byte ordering"); + else + puts("machine has a big-endian byte ordering"); + + TRACE(y, %d); + + return 0; +} + |