Merge branch 'tm1637'
authorRobin Krens <robin@robinkrens.nl>
Tue, 13 Aug 2019 16:49:37 +0000 (00:49 +0800)
committerRobin Krens <robin@robinkrens.nl>
Tue, 13 Aug 2019 16:49:37 +0000 (00:49 +0800)
23 files changed:
Makefile
clock.c
drivers/at24c.c [new file with mode: 0644]
drivers/led.c
drivers/tm1637.c
drivers/tsensor.c [new file with mode: 0644]
drivers/uart.c
include/drivers/at24c.h [new file with mode: 0644]
include/drivers/tsensor.h [new file with mode: 0644]
include/lib/regfunc.h
include/lib/stdio.h
include/lib/tinyprintf.h [new file with mode: 0644]
include/sys/mmap.h
include/sys/robsys.h
ivt.c
lib/regfunc.c
lib/stdio.c
lib/tinyprintf.c [new file with mode: 0644]
main.c
rtc.c [new file with mode: 0644]
sysinfo.c
systick.c
term.c

index 3da9701..678ac90 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -20,15 +20,15 @@ INCLUDE+= -Iinclude
 BIN = bin
 
 ODIR = obj
-_OBJ = ivt.o systick.o sysinfo.o term.o main.o 
+_OBJ = ivt.o systick.o sysinfo.o term.o main.o clock.o rtc.o 
 OBJ = $(patsubst %, $(ODIR)/%,$(_OBJ))
 
 DDIR = obj/drivers
-_DRIVERS = uart.o tm1637.o led.o
+_DRIVERS = uart.o tm1637.o led.o tsensor.o at24c.o
 DRIVERS = $(patsubst %, $(DDIR)/%,$(_DRIVERS))
 
 LDIR = obj/lib
-_LIBS = string.o stdio.o regfunc.o pool.o  
+_LIBS = string.o stdio.o regfunc.o pool.o tinyprintf.o 
 LIBS = $(patsubst %, $(LDIR)/%,$(_LIBS))
 
 $(DDIR)/%.o: drivers/%.c
diff --git a/clock.c b/clock.c
index 7d5dc19..02a26ab 100644 (file)
--- a/clock.c
+++ b/clock.c
@@ -1,15 +1,55 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/7/30 - ROBIN KRENS     
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ * 1. Routines to setup the high speed external (HSE) clock. 
+ * Initially a (less accurate) high speed internal (HSI) 
+ * clock is used. PPL is enabled; HSE is input for PPL.
+ * PPL is multiplied to get the desired clock speed. 
+ *
+ * Some buses might not support the maximum speed and
+ * should be prescaled (i.e. low speed APB)
+ * 
+ * $USAGE
+ * Check external crystals on board and maximum speed
+ * for buses. In this example, a 8 Mhz external crystal
+ * is used. CPU speed is 36 Mhz. No prescaling is done.
+ * 
+ * */
+
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
-#include <stm32.h>
-#include <mmap.h>
 
+#include <sys/robsys.h>
+#include <sys/mmap.h>
+
+#include <lib/regfunc.h>
+
+static void setup_hse() {
+
+       rsetbit(RCC_CR, 16); /* HSE enable */
+       rsetbit(RCC_CFGR, 17); /* HSE divider for PLL entry */
+       
+       while(!rchkbit(RCC_CR, 17)); /* Wait for HSE to come up */
+       
+       rsetbitsfrom(RCC_CFGR, 18, 0x7); /* PLL Multiplayer (x9) */
+       rsetbit(RCC_CFGR, 16); /* HSE as PPL clock source */
+       rsetbit(RCC_CR, 24); /* PLL enable */
+       //rsetbitsfrom(RCC_CFGR, 8, 0x4); /* APB low speed prescraler */
+       rsetbitsfrom(RCC_CFGR, 0, 0x2); /* use PPL as system clock */
+
+       while(!rchkbit(RCC_CFGR, 3)); /* Wait for the clock switch to complete */
+}
 
 void clock_init() {
 
+#ifdef ENABLE_HSE
+setup_hse();
+#endif
 
-      *RCC_CR = *RCC_CR | 0x00010000;
-      for (int i = 0; i < 200; i++) {
-      }
-      *RCC_CFGR = *RCC_CFGR | 0x05000001;
 }
