summaryrefslogtreecommitdiff
path: root/content/projects/uC_bare.md
diff options
context:
space:
mode:
Diffstat (limited to 'content/projects/uC_bare.md')
-rw-r--r--content/projects/uC_bare.md191
1 files changed, 191 insertions, 0 deletions
diff --git a/content/projects/uC_bare.md b/content/projects/uC_bare.md
new file mode 100644
index 0000000..eeded17
--- /dev/null
+++ b/content/projects/uC_bare.md
@@ -0,0 +1,191 @@
++++
+title = "µC firmware: interacting with bare-systems"
+date = 2023-08-18
++++
+
+---
+## Address an hardware register
+### Raw
+```C
+int main(void)
+{
+ unsigned char addr = 0xff; // reg addr
+ volatile unsigned char *reg = (volatile unisgned char *)addr; // reg ptr
+ unsigned char val; // reg value
+ // change the integer type if needed
+
+read:
+ val = *(volatile unsigned char *)reg;
+write:
+ *(volatile unsigned char *)reg = val;
+
+ return 0;
+}
+```
+
+### Macro
+```C
+#define REG 0xff
+#define READ_H(reg) (*(volatile unsigned char *)(reg))
+#define WRITE_H(reg, val) (*(volatile unsigned char *)(reg)) = (val)
+```
+
+
+## Bit manipulation
+### Raw
+```C
+int main(void)
+{
+ int val; // signed or unsigned
+ unsigned char position; // max at bit-length of val
+ unsigned char bit; // 0 or 1
+ unsigned char x; // unknown value, 0 or 1
+
+setBit:
+ val |= (1 << position);
+unsetBit:
+ val &= ~(1 << position);
+toggleBit:
+ val ^= (1 << position);
+verifyBit:
+ bit = (val >> position) & 0x1;
+
+bit_to_x: // works with both x = 1 or 0
+ val = (val & ~(1 << position)) | (x << position);
+
+ return 0;
+}
+```
+
+### Macro
+```C
+#define SET_BIT(val, bitIndex) (val) |= (1 << (bitIndex))
+#define CLEAR_BIT(val, bitIndex) (val) &= ~(1 << (bitIndex))
+#define TOGGLE_BIT(val, bitIndex) (val) ^= (1 << (bitIndex))
+#define BIT_VALUE(val, bitIndex) (((val) >> (bitIndex)) & 1)
+#define BIT_TO_X(val, x, bitIndex) (val) = ((val) & ~(1 << (bitIndex)) | ((x) << (bitIndex))
+```
+
+
+## Declaration and use of hardware register
+Following the last two sections:
+```C
+#define REGD (*(volatile unsigned char *)(0xff))
+#define D0 0
+#define D1 1
+#define D2 2 // etc
+
+int main(void)
+{
+ REGD = 0x00; // whole register
+ REGD |= (1 << D1); // set bit 1 of REGD
+ REGD &= ~(1 << D0); // unset bit 2 of REGD
+ return 0;
+}
+```
+
+## Transpose a dataBus value on spread registers' bits
+```C
+void Xpos(unsigned char x, unsigned char xIndex, unsigned char *dest, unsigned char destIndex, unsigned char bitLength)
+{
+ unsigned char mask = 0x1;
+ unsigned char i = 1;
+ while (i++ < bitLength)
+ mask = (mask << 1) | 0x1;
+ *dest &= ~(mask << destIndex); // set the 0s
+ *dest |= (((x >> xIndex) & mask) << destIndex); // set the 1s
+}
+
+
+/*** Example ***/
+// Registers
+unsigned char E = 0xa5;
+unsigned char D = 0xa5;
+unsigned char C = 0xa5;
+
+void drawBar(unsigned char x) // outputs x value on spread bits of E, D and C
+{
+ Xpos(x, 7, &E, 6, 1); // x7 is on E6
+ Xpos(x, 6, &D, 7, 1); // x6 is on D7
+ Xpos(x, 5, &C, 6, 1); // x5 is on C6
+ Xpos(x, 4, &D, 4, 1); // x4 is on D4
+ Xpos(x, 3, &D, 0, 1); // x3 is on D0
+ Xpos(x, 2, &D, 1, 1); // x2 is on D1
+ Xpos(x, 0, &D, 2, 2); // x1-0 is on D3-2
+}
+
+int main(void)
+{
+ unsigned char x = 0xff;
+ drawBar(x);
+
+ return 0;
+}
+```
+
+## Some macros
+```C
+#define MIN(A, B) ((A) <= (B) ? (A) : (B))
+#define MAX(A, B) ((A) >= (B) ? (A) : (B))
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+```
+
+## Bit-fields
+**Careful:** the bit order is compiler-dependent, this implementation is *not* portable.
+```C
+#include <stdio.h>
+
+union byte_t {
+ unsigned char val;
+ struct {
+ unsigned char A : 2;
+ unsigned char B : 1;
+ unsigned char C : 3;
+ };
+ struct {
+ unsigned char A0 : 1;
+ unsigned char A1 : 1;
+ unsigned char : 1;
+ unsigned char C0 : 1;
+ unsigned char C1 : 1;
+ unsigned char C2 : 1;
+ };
+};
+
+int main(void)
+{
+ union byte_t reg = {0x2a}; // 0b101010
+
+ printf("%hhu\t0x%x\t0x%x\n", reg.C1, reg.A, reg.val);
+ // gives: 1, 0x2, 0x2a
+
+ return 0;
+}
+```
+
+## Tricky definitions
+
+### Static
+Static has three distinct uses in `C`:
+1. A variable declared static within the body of a function maintains its value
+between function invocations.
+2. A variable declared static within a module, (but outside the body of
+a function) is accessible by all functions within that module. It is not
+accessible by functions within any other module. That is, it is a localized
+global.
+3. Functions declared static within a module may only be called by other
+functions within that module. That is, the scope of the function is localized
+to the module within which it is declared.
+
+### Volatile
+Examples of volatile variables are:
+1. Hardware registers in peripherals (e.g., status registers).
+2. Non-stack variables referenced within an interrupt service routine.
+3. Variables shared by multiple tasks in a multi-threaded application.