basic command implementation traditional way
[cortex-from-scratch] / lib / regfunc.c
index b783901..2e24689 100644 (file)
@@ -1,3 +1,14 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/7/20 - ROBIN KRENS     
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ * Helper functions to set registers 
+ *
+ * */
+
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <lib/string.h>
 #include <lib/stdio.h>
 
+#include <lib/tinyprintf.h>
+
 #include <sys/mmap.h>
+#include <sys/robsys.h>
 
-/* write value (uint8_t) to register */
-void regw_u8(volatile uint32_t * reg, uint8_t val, short shift, short flag) {
-
-       switch(flag) {
-               case OWRITE:
-                       *reg = (val << shift);
-                       break;
-               case SETBIT:
-                       *reg = *reg | (val << shift);
-                       break;
-               case CLRBIT:
-                       *reg = (val << shift);
-                       break;
-       }
+// register set bit at position
+void rsetbit(volatile uint32_t * reg, short pos) {
+       *reg = *reg | (0x1 << pos);
 }
 
-/* write value (uint32_t) to register */
-void regw_u32(volatile uint32_t * reg, uint32_t val, short shift, short flag) {
-
-       switch(flag) {
-               case OWRITE:
-                       *reg = (val << shift);
-                       break;
-               case SETBIT:
-                       *reg = *reg | (val << shift);
-                       break;
-               case CLRBIT:
-                       break;
-       }
+// register set bits from certain pos
+void rsetbitsfrom(volatile uint32_t * reg, short pos, int val) {
+       *reg = *reg | (val << pos);
+}
+
+// register clear bit at position
+void rclrbit(volatile uint32_t * reg, short pos) {
+       *reg = *reg & ~(0x1 << pos);
+}
+
+// check if a bit is set 
+int rchkbit(volatile uint32_t * reg, short pos) {
+       if ((*reg >> pos) & 0x1)
+               return 1;
+       return 0;
+}
+
+// register (over)write
+void rwrite(volatile uint32_t * reg, uint32_t val) {
+       *reg = val;
 }
 
-/* Print out the hexidecimal representation of an integer
-   After implementation of scanf or sth this will be obsolete.  */
 
+/* Deprecated use printf instead
 char hexbuf[8];
 char * regtohex(uint32_t addr) {
        char tmpbuf[6] = {'A', 'B', 'C', 'D', 'E', 'F'};
@@ -60,7 +69,9 @@ char * regtohex(uint32_t addr) {
                }
        }
        return &hexbuf[0];      
-}
+} */
+
+// TODO: implement simple scanf functions
 int singlehextoreg(char  hex) {
 
        int conv = 0;
@@ -86,3 +97,26 @@ uint32_t hextoreg(char * a) {
 
 }
 
+/* Busy-loop block implementation. Each iteration will take 3 CPU cycles.
+ * Of course, when interrupts are enabled, the exact delay time will be 
+ * uncertain. 
+ *
+ * Example: for a standard STM32x config board (8MHz) the maximum delay is
+ * 0xFFFF * (1/8,000,000) * 3 = 24.58ms 
+ * */
+static void __block(uint16_t count) {
+
+       asm volatile("b1: subs %0, %1, #1" "\n\t"
+               "bne b1" : "=r" (count) : "r" (count));
+}
+
+/* Delay us microsecond
+ * Note: delay includes setup time (about 4 clockcycles), so is quite
+ * inaccurate  */
+void _block(uint16_t us) {
+       
+       uint16_t count = (us/3) * CLKSPEED_MHZ; // x cycles 
+       __block(count);
+
+}
+