+
diff --git a/drivers/at24c.c b/drivers/at24c.c
new file mode 100644 (file)
index 0000000..7bf900a
--- /dev/null
@@ -0,0 +1,355 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/8/11 - ROBIN KRENS     
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ * Driver for AT24C256 EEPROM for STM32 based boards. Communication protocol is I2C
+ * Maximum write in limited to 64 bytes. Reading bytes is unlimited, but memory should
+ * be allocated accordingly. 
+ *
+ * I2C protocol : (W)rite or (R)ead 
+ * MCU is in master mode: either as transmitter or receiver
+ * | P | DEVICEADDR + R/W bit | ACK | ADDR_PART1 | ACK | ADDR_PART2 | (d+a*n) | (N)ACK | S
+ * Sending data: wait for ACK from EEPROM
+ * Receiving data: send (n)ACK to EEPROM after receiving data
+ *
+ * STM32F1 microcontrollers do not provide the ability to pull-up SDA and SCL lines. Their
+ * GPIOs must be configured as open-drain. So, you have to add two additional resistors to
+ * pull-up I2C lines. Something between 4K and 10K is a proven value. 
+ *
+ * */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <sys/mmap.h>
+#include <sys/robsys.h>
+
+#include <lib/regfunc.h>
+#include <lib/string.h>
+#include <lib/tinyprintf.h>
+
+#include <drivers/at24c.h>
+
+#define TIMEOUT 5000
+#define READ_CMD       0xA1
+#define WRITE_CMD      0xA0
+#define PAGE 64        /* Bytes that can be written continiously */
+#define BUFFER 64      /* Reading buffer */
+
+
+static char eeprombuf[BUFFER];
+
+void eeprom_at24c_init() {
+
+ /* Program the peripheral input clock generate correct timings. 
+  * Configure the clock control registers CCR
+  * Configure the rise time register TRIS
+  * Program the I2C_CR1 register to enable the peripheral 
+  * Enable GPIOB6 and B7*/
+
+ rsetbit(RCC_APB1ENR, 21); // enable GPIOB
+ rsetbit(RCC_APB2ENR, 3); // enable I2C
+ rwrite(GPIOB_CRL, 0xEE444444); // open-drain
+ rsetbitsfrom(I2C_CR2, 0, 0x2); // 2 MHz 
+ rwrite(I2C_TRISE, 0x3); // MAX = 1000ns, TPCLK1 = 500ns (+1)
+ rwrite(I2C_CCR, 0x000A); // standard mode
+ rsetbit(I2C_CR2, 10); // buffer interrupt
+ rsetbit(I2C_CR1, 0); // enable
+
+
+}
+
+/* Writes data to the EEPROM starting at address addr. Size can not
+ * be more than one PAGE (64 bytes)  */
+int eeprom_write(uint16_t addr, char * data, size_t size) {
+       
+       if(size > PAGE) {
+               printf("Error: Maximum writable page size: %d\n", PAGE);
+               return -1;
+       }
+
+       uint8_t hi_lo[] = { (uint8_t)(addr >> 8), (uint8_t)addr }; 
+       
+       start_condition();
+       rwrite(I2C_DR, WRITE_CMD);
+       if(!ack_recv()) 
+               return -1;
+       
+
+       rwrite(I2C_DR, hi_lo[0]); // higher part of address
+       if(!buf_empty()) 
+               return -1;
+       
+       rwrite(I2C_DR,hi_lo[1]); // lower part of address
+       if(!buf_empty()) 
+               return -1;
+       
+
+       for (int i = 0; i < size; i++) {
+               rwrite(I2C_DR, *data++);
+               if(!buf_empty()) 
+                       return -1;
+                       
+       }
+
+       stop_condition();
+       delay(); // wait for write action to finish     
+       return 0;
+}
+
+/* Erase (write all 0xFF) data on EEPROM
+ * Maximum hardware allowed sequential writes of 64 bytes */
+int eeprom_erase() {
+       
+       uint16_t cur_addr = 0x0000;
+
+       for (int i = 0; i < 512; i++) {
+               
+               printf("Writing at address: %#x (64 bytes) ", cur_addr);
+               uint8_t hi_lo[] = { (uint8_t)(cur_addr >> 8), (uint8_t)cur_addr }; 
+       
+               start_condition();
+               rwrite(I2C_DR, WRITE_CMD);
+               if(!ack_recv()) 
+                       return -1;
+       
+
+               rwrite(I2C_DR, hi_lo[0]); // higher part of address
+               if(!buf_empty()) 
+                       return -1;
+       
+               rwrite(I2C_DR,hi_lo[1]); // lower part of address
+               if(!buf_empty()) 
+                       return -1;
+       
+
+               for (int i = 0; i < PAGE; i++) {
+               rwrite(I2C_DR, 0xFF); // write all ones
+               if(!buf_empty()) 
+                       return -1;
+                       
+               }
+               stop_condition();
+               printf("[COMPLETE]\n");
+               cur_addr += 0x40; // 64 bytes; next PAGE
+               delay(); // wait for write to finish
+       }
+       
+       return 0;
+}
+
+/* Random access read of num bytes
+ * Initialize dummy write first to set correct address location
+ * The read function differentiate between num = 1 num = 2 and num > 3
+ * Data is saved to rvalues */
+int eeprom_read(uint16_t addr, int num, char * rvalues) {
+
+       uint8_t hi_lo[] = { (uint8_t)(addr >> 8), (uint8_t)addr }; 
+
+       /* Dummy write to set address */        
+       start_condition();
+       rwrite(I2C_DR, WRITE_CMD);
+       if(!ack_recv())
+               return -1;
+
+       rwrite(I2C_DR, hi_lo[0]); // higher part of address
+       if(!buf_empty())
+               return -1;
+
+       rwrite(I2C_DR,hi_lo[1]); // lower part of address
+       if(!buf_empty()) 
+               return -1;
+       
+       stop_condition();
+       
+       delay(); // wait form EEPROM
+
+       switch(num) {
+               case 1:
+                       start_condition(); // restart condition
+                       rwrite(I2C_DR, READ_CMD); // read? to address CMD
+                       if(!ack_recv())
+                               return -1;
+                       stop_condition();
+       
+                       if(!data_recv())
+                               return -1;
+
+                       rvalues[0] = (char) *I2C_DR;
+                       rvalues[1] = '\0';
+                       break;
+               case 2:
+
+                       rsetbit(I2C_CR1, 10); // set ACK
+                       rsetbit(I2C_CR1, 11); // set POS
+                       start_condition(); // restart condition
+                       rwrite(I2C_DR, READ_CMD); // read to address CMD
+                       if(!ack_recv()) 
+                               return -1;      
+                       rclrbit(I2C_CR1, 10); // clear ACK
+                       if(!late_recv()) 
+                               return -1;
+               
+                       stop_condition();
+                       
+                       rvalues[0] = (char) *I2C_DR;
+                       rvalues[1] = (char) *I2C_DR;
+                       rvalues[2] = '\0';
+                       break;
+
+               default:
+                       rsetbit(I2C_CR1, 10); // set ACK
+                       start_condition(); // restart condition
+                       rwrite(I2C_DR, READ_CMD); // read to address CMD
+                       if(!ack_recv()) 
+                               return -1;
+       
+                       for(int i = 0; i < num-3; i++) {
+                               if(!data_recv()) 
+                                       return -1;
+                               rvalues[i] = (char) *I2C_DR;
+                       }
+
+                       if(!late_recv()) 
+                               return -1;
+               
+                       rclrbit(I2C_CR1, 10);
+                       rvalues[num-3] = *I2C_DR;
+                       stop_condition();
+                       rvalues[num-2] = *I2C_DR;
+                       if(!data_recv()) 
+                               return -1;
+               
+                       rvalues[num-1] = *I2C_DR;
+                       rvalues[num] = '\0';
+       }
+
+       return 0;
+
+}
+
+/* Dump all data on EEPROM to std out */
+int eeprom_dump() {
+
+       uint16_t curr_addr = 0x0000;
+
+       for (int i = 0; i < 512; i++) {
+
+               if(eeprom_read(curr_addr, 64, eeprombuf) == -1) {
+                       printf("Error: Can't (continue) dump");
+                       return -1;
+               }
+               printf("%#x:\n", curr_addr);
+               for (int i = 0; i < strlen(eeprombuf); i++) {
+                       printf("%x ", eeprombuf[i]);
+                       if (((i % 16) == 0) && (i != 0))
+                               printf("\n");
+               }
+               printf("\n");
+               curr_addr += 0x40; // 64 bytes
+       }
+       return 0;
+
+}
+
+/* HELPER SUBROUTINES */
+
+static void start_condition() {
+       rsetbit(I2C_CR1, 8); //start bit
+}
+
+static void stop_condition() {
+       rsetbit(I2C_CR1, 9); //stop bit
+}
+
+/* Initial ACK received after address lookup 
+ * read registers clear ADDR bit */
+static int ack_recv() {
+       int cnt = 0;
+       while(!(*I2C_SR1 & 0x2)) {
+               cnt++;
+               if (cnt > TIMEOUT) {
+                       printf("Error: Can't reach device\n");
+                       return 0;
+               }
+       }
+       int a = *I2C_SR2;
+       return 1;
+}
+
+/* Check send buffer
+ * Note: BLOCKING function */
+static int buf_empty() {
+       int cnt = 0;
+       while(!(*I2C_SR1 & 0x80)) {
+               cnt++;
+               if (cnt > TIMEOUT) {
+                       printf("Error: Can't send data\n");
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+/* Check data receive buffer
+ * Note: BLOCKING function */
+static int data_recv() {
+       int cnt = 0;
+       while(!(*I2C_SR1 & 0x40)) {
+               cnt++;
+               if (cnt > TIMEOUT) {
+                       printf("Error: Timeout receiving data\n");
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+/* Similar as above, waits for two packages to be received
+ * one in DR and one in the shadow register */
+static int late_recv() {
+       int cnt = 0;
+       while(!(*I2C_SR1 & 0x4)) {
+               cnt++;
+               if (cnt > TIMEOUT) {
+                       printf("Error: Timeout receiving data\n");
+                       return 0;
+               }
+       }
+       return 1;
+
+}
+
+/* Write delay form EEPROM chip */
+static int delay() {
+       int a = 0;
+       for (int i = 0; i < 0xFFFF; i++)
+               a++;
+}
+
+
+int eeprom_test() {
+       char * gd = "Testing the EEPROM chip AT24C256 write and read function";
+       eeprom_write(0x1000, gd, strlen(gd));
+       
+       uint16_t curr_addr = 0x1000;
+
+       for (int i = 0; i < 4; i++) {
+
+               if(eeprom_read(curr_addr, 16, eeprombuf) == -1) {
+                       printf("Can't (continue) dump");
+                       return -1;
+               }
+               printf("%#x: ", curr_addr);
+               for (int i = 0; i < strlen(eeprombuf); i++) {
+                       printf("%x ", eeprombuf[i]);
+               }
+               printf("\n");
+               curr_addr += 0x10; // 16 bytes
+       }
+}
+
index 0cdda5a..ca74c14 100644 (file)
 
 void led_init() {
 
-       regw_u8(RCC_APB2ENR, 0x1, 4, SETBIT); // enable GPIOC
-       regw_u32(GPIOC_CRL, 0x44444442, 0, OWRITE); // set PC0 pin to output mode
-       *GPIOC_ODR = 0xFFFF; // only writable in word mode
+       rsetbit(RCC_APB2ENR, 5); // enable GPIOD
+       rsetbit(RCC_APB2ENR, 2); // enable GPIOA
+
+       //rwrite(GPIOD_CRL, 0x44444644); 
+       rsetbitsfrom(GPIOD_CRL, 8, 0x6);
+       rsetbitsfrom(GPIOA_CRH, 0, 0x6);
+//     rsetbit(GPIOD_ODR, 2);
+//     rclrbit(GPIOA_ODR, 8);
 
 }
 
 void led_on() {
-       *GPIOC_ODR = 0x0001;
+       rsetbit(GPIOD_ODR, 2);
+       rclrbit(GPIOA_ODR, 8);
+
 }
 
 void led_off() {
-       *GPIOC_ODR = 0x0000;
+       rclrbit(GPIOD_ODR, 2);
+       rsetbit(GPIOA_ODR, 8);
 }
 
index 485d81d..8c8ce5b 100644 (file)
@@ -28,7 +28,7 @@
 
 #include <drivers/tm1637.h>
 
-#define TIMEOUT 1000
+#define TIMEOUT 5000
 
 #define DOT true
 #define NODOT false
@@ -221,7 +221,6 @@ void set_segment(int offset, char value, bool dot) {
                cputs("Error: can't set location\n");
        stop_condition(); 
 
-
        regw_u32(I2C_CR1, 0x1, 15, SETBIT);
 
        tm1637_reset();
diff --git a/drivers/tsensor.c b/drivers/tsensor.c
new file mode 100644 (file)
index 0000000..3799095
--- /dev/null
@@ -0,0 +1,226 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/8/4 - ROBIN KRENS      
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ * Temperature sensor
+ *
+ * */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <sys/mmap.h>
+#include <sys/robsys.h>
+
+#include <lib/regfunc.h>
+#include <lib/string.h>
+#include <lib/tinyprintf.h>
+
+#include <drivers/tsensor.h>
+
+#define PRESCALER 36000 // 1 Mhz
+
+int *ccr1, *ccr2, *ccr1b, *ccr2b;
+bool s1, s2;
+
+ void * update_handler() {
+
+       s1 = false;
+       s2 = false;
+       ccr1 = 0xFFFFFFFF;
+               ccr2 = 0xFFFFFFFF;
+               ccr1b = 0xFFFFFFFF;
+               ccr2b = 0xFFFFFFFF;
+       
+       if(rchkbit(TIM4_SR1, 1)) {
+                       s1 = true;
+               //      printf("CCR1: %p\n", *TIM4_CCR1);
+               //      printf("CCR2: %p\n", *TIM4_CCR2);
+                       ccr1 = *TIM4_CCR1;
+                       ccr2 = *TIM4_CCR2;
+                       rclrbit(TIM4_SR1, 1); 
+       }
+       
+       if(rchkbit(TIM4_SR1, 2)) {
+                       s2 = true;
+                       ccr1b = *TIM4_CCR1;
+                       ccr2b = *TIM4_CCR2;
+                       rclrbit(TIM4_SR1, 2);
+       }
+       
+       if(rchkbit(TIM4_SR1, 6)) {
+       //              printf("TRIGGER\n");
+                       rclrbit(TIM4_SR1, 6);
+       }
+
+       rclrbit(TIM4_SR1, 0);
+//     rclrbit(TIM4_SR1, 9); // OF
+//     rclrbit(TIM4_SR1, 10); // OF
+
+       // TODO clear overflow tag
+       
+       printf("SR1/CCR1: %p\n", ccr1);
+       printf("SR1/CCR2: %p\n", ccr2);
+       printf("SR2/CCR1: %p\n", ccr1b);
+       printf("SR2/CCR2: %p\n", ccr2b);
+
+       if (s1)
+               printf("EDGE DOWN\n");
+       if (s2)
+               printf("EDGE UP\n");
+
+       s1 = false;
+       s2 = false;
+}
+
+static void reset() {
+       rwrite(GPIOB_CRL, 0x44444444);
+}
+
+void * tmp_update_handler() {
+
+       printf("SR: %p\n", *TIM4_SR1);
+       
+       rclrbit(TIM4_CR1, 0);   /* EMULATOR STOP */
+       rclrbit(TIM4_SR1, 0);
+       rclrbit(TIM4_SR1, 1);
+               reset();
+               tsensor_input(0xFFFF);
+
+//     if(rchkbit(TIM4_SR1, 1)) {
+//             printf("TEST\n");
+//     }
+
+}
+
+void * cnt_complete_handler() {
+       rclrbit(TIM4_CR1, 0);
+       rclrbit(TIM4_SR1, 0);
+       rclrbit(TIM4_DIER, 0);
+       rwrite(GPIOB_CRL, 0x44444444);
+       printf("CNT COMPLETE\n");
+       tsensor_input(0xFFFF);
+}
+
+
+void tsensor_simple(uint16_t preload) {
+       
+       rsetbit(RCC_APB1ENR, 2); // TIM4 enable
+
+       rsetbitsfrom(TIM4_CR1, 5, 0x00); // edge-aligned mode
+       rclrbit(TIM4_CR1, 4); // upcounter (clrbit! not needed to set)
+       rsetbit(TIM4_CR1, 2); // only overflow generates update
+
+       rwrite(TIM4_PSC, PRESCALER - 1);
+       rwrite(TIM4_ARR, preload);
+       rsetbit(TIM4_EGR, 0);
+       
+       ivt_set_gate(46, cnt_complete_handler, 0);
+       rsetbit(NVIC_ISER0, 30); // interupt 41 - 32
+
+       rsetbit(GPIOB_BSRR, 22); // 
+       rsetbit(TIM4_DIER, 0);
+       rsetbit(TIM4_CR1, 0);
+
+}
+
+void run() {
+
+       rsetbit(RCC_APB2ENR, 3); // GPIOB enable
+       rwrite(GPIOB_CRL, 0x47444444); // open drain general
+
+       rsetbit(GPIOB_BSRR, 22); // high
+       tsensor_simple(2000);
+//     tsensor_output(580, 520);
+//     reset();
+//     tsensor_simple(580);
+}
+
+void tsensor_output(uint16_t preload, uint16_t compare/*, uint16_t pulses */) {
+
+       /* GPIO AND CLOCK */
+       rsetbit(RCC_APB2ENR, 3); // GPIOB enable
+       rwrite(GPIOB_CRL, 0x4A444444); // PB6 for Channel 1 TIM4 alternate 
+       rsetbit(RCC_APB1ENR, 2); // TIM4 enable
+       
+       rsetbitsfrom(TIM4_CR1, 5, 0x00); // edge-aligned mode
+       rclrbit(TIM4_CR1, 4); // upcounter (clrbit! not needed to set)
+       rsetbit(TIM4_CR1, 2); // only overflow generates update
+
+       rwrite(TIM4_PSC, PRESCALER - 1); // 1 MHz
+       rwrite(TIM4_ARR, preload); // preload 
+       rwrite(TIM4_CCR1, compare); // compare
+       //rwrite(TIM4_RCR, pulses - 1); /* repeat ONLY IN ADVANCED TIMER */
+       
+       rsetbit(TIM4_EGR, 0); // update generation  
+       
+       rsetbit(TIM4_CR1, 3); // one pulse mode
+       rsetbitsfrom(TIM4_CCMR1, 4, 0x6); // mode
+       
+       //rsetbit(TIM4_CCMR1, 3); // preload enable
+       //rsetbit(TIM4_CR1, 7); // buffered
+
+       rsetbit(TIM4_CCER, 0); // enable output channeli 1
+       rsetbit(TIM4_CCER, 1); // active low
+       rsetbit(TIM4_CR1, 0); // start counter
+
+       /* INTERRUPTS */        
+       ivt_set_gate(46, tmp_update_handler, 0);
+
+       rsetbit(TIM4_DIER, 1);
+       rsetbit(NVIC_ISER0, 30); // interupt 41 - 32
+       
+}
+
+void tsensor_input(uint16_t preload) {
+
+       //uint16_t timestamp;   
+       /* GPIO AND CLOCK */
+       //rsetbit(RCC_APB2ENR, 3); // GPIOB enable
+       //rwrite(GPIOB_CRL, 0x44444444); // Input floating (default state)
+       //rsetbit(RCC_APB1ENR, 2); // TIM4 enable
+       
+       //rsetbitsfrom(TIM4_CR1, 5, 0x00); // edge-aligned mode
+       //rclrbit(TIM4_CR1, 4); // upcounter (clrbit! not needed to set)
+
+       rwrite(TIM4_PSC, PRESCALER - 1); // 1 MHz
+       rwrite(TIM4_ARR, preload); // preload 
+
+       
+       rsetbit(TIM4_EGR, 0); // update generation  
+
+       rsetbit(TIM4_CCMR1, 0); // input on TI1
+       rsetbit(TIM4_CCMR1, 9); // another input TI2
+       rsetbit(TIM4_CCER, 1); // other polarity for T1, inverted
+
+       /* TODO: reg funct */
+       rsetbit(TIM4_SMCR, 4); // OLD: 101, new Edge detector
+       rsetbit(TIM4_SMCR, 6); // 
+       
+
+       // rsetbit(TIM4_SMCR, 2); // RESET rising edge triggers counter and generates update
+       rsetbit(TIM4_SMCR, 2); // OLD: 110
+       rsetbit(TIM4_SMCR, 1);
+       rsetbit(TIM4_SMCR, 0);
+       //rsetbit(TIM4_SMCR, 1); // 110
+
+       //rsetbit(TIM4_CR1, 3); // one pulse mode // NOTE: RESET after finised preload
+       // will catch multiple signal... can set fram
+       
+       rsetbit(TIM4_CCER, 0); // enable capture channel 1 (changed pos)
+       rsetbit(TIM4_CCER, 4); // enable capture channel 2 
+       /* Caught on rising edge, no need to change*/
+       /* Clear capture event flag */
+//     rsetbit(TIM4_CR1, 0); // RESET with no trigger mode start
+
+       // enable capture channel 1 interrupt
+       rsetbit(TIM4_DIER, 1);
+       rsetbit(TIM4_DIER, 2);
+        ivt_set_gate(46, update_handler, 0);
+       rsetbit(NVIC_ISER0, 30);
+
+}
index 4693c6f..0090ef2 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <drivers/uart.h>
 
-#define RXNE ((*USART1_SR >> 5) & 0x1)
 #define UARTBUF 256
 #define ECHO 1
 
@@ -20,19 +19,16 @@ static struct {
                 uint32_t wpos;
 } linefeed;
 
+void set_baudrate();
 
 void * uart_handler() {
 
-       //uart_puts("echo: ");
-       while (RXNE) {
+       while (rchkbit(USART1_SR, 5)) {
                char echochar = *USART1_DR;
-//             uart_putc(echochar);
                 linefeed.buf[linefeed.wpos++] = echochar;
                  if (linefeed.wpos == UARTBUF)
                          linefeed.wpos = 0;
-               //regw_u32(USART1_DR, echochar, 0, O_WRITE);
        }
-       //uart_putc('\n');
                
 }
 
@@ -42,50 +38,42 @@ void uart_init() {
        linefeed.wpos = 0;
 
        //memset(&linefeed, 0, (sizeof(struct linefeed) ));
-       regw_u32(RCC_APB2ENR, 0x4005, 0, SETBIT);// enable clock to UART1, AFIO and GPIOA
+       //rsetbitsfrom(RCC_APB2ENR, 0, 0x4005);
+       rsetbit(RCC_APB2ENR, 0);
+       rsetbit(RCC_APB2ENR, 2);
+       rsetbit(RCC_APB2ENR, 14);
        
        /* (after enable GPIOA), on PA9&PA10 and set mode
         *  to alternative output */
-       regw_u32(GPIOA_CRH, 0x444444D4, 0, OWRITE);
-       regw_u8(AFIO_EVCR, 0x89, 0, OWRITE);// set event control register, output on PA, Pin 9 TODO: check
+       rwrite(GPIOA_CRH, 0x444444D4);
+       // set event control register, output on PA, Pin 9 TODO: check
+       rsetbitsfrom(AFIO_EVCR, 0, 0x89);
 
        //disable temporarily to set values
-       regw_u8(USART1_CR1, 0x0, 13, SETBIT);
+       rclrbit(USART1_CR1, 13);
 
-       /* baud rate 115200,  8MHz / (16 * USARTDIV)
-        * USARTDIV = 4.34
-        * FRACTION: 16 x 0.34 = 0d5.44 0d5 -> 0x5
-        * MANTISSA: 0d4.34 0d4 -> 0x4 
-        * USART_BRR = 0x45*/
+       set_baudrate();
 
-       regw_u32(USART1_BRR, 0x00000045, 0, OWRITE);
-       regw_u32(USART1_CR2, 0x0000, 0, OWRITE); //set stop bit, default is 1 stop bit 0x00
+       //set stop bit, default is 1 stop bit 0x00
+       rwrite(USART1_CR2, 0x0000);
        
        /* parity = 8 bit, UART1 enabled,
         * TX and RX enabled, interrupts enabled */
-       //regw_u32(USART1_CR1, 0x000030AC, 0, O_WRITE);
-       regw_u32(USART1_CR1, 0x0000302C, 0, OWRITE);
+       rwrite(USART1_CR1, 0x0000302C);
 
        ivt_set_gate(53, uart_handler, 0);
        
-       *NVIC_ISER1 = (1 << 5); // Enable UART interrupt at NVIC
-}
-
-static void wait() {
-       for (int i = 0; i < 100; i++);
+       rsetbit(NVIC_ISER1, 5);
 }
 
 void uart_putc(unsigned char ch) {
        
        if (ch == '\n') {
-               while (*USART1_SR & 0x0C) { } // transmit data register empty and complete
+               while(!rchkbit(USART1_SR, 6));
                regw_u8(USART1_DR, 0x0D, 0, OWRITE); // return line
        }
-
-       while (*USART1_SR & 0x0C) {} 
+               while(!rchkbit(USART1_SR, 6));
                regw_u8(USART1_DR, ch, 0, OWRITE);
-
-       wait();
 }
 
 char uart_getc(void) {
@@ -100,12 +88,24 @@ char uart_getc(void) {
          return 0;
  }
 
-
-// move to library 
-/* extern void uart_puts(unsigned char *str) {
-    int i;
-    for (i = 0; i < strlen(str); i++)     {
-        uart_putc(str[i]);
-    }
-} */
-
+/* Calculate baud rate. Example how this is done
+ * to set this register on a stm32
+ * Desired baudrate: 115200,  CLK: 8 MHz
+ * Desired Baudrate = CLK / (16 * USARTDIV)
+ * USARTDIV = 4.34
+ * FRACTION: 16 x 0.34 = 0d5.44 0d5 -> 0x5
+ * MANTISSA: 0d4.34 0d4 -> 0x4 
+ * USART_BRR = 0x45*/
+       
+void set_baudrate() {
+
+//     rwrite(USART1_BRR, 0x000001A1); 48 MHZ
+//     rwrite(USART1_BRR, 0x0000022B); 64 MHz
+//     rwrite(USART1_BRR, 0x00000138); 36 MHz
+//     rwrite(USART1_BRR, 0x00000271); 72 MHz
+#ifdef ENABLE_HSE
+       rwrite(USART1_BRR, 0x00000138);
+#else
+       rwrite(USART1_BRR, 0x00000045);
+#endif
+}
diff --git a/include/drivers/at24c.h b/include/drivers/at24c.h
new file mode 100644 (file)
index 0000000..c5e6026
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __AT24C_H
+#define __AT24C_H
+
+/* HELPER SUBROUTINES DECLARATIONS */
+static void start_condition();
+static void stop_condition();
+static int ack_recv();
+static int buf_empty();
+static int data_recv();
+static int late_recv();
+static int delay();
+
+extern void eeprom_at24c_init();
+extern int eeprom_write(uint16_t addr, char * data, size_t size);
+extern int eeprom_erase();
+extern int eeprom_read(uint16_t addr, int num, char * rvalues);
+extern int eeprom_dump();
+
+extern int eeprom_test();
+
+#endif
diff --git a/include/drivers/tsensor.h b/include/drivers/tsensor.h
new file mode 100644 (file)
index 0000000..ced6f5d
--- /dev/null
@@ -0,0 +1,4 @@
+extern void tsensor_output(uint16_t, uint16_t/* , uint16_t */);
+extern void tsensor_input(uint16_t);
+extern void run();
+
index f194df0..b13c28f 100644 (file)
@@ -1,5 +1,10 @@
 /* regfunc.h */
 extern char * regtohex(uint32_t );
 extern uint32_t hextoreg(char *);
+extern void rsetbit(volatile uint32_t *, short);
+extern void rclrbit(volatile uint32_t *, short);
+extern void rsetbitsfrom(volatile uint32_t *, short, int);
+extern int rchkbit(volatile uint32_t *, short);
+extern void rwrite(volatile uint32_t *, uint32_t);
 extern void regw_u8(volatile uint32_t *, uint8_t, short, short);
 extern void regw_u32(volatile uint32_t *, uint32_t, short, short);
index cf3075b..93d1f99 100644 (file)
@@ -6,3 +6,4 @@ extern char getchar();
 extern void cputchar(char);
 extern void cputs(unsigned char *);
 extern char * readline();
+extern void putc(void *, char);
diff --git a/include/lib/tinyprintf.h b/include/lib/tinyprintf.h
new file mode 100644 (file)
index 0000000..8855710
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+File: tinyprintf.h
+
+Copyright (C) 2004  Kustaa Nyholm
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+#ifndef __TFP_PRINTF__
+#define __TFP_PRINTF__
+
+#include <stdarg.h>
+
+/* Global configuration */
+
+/* Set this to 0 if you do not want to provide tfp_printf */
+#ifndef TINYPRINTF_DEFINE_TFP_PRINTF
+# define TINYPRINTF_DEFINE_TFP_PRINTF 1
+#endif
+
+/* Set this to 0 if you do not want to provide
+   tfp_sprintf/snprintf/vsprintf/vsnprintf */
+#ifndef TINYPRINTF_DEFINE_TFP_SPRINTF
+# define TINYPRINTF_DEFINE_TFP_SPRINTF 1
+#endif
+
+/* Set this to 0 if you do not want tfp_printf and
+   tfp_{vsn,sn,vs,s}printf to be also available as
+   printf/{vsn,sn,vs,s}printf */
+#ifndef TINYPRINTF_OVERRIDE_LIBC
+# define TINYPRINTF_OVERRIDE_LIBC 1
+#endif
+
+/* Optional external types dependencies */
+
+#if TINYPRINTF_DEFINE_TFP_SPRINTF
+# include <sys/types.h>  /* size_t */
+#endif
+
+/* Declarations */
+
+#ifdef __GNUC__
+# define _TFP_SPECIFY_PRINTF_FMT(fmt_idx,arg1_idx) \
+    __attribute__((format (printf, fmt_idx, arg1_idx)))
+#else
+# define _TFP_SPECIFY_PRINTF_FMT(fmt_idx,arg1_idx)
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef void (*putcf) (void *, char);
+
+/*
+   'tfp_format' really is the central function for all tinyprintf. For
+   each output character after formatting, the 'putf' callback is
+   called with 2 args:
+     - an arbitrary void* 'putp' param defined by the user and
+       passed unmodified from 'tfp_format',
+     - the character.
+   The 'tfp_printf' and 'tfp_sprintf' functions simply define their own
+   callback and pass to it the right 'putp' it is expecting.
+*/
+void tfp_format(void *putp, putcf putf, const char *fmt, va_list va);
+
+#if TINYPRINTF_DEFINE_TFP_SPRINTF
+int tfp_vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
+int tfp_snprintf(char *str, size_t size, const char *fmt, ...) \
+     _TFP_SPECIFY_PRINTF_FMT(3, 4);
+int tfp_vsprintf(char *str, const char *fmt, va_list ap);
+int tfp_sprintf(char *str, const char *fmt, ...) \
+    _TFP_SPECIFY_PRINTF_FMT(2, 3);
+# if TINYPRINTF_OVERRIDE_LIBC
+#  define vsnprintf tfp_vsnprintf
+#  define snprintf tfp_snprintf
+#  define vsprintf tfp_vsprintf
+#  define sprintf tfp_sprintf
+# endif
+#endif
+
+#if TINYPRINTF_DEFINE_TFP_PRINTF
+void init_printf(void *putp, putcf putf);
+void tfp_printf(char *fmt, ...) _TFP_SPECIFY_PRINTF_FMT(1, 2);
+# if TINYPRINTF_OVERRIDE_LIBC
+#  define printf tfp_printf
+# endif
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
index a5d2228..9aae914 100644 (file)
 
 /* SYSTEM INFO AND DEBUG */
 #define MCU_ID MEM_ADDR(0xE000ED00) 
-#define FLASH_MEM MEM_ADDR(0x1FFFF000) 
+#define FLASH_MEM MEM_ADDR(0x1FFFF000)
+
+/* POWER CONTROL REGISTERS */
+#define PWR_CR MEM_ADDR(0x40007000)
 
 /* SYSTEM CONTROL BLOCK REGISTER */
 #define SCB_VTOR MEM_ADDR(0xE000ED08) // VECTOR TABLE
 /* SYSTICK REGISTER */
 #define STK_CTRL MEM_ADDR(0xE000E010)
 #define STK_RELOAD MEM_ADDR(0xE000E014)
+#define STK_CALIB MEM_ADDR(0xE000E01C)
 
-/* CLOCK REGISTER */
+/* RESET AND CLOCK REGISTER */
 #define RCC_CR MEM_ADDR(0x40021000)
 #define RCC_CFGR MEM_ADDR(0x40021004)
+#define RCC_BDCR MEM_ADDR(0x40021020)
 
 /* SYSTEM CONTROL REGISTER */
 #define SYSCTRL_RCC MEM_ADDR(0x40021000)
 #define GPIOPA_AFSEL MEM_ADDR(0x40004420)
 
 #define GPIOA_CRH MEM_ADDR(0x40010804) // for USART1
+#define GPIOA_ODR MEM_ADDR(0x4001080C)
 #define GPIOB_CRL MEM_ADDR(0x40010C00) // low register (!) for I2C1
-#define GPIOC_CRL MEM_ADDR(0x40011000) // for led
-#define GPIOC_ODR MEM_ADDR(0x4001100C) //
+#define GPIOB_BSRR MEM_ADDR(0x40010C10)
+#define GPIOC_CRL MEM_ADDR(0x40011000) // led
+#define GPIOC_CRH MEM_ADDR(0x40011004) 
+#define GPIOC_ODR MEM_ADDR(0x4001100C)
+
+#define GPIOD_CRL MEM_ADDR(0x40011400)
+#define GPIOD_ODR MEM_ADDR(0x4001140C)
 
 #define AFIO_EVCR MEM_ADDR(0x40010000)
 
 #define USART1_CR1 MEM_ADDR(0x4001380C)
 #define USART1_CR2 MEM_ADDR(0x40013810)
 #define USART1_CR3 MEM_ADDR(0x40013814)
+
+/* REAL TIME CLOCK REGISTERS */
+#define RTC_CRH MEM_ADDR(0x40002800) // interrupts
+#define RTC_CRL MEM_ADDR(0x40002804)
+#define RTC_PRLL MEM_ADDR(0x4000280C)
+#define RTC_CNTH MEM_ADDR(0x40002818)
+#define RTC_CNTL MEM_ADDR(0x4000281C)
+/* BACKUP (CALIBR) REGISTERS */
+#define BKP_RTCCR MEM_ADDR(0x40006C2C) // RTC Calibration 
+
+#define TIM4_CR1 MEM_ADDR(0x40000800)
+#define TIM4_RCR MEM_ADDR(0x40000830)
+#define TIM4_ARR MEM_ADDR(0x4000082C)
+#define TIM4_EGR MEM_ADDR(0x40000814)
+#define TIM4_SR1 MEM_ADDR(0x40000810)
+#define TIM4_CCR1 MEM_ADDR(0x40000834)
+#define TIM4_CCR2 MEM_ADDR(0x40000838)
+#define TIM4_PSC MEM_ADDR(0x40000828)
+#define TIM4_SMCR MEM_ADDR(0x40000808)
+#define TIM4_CCER MEM_ADDR(0x40000820)
+//#define TIM1_BDTR MEM_ADDR(0x40000844)
+#define TIM4_CCMR1 MEM_ADDR(0x40000818)
+#define TIM4_DIER MEM_ADDR(0x4000080C)
index e02eded..9a19a47 100644 (file)
@@ -1,8 +1,23 @@
 #ifndef __SYSTEM_H
 #define __SYSTEM_H
 
-/* CLOCK.C */
+
+/* CLOCK.C 
+ * Board specific clock settings. These boards often come with two 
+ * external oscillators: one high speed (8MHz) and one low speed (~30kHz).
+ * These values are used throughout the code to calculator desired baud
+ * rates etc.
+ */
+//#define ENABLE_HSE   
+//efine CRYSTAL_MHZ    8
+//efine CLKSPEED_MHZ   72
 extern void clock_init();
+// extern int clock_test();
+// extern void clock_reset();
+
+/* RTC.C */
+#define ENABLE_RTC     
+extern void rtc_init();
 
 /* IVT.C */
 extern void ivt_init();
@@ -14,12 +29,6 @@ extern void systick_init();
 /* SYSINFO.C */
 extern void sysinfo();
 
-/* MM.C DELETE TODO */
-//extern void mm_init();
-//extern void * malloc(size_t);
-//extern void free(void *);
-//extern void test_memory(uint32_t *);
-
 /* POOL.c */
 extern void pool_init(size_t, unsigned int, uint32_t *);
 extern void * alloc();
diff --git a/ivt.c b/ivt.c
index 9f8e643..02c45ec 100644 (file)
--- a/ivt.c
+++ b/ivt.c
@@ -30,6 +30,7 @@
 #include <lib/stdio.h>
 #include <lib/string.h>
 #include <lib/regfunc.h>
+#include <lib/tinyprintf.h>
 
 /* 
  * These values are pushed on the stack just before
@@ -92,13 +93,15 @@ char * messages[] = {
 
 if (intnr < 20) // TODO: strlen
        return messages[intnr];
-       return NULL;
+
+return "UNKNOWN";
 }
 
 void ivt_set_gate(unsigned char num, void * isr(), short pri) {
 
        ivt[num] = (uint32_t) isr;
-       *NVIC_ISER0 = (1 << ((uint32_t)(num) & 0x1F));
+//     if (num <= 32)
+//             *NVIC_ISER0 = (1 << ((uint32_t)(num) & 0x1F));
        /* TODO: Priorities */
 }
 
@@ -106,16 +109,23 @@ void ivt_set_gate(unsigned char num, void * isr(), short pri) {
 /* Dummy interrupt: comment out the comment to use a naked
  * function */
 
-// __attribute__ ((interrupt)) 
-void * dummy_isr(/* struct interrupt_frame * frame */) {
+__attribute__ ((interrupt)) 
+void * dummy_isr( struct interrupt_frame * frame ) {
 
        uint8_t nr = *SCB_VTOR_ST & 0xFF;
+       //printf("PC:%p\n",frame->lr);
+       printf("EXCEPTION: %s\n", exception_message(nr));
+       printf("STACK TRACE:\n");
+       printf("R0:%p\n",frame->r0);
+       printf("R1:%p\n",frame->r1);
+       printf("R2:%p\n",frame->r2);
+       printf("R3:%p\n",frame->r3);
+       printf("R12:%p\n",frame->r12);
+       printf("LR:%p\n",frame->lr);
+       printf("PC:%p\n",frame->pc);
+       printf("PSR:%p\n",frame->psr);
        
-       cputs("EXCEPTION: ");
-       cputs(exception_message(nr));
-       cputs("\nSYSTEM HALTED\n");
-       
-       for(;;);
+       //for(;;);
 }
 
 /* Initialize interrupt vector  */
index b783901..9ea7d7b 100644 (file)
@@ -8,6 +8,34 @@
 
 #include <sys/mmap.h>
 
+
+// register set bit at position
+void rsetbit(volatile uint32_t * reg, short pos) {
+       *reg = *reg | (0x1 << pos);
+}
+
+// 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);
+}
+
+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;
+}
+
+
 /* write value (uint8_t) to register */
 void regw_u8(volatile uint32_t * reg, uint8_t val, short shift, short flag) {
 
@@ -19,7 +47,7 @@ void regw_u8(volatile uint32_t * reg, uint8_t val, short shift, short flag) {
                        *reg = *reg | (val << shift);
                        break;
                case CLRBIT:
-                       *reg = (val << shift);
+                       *reg = *reg & ~(val << shift);
                        break;
        }
 }
@@ -35,6 +63,7 @@ void regw_u32(volatile uint32_t * reg, uint32_t val, short shift, short flag) {
                        *reg = *reg | (val << shift);
                        break;
                case CLRBIT:
+                       *reg = *reg & ~(val << shift);
                        break;
        }
 }
index ac26165..9ef20ee 100644 (file)
@@ -31,6 +31,12 @@ void cputchar(char c) {
 
 }
 
+void putc(void *p, char c) {
+
+       cputchar(c);
+
+}
+
 void cputs(unsigned char *str) {
      
      int i;
diff --git a/lib/tinyprintf.c b/lib/tinyprintf.c
new file mode 100644 (file)
index 0000000..d57128f
--- /dev/null
@@ -0,0 +1,521 @@
+/*
+File: tinyprintf.c
+
+Copyright (C) 2004  Kustaa Nyholm
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+#include <lib/tinyprintf.h>
+
+
+/*
+ * Configuration
+ */
+
+/* Enable long int support */
+#define PRINTF_LONG_SUPPORT
+
+/* Enable long long int support (implies long int support) */
+//#define PRINTF_LONG_LONG_SUPPORT
+
+/* Enable %z (size_t) support */
+#define PRINTF_SIZE_T_SUPPORT
+
+/*
+ * Configuration adjustments
+ */
+#ifdef PRINTF_SIZE_T_SUPPORT
+#include <sys/types.h>
+#endif
+
+#ifdef PRINTF_LONG_LONG_SUPPORT
+# define PRINTF_LONG_SUPPORT
+#endif
+
+/* __SIZEOF_<type>__ defined at least by gcc */
+#ifdef __SIZEOF_POINTER__
+# define SIZEOF_POINTER __SIZEOF_POINTER__
+#endif
+#ifdef __SIZEOF_LONG_LONG__
+# define SIZEOF_LONG_LONG __SIZEOF_LONG_LONG__
+#endif
+#ifdef __SIZEOF_LONG__
+# define SIZEOF_LONG __SIZEOF_LONG__
+#endif
+#ifdef __SIZEOF_INT__
+# define SIZEOF_INT __SIZEOF_INT__
+#endif
+
+#ifdef __GNUC__
+# define _TFP_GCC_NO_INLINE_  __attribute__ ((noinline))
+#else
+# define _TFP_GCC_NO_INLINE_
+#endif
+
+/*
+ * Implementation
+ */
+struct param {
+    char lz:1;          /**<  Leading zeros */
+    char alt:1;         /**<  alternate form */
+    char uc:1;          /**<  Upper case (for base16 only) */
+    char align_left:1;  /**<  0 == align right (default), 1 == align left */
+    unsigned int width; /**<  field width */
+    char sign;          /**<  The sign to display (if any) */
+    unsigned int base;  /**<  number base (e.g.: 8, 10, 16) */
+    char *bf;           /**<  Buffer to output */
+};
+
+
+#ifdef PRINTF_LONG_LONG_SUPPORT
+static void _TFP_GCC_NO_INLINE_ ulli2a(
+    unsigned long long int num, struct param *p)
+{
+    int n = 0;
+    unsigned long long int d = 1;
+    char *bf = p->bf;
+    while (num / d >= p->base)
+        d *= p->base;
+    while (d != 0) {
+        int dgt = num / d;
+        num %= d;
+        d /= p->base;
+        if (n || dgt > 0 || d == 0) {
+            *bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
+            ++n;
+        }
+    }
+    *bf = 0;
+}
+
+static void lli2a(long long int num, struct param *p)
+{
+    if (num < 0) {
+        num = -num;
+        p->sign = '-';
+    }
+    ulli2a(num, p);
+}
+#endif
+
+#ifdef PRINTF_LONG_SUPPORT
+static void uli2a(unsigned long int num, struct param *p)
+{
+    int n = 0;
+    unsigned long int d = 1;
+    char *bf = p->bf;
+    while (num / d >= p->base)
+        d *= p->base;
+    while (d != 0) {
+        int dgt = num / d;
+        num %= d;
+        d /= p->base;
+        if (n || dgt > 0 || d == 0) {
+            *bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
+            ++n;
+        }
+    }
+    *bf = 0;
+}
+
+static void li2a(long num, struct param *p)
+{
+    if (num < 0) {
+        num = -num;
+        p->sign = '-';
+    }
+    uli2a(num, p);
+}
+#endif
+
+static void ui2a(unsigned int num, struct param *p)
+{
+    int n = 0;
+    unsigned int d = 1;
+    char *bf = p->bf;
+    while (num / d >= p->base)
+        d *= p->base;
+    while (d != 0) {
+        int dgt = num / d;
+        num %= d;
+        d /= p->base;
+        if (n || dgt > 0 || d == 0) {
+            *bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
+            ++n;
+        }
+    }
+    *bf = 0;
+}
+
+static void i2a(int num, struct param *p)
+{
+    if (num < 0) {
+        num = -num;
+        p->sign = '-';
+    }
+    ui2a(num, p);
+}
+
+static int a2d(char ch)
+{
+    if (ch >= '0' && ch <= '9')
+        return ch - '0';
+    else if (ch >= 'a' && ch <= 'f')
+        return ch - 'a' + 10;
+    else if (ch >= 'A' && ch <= 'F')
+        return ch - 'A' + 10;
+    else
+        return -1;
+}
+
+static char a2u(char ch, const char **src, int base, unsigned int *nump)
+{
+    const char *p = *src;
+    unsigned int num = 0;
+    int digit;
+    while ((digit = a2d(ch)) >= 0) {
+        if (digit > base)
+            break;
+        num = num * base + digit;
+        ch = *p++;
+    }
+    *src = p;
+    *nump = num;
+    return ch;
+}
+
+static void putchw(void *putp, putcf putf, struct param *p)
+{
+    char ch;
+    int n = p->width;
+    char *bf = p->bf;
+
+    /* Number of filling characters */
+    while (*bf++ && n > 0)
+        n--;
+    if (p->sign)
+        n--;
+    if (p->alt && p->base == 16)
+        n -= 2;
+    else if (p->alt && p->base == 8)
+        n--;
+
+    /* Fill with space to align to the right, before alternate or sign */
+    if (!p->lz && !p->align_left) {
+        while (n-- > 0)
+            putf(putp, ' ');
+    }
+
+    /* print sign */
+    if (p->sign)
+        putf(putp, p->sign);
+
+    /* Alternate */
+    if (p->alt && p->base == 16) {
+        putf(putp, '0');
+        putf(putp, (p->uc ? 'X' : 'x'));
+    } else if (p->alt && p->base == 8) {
+        putf(putp, '0');
+    }
+
+    /* Fill with zeros, after alternate or sign */
+    if (p->lz) {
+        while (n-- > 0)
+            putf(putp, '0');
+    }
+
+    /* Put actual buffer */
+    bf = p->bf;
+    while ((ch = *bf++))
+        putf(putp, ch);
+
+    /* Fill with space to align to the left, after string */
+    if (!p->lz && p->align_left) {
+        while (n-- > 0)
+            putf(putp, ' ');
+    }
+}
+
+void tfp_format(void *putp, putcf putf, const char *fmt, va_list va)
+{
+    struct param p;
+#ifdef PRINTF_LONG_SUPPORT
+    char bf[23];  /* long = 64b on some architectures */
+#else
+    char bf[12];  /* int = 32b on some architectures */
+#endif
+    char ch;
+    p.bf = bf;
+
+    while ((ch = *(fmt++))) {
+        if (ch != '%') {
+            putf(putp, ch);
+        } else {
+#ifdef PRINTF_LONG_SUPPORT
+            char lng = 0;  /* 1 for long, 2 for long long */
+#endif
+            /* Init parameter struct */
+            p.lz = 0;
+            p.alt = 0;
+            p.width = 0;
+            p.align_left = 0;
+            p.sign = 0;
+
+            /* Flags */
+            while ((ch = *(fmt++))) {
+                switch (ch) {
+                case '-':
+                    p.align_left = 1;
+                    continue;
+                case '0':
+                    p.lz = 1;
+                    continue;
+                case '#':
+                    p.alt = 1;
+                    continue;
+                default:
+                    break;
+                }
+                break;
+            }
+
+            /* Width */
+            if (ch >= '0' && ch <= '9') {
+                ch = a2u(ch, &fmt, 10, &(p.width));
+            }
+
+            /* We accept 'x.y' format but don't support it completely:
+             * we ignore the 'y' digit => this ignores 0-fill
+             * size and makes it == width (ie. 'x') */
+            if (ch == '.') {
+              p.lz = 1;  /* zero-padding */
+              /* ignore actual 0-fill size: */
+              do {
+                ch = *(fmt++);
+              } while ((ch >= '0') && (ch <= '9'));
+            }
+
+#ifdef PRINTF_SIZE_T_SUPPORT
+# ifdef PRINTF_LONG_SUPPORT
+            if (ch == 'z') {
+                ch = *(fmt++);
+                if (sizeof(size_t) == sizeof(unsigned long int))
+                    lng = 1;
+#  ifdef PRINTF_LONG_LONG_SUPPORT
+                else if (sizeof(size_t) == sizeof(unsigned long long int))
+                    lng = 2;
+#  endif
+            } else
+# endif
+#endif
+
+#ifdef PRINTF_LONG_SUPPORT
+            if (ch == 'l') {
+                ch = *(fmt++);
+                lng = 1;
+#ifdef PRINTF_LONG_LONG_SUPPORT
+                if (ch == 'l') {
+                  ch = *(fmt++);
+                  lng = 2;
+                }
+#endif
+            }
+#endif
+            switch (ch) {
+            case 0:
+                goto abort;
+            case 'u':
+                p.base = 10;
+#ifdef PRINTF_LONG_SUPPORT
+#ifdef PRINTF_LONG_LONG_SUPPORT
+                if (2 == lng)
+                    ulli2a(va_arg(va, unsigned long long int), &p);
+                else
+#endif
+                  if (1 == lng)
+                    uli2a(va_arg(va, unsigned long int), &p);
+                else
+#endif
+                    ui2a(va_arg(va, unsigned int), &p);
+                putchw(putp, putf, &p);
+                break;
+            case 'd':
+            case 'i':
+                p.base = 10;
+#ifdef PRINTF_LONG_SUPPORT
+#ifdef PRINTF_LONG_LONG_SUPPORT
+                if (2 == lng)
+                    lli2a(va_arg(va, long long int), &p);
+                else
+#endif
+                  if (1 == lng)
+                    li2a(va_arg(va, long int), &p);
+                else
+#endif
+                    i2a(va_arg(va, int), &p);
+                putchw(putp, putf, &p);
+                break;
+#ifdef SIZEOF_POINTER
+            case 'p':
+                p.alt = 1;
+# if defined(SIZEOF_INT) && SIZEOF_POINTER <= SIZEOF_INT
+                lng = 0;
+# elif defined(SIZEOF_LONG) && SIZEOF_POINTER <= SIZEOF_LONG
+                lng = 1;
+# elif defined(SIZEOF_LONG_LONG) && SIZEOF_POINTER <= SIZEOF_LONG_LONG
+                lng = 2;
+# endif
+#endif
+            case 'x':
+            case 'X':
+                p.base = 16;
+                p.uc = (ch == 'X')?1:0;
+#ifdef PRINTF_LONG_SUPPORT
+#ifdef PRINTF_LONG_LONG_SUPPORT
+                if (2 == lng)
+                    ulli2a(va_arg(va, unsigned long long int), &p);
+                else
+#endif
+                  if (1 == lng)
+                    uli2a(va_arg(va, unsigned long int), &p);
+                else
+#endif
+                    ui2a(va_arg(va, unsigned int), &p);
+                putchw(putp, putf, &p);
+                break;
+            case 'o':
+                p.base = 8;
+                ui2a(va_arg(va, unsigned int), &p);
+                putchw(putp, putf, &p);
+                break;
+            case 'c':
+                putf(putp, (char)(va_arg(va, int)));
+                break;
+            case 's':
+                p.bf = va_arg(va, char *);
+                putchw(putp, putf, &p);
+                p.bf = bf;
+                break;
+            case '%':
+                putf(putp, ch);
+            default:
+                break;
+            }
+        }
+    }
+ abort:;
+}
+
+#if TINYPRINTF_DEFINE_TFP_PRINTF
+static putcf stdout_putf;
+static void *stdout_putp;
+
+void init_printf(void *putp, putcf putf)
+{
+    stdout_putf = putf;
+    stdout_putp = putp;
+}
+
+void tfp_printf(char *fmt, ...)
+{
+    va_list va;
+    va_start(va, fmt);
+    tfp_format(stdout_putp, stdout_putf, fmt, va);
+    va_end(va);
+}
+#endif
+
+#if TINYPRINTF_DEFINE_TFP_SPRINTF
+struct _vsnprintf_putcf_data
+{
+  size_t dest_capacity;
+  char *dest;
+  size_t num_chars;
+};
+
+static void _vsnprintf_putcf(void *p, char c)
+{
+  struct _vsnprintf_putcf_data *data = (struct _vsnprintf_putcf_data*)p;
+  if (data->num_chars < data->dest_capacity)
+    data->dest[data->num_chars] = c;
+  data->num_chars ++;
+}
+
+int tfp_vsnprintf(char *str, size_t size, const char *format, va_list ap)
+{
+  struct _vsnprintf_putcf_data data;
+
+  if (size < 1)
+    return 0;
+
+  data.dest = str;
+  data.dest_capacity = size-1;
+  data.num_chars = 0;
+  tfp_format(&data, _vsnprintf_putcf, format, ap);
+
+  if (data.num_chars < data.dest_capacity)
+    data.dest[data.num_chars] = '\0';
+  else
+    data.dest[data.dest_capacity] = '\0';
+
+  return data.num_chars;
+}
+
+int tfp_snprintf(char *str, size_t size, const char *format, ...)
+{
+  va_list ap;
+  int retval;
+
+  va_start(ap, format);
+  retval = tfp_vsnprintf(str, size, format, ap);
+  va_end(ap);
+  return retval;
+}
+
+struct _vsprintf_putcf_data
+{
+  char *dest;
+  size_t num_chars;
+};
+
+static void _vsprintf_putcf(void *p, char c)
+{
+  struct _vsprintf_putcf_data *data = (struct _vsprintf_putcf_data*)p;
+  data->dest[data->num_chars++] = c;
+}
+
+int tfp_vsprintf(char *str, const char *format, va_list ap)
+{
+  struct _vsprintf_putcf_data data;
+  data.dest = str;
+  data.num_chars = 0;
+  tfp_format(&data, _vsprintf_putcf, format, ap);
+  data.dest[data.num_chars] = '\0';
+  return data.num_chars;
+}
+
+int tfp_sprintf(char *str, const char *format, ...)
+{
+  va_list ap;
+  int retval;
+
+  va_start(ap, format);
+  retval = tfp_vsprintf(str, format, ap);
+  va_end(ap);
+  return retval;
+}
+#endif
diff --git a/main.c b/main.c
index 342059e..8455b46 100644 (file)
--- a/main.c
+++ b/main.c
 
 #include <lib/regfunc.h>
 #include <lib/stdio.h>
+#include <lib/tinyprintf.h>
 
 #include <drivers/uart.h>
 #include <drivers/led.h>
 #include <drivers/tm1637.h>
+#include <drivers/at24c.h>
+#include <drivers/tsensor.h>
+
+//void sleep() {
+//
+//     __asm__ __volatile__("wfe");
+//
+//}
 
 void main()
 {
+       clock_init();
        ivt_init();
        uart_init();
 //     cputs("ROBSYS LOADING...\n");
-       systick_init();
-       led_init();
+       //systick_init();
+//     tsensor_output(0xFFFF, 0x7FFF);
+
+       init_printf(NULL, putc);
+       // SPEED_TEST
+/*     cputs("START TEST (8MHz) \n");
+       int a;
+       for (int i = 0; i < 20000000; i++) {
+               a + 2;  
+       }
+       a = 0;
+       cputs("END TEST\n");
+       
+       //! 
+       clock_init();
+
+       cputs("START TEST (??MHz) \n");
+       for (int i = 0; i < 20000000; i++) {
+               a + 2;  
+       }
+       cputs("END TEST\n"); */
        sysinfo();
 
+
+//     tsensor_input(5000);
+//     run();
+
+       led_init();
+//     eeprom_at24c_init();
+//     eeprom_test();
+//     rtc_init();
+
        tm1637_init();
        tm1637_start();
 
diff --git a/rtc.c b/rtc.c
new file mode 100644 (file)
index 0000000..4877d92
--- /dev/null
+++ b/rtc.c
@@ -0,0 +1,92 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/7/30 - ROBIN KRENS     
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ * 
+ * */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <sys/robsys.h>
+#include <sys/mmap.h>
+
+#include <lib/regfunc.h>
+#include <lib/stdio.h>
+
+#include <drivers/led.h>
+
+
+static void periodic_intr() {
+
+       while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
+       rsetbit(RTC_CRL, 4); // start configure
+       
+       rsetbit(RTC_CRH, 0); // enable periodic (second) interrupt
+       
+       while(!rchkbit(RTC_CRL, 5)); 
+
+       rwrite(RTC_PRLL, 0x7FFF); // 1 second
+       rclrbit(RTC_CRL, 4); // stop configure
+       while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
+       rsetbit(NVIC_ISER0, 3); // enable in register vector
+}
+
+static void calibrate_rtc() {
+
+
+//     rsetbit(BKP_RTCCR, 7); // enable CC0, 
+//     while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
+//     rsetbit(RTC_CRL, 4);
+
+       // Set up and check tamper pin
+       
+//     rclrbit(RTC_CRL, 4);
+//     while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
+}
+
+void * rtc_handler() {
+
+       //cputs("TICKING IN REAL TIME\n");
+       //uint32_t curr = *RTC_CNTL;
+       int even = *RTC_CNTL % 2;
+       (!even) ? led_off() : led_on();
+
+       rclrbit(RTC_CRL, 0);
+}
+
+static void setup_rtc() {
+
+// TODO: long time to get stable?
+       /* Enable PWREN and BKPEN */
+       rsetbit(RCC_APB1ENR, 28);
+       rsetbit(RCC_APB1ENR, 27);
+
+       /* Enable access to backup registers and RTC */
+       rsetbit(PWR_CR, 8);
+
+       rsetbit(RCC_BDCR, 0); /* LSE enable */
+       while(!rchkbit(RCC_BDCR, 1)); /* wait for LSE to come up */
+       
+       rsetbitsfrom(RCC_BDCR, 8, 0x1); /* use LSE as RTC source */
+       rsetbit(RCC_BDCR, 15); /* enable RTC */
+       
+       ivt_set_gate(19, rtc_handler, 0); /* setup interrupt handler */
+
+//     calibrate_rtc(); TODO: TAMPER PIN?
+       
+       periodic_intr();// setup periodic interrupt
+
+}
+
+void rtc_init() {
+
+#ifdef ENABLE_RTC
+       setup_rtc();
+#endif
+
+}
index 7f06334..bd5d1bb 100644 (file)
--- a/sysinfo.c
+++ b/sysinfo.c
@@ -13,7 +13,7 @@
 #include <sys/robsys.h>
 #include <sys/mmap.h>
 
-#include <lib/stdio.h>
+#include <lib/tinyprintf.h>
 #include <lib/regfunc.h>
 
 
@@ -22,28 +22,28 @@ uint32_t get_msp(void);
 void sysinfo() {
 
        uint32_t tmp = *MCU_ID;
-       cputs("# DEVICE ID: ");
+       printf("# DEVICE ID: ");
 
        if (tmp & 0x414) 
-               cputs("HIGH DENSITY\n");
+               printf("HIGH DENSITY\n");
        else {
-               cputs("UNKNOWN\n");
+               printf("UNKNOWN\n");
        }
 
        tmp = (tmp >> 16);
-       cputs("# REVISION: ");
+       printf("# REVISION: ");
        switch  (tmp) {
                case 0x1000:
-                     cputs("REVISION A\n");
+                     printf("REVISION A\n");
                      break;
                case 0x1001:
-                     cputs("REVISION Z\n");
+                     printf("REVISION Z\n");
                      break;
                case 0x1003:
-                     cputs("REVISION 1/2/3/X/Y\n");
+                     printf("REVISION 1/2/3/X/Y\n");
                      break;
                default:
-                     cputs("UNKNOWN\n");
+                     printf("UNKNOWN\n");
        }
 
        extern char _endofbss;
@@ -53,15 +53,15 @@ void sysinfo() {
        uint32_t data_bss = &_endofbss - SRAM_OFFSET;
        uint32_t mem_free = SRAM_SIZE - stack_usage - data_bss;
 
-       cputs("# TOTAL MEMORY: ");
-       cputs(regtohex(SRAM_SIZE));
-       cputchar('\n');
-       cputs("# FREE MEMORY: ");
-       cputs(regtohex(mem_free));
-       cputchar('\n');
-       cputs("# STACK USAGE: ");
-       cputs(regtohex(stack_usage));
-       cputchar('\n');
+       printf("# TOTAL MEMORY: %#x\n", SRAM_SIZE);
+//     cputs(regtohex(SRAM_SIZE));
+//     cputchar('\n');
+       printf("# FREE MEMORY: %#x\n", mem_free);
+//     cputs(regtohex(mem_free));
+//     cputchar('\n');
+       printf("# STACK USAGE: %#x\n", stack_usage);
+//     cputs(regtohex(stack_usage));
+//     cputchar('\n');
 
 }
 
index 1d632ec..05f515f 100644 (file)
--- a/systick.c
+++ b/systick.c
@@ -5,7 +5,8 @@
 #include <sys/robsys.h>
 #include <sys/mmap.h>
 
-#include <lib/regfunc.h> // TODO
+#include <lib/regfunc.h>
+#include <lib/stdio.h>
 
 struct interrupt_frame {
 
@@ -22,25 +23,31 @@ struct interrupt_frame {
 //__attribute__ ((interrupt))
 void * systick_handler(/* struct interrupt_frame * frame */) {
 
-//     uint32_t volatile status;
-       //uart_puts("TICKING\n");
+//     cputs("TICKING\n");
 //     for(;;);
 }
 
 
 void systick_init() {
 
-       /* Enable the counter and enable the interrupt
-        * associated with it */
-       *STK_CTRL = (volatile uint32_t) 0x00000003;
-
-       /* The counter reload register here holds 
-        * 0x1000 -- that's 4096 clock cycles -- if 
-        * it is down to zero it is restores the value */
-       *STK_RELOAD = (volatile uint32_t) 0x00400000; 
-
        /* Every time the counter counts down to zero
         * a systick exception is asserted. Systick has
         * exception number 15. in the vector table  */
        ivt_set_gate(15, systick_handler, 0); 
+
+       /* Get calibration and set this to 1 sec
+        * !Most boards have a 1 ms or 10 ms 
+        * calibration value */
+       int calib = (*STK_CALIB << 0) * 500;
+
+       /* The counter reload registers counts down to zero
+        * and then it is restores the value */
+       rwrite(STK_RELOAD, calib);
+       
+       /* Enable the counter and enable the interrupt
+        * associated with it */
+       rsetbit(STK_CTRL, 0);
+       rsetbit(STK_CTRL, 1);
+
+
 }
diff --git a/term.c b/term.c
index 51eb9cf..7ce25ce 100644 (file)
--- a/term.c
+++ b/term.c
@@ -8,6 +8,7 @@
 #include <lib/stdio.h>
 #include <lib/string.h>
 #include <lib/regfunc.h>
+#include <lib/tinyprintf.h>
 
 #include <drivers/led.h>
 
 #define BUFSIZE 200
 #define MAXARGS 5
 #define WHITESPACE "\t\r\n "
-#define BUILTINCMDS 3
+#define BUILTINCMDS 4
 
 int help(int, char**);
 
 /* 
  * Built in commands
  *     info -- shows basic info of system
- *     reset -- software reset
+ *     uptime -- uptime; read from the RTC register
+ *     reset -- software reset TODO
  *     show [ADDRESS-ADDRESS] -- shows SRAM range
  *     switchmode -- switch to unprivileged mode
  * */
@@ -37,11 +39,18 @@ struct cmd {
 
 struct cmd builtincmds[4];
 
-int help(int argc, char ** argsv) {
+int info(int argc, char ** argsv) {
        sysinfo();
        return 0;
 }
 
+int uptime(int arg, char ** argsv) {
+       //cputs("CURRENT UPTIME: ");
+       //cputs(regtohex(*RTC_CNTL));
+       //cputchar('\n');
+       printf("CURRENT UPTIME: %p\n", *RTC_CNTL);
+}
+
 int led(int argc, char ** argsv) {
 
 
@@ -116,8 +125,8 @@ int exec_cmd(char * buf) {
 
 void terminal() {
 
-               builtincmds[0].name = "help";
-       builtincmds[0].function = help;
+               builtincmds[0].name = "info";
+       builtincmds[0].function = info;
 
        builtincmds[1].name = "led";
        builtincmds[1].function = led;
@@ -125,8 +134,12 @@ void terminal() {
        builtincmds[2].name = "show";
        builtincmds[2].function = show;
 
+       builtincmds[3].name = "uptime";
+       builtincmds[3].function = uptime;
+
+
        char *buf;
-        cputs("WELCOME TO ROBSYS!\n");
+        //cputs("WELCOME TO ROBSYS!\n");
  
          while (1) {
                  buf = readline("root# ");