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
+/* (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;
}
+
--- /dev/null
+/* (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
+ }
+}
+
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);
}
#include <drivers/tm1637.h>
-#define TIMEOUT 1000
+#define TIMEOUT 5000
#define DOT true
#define NODOT false
cputs("Error: can't set location\n");
stop_condition();
-
regw_u32(I2C_CR1, 0x1, 15, SETBIT);
tm1637_reset();
--- /dev/null
+/* (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);
+
+}
#include <drivers/uart.h>
-#define RXNE ((*USART1_SR >> 5) & 0x1)
#define UARTBUF 256
#define ECHO 1
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');
}
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) {
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
+}
--- /dev/null
+#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
--- /dev/null
+extern void tsensor_output(uint16_t, uint16_t/* , uint16_t */);
+extern void tsensor_input(uint16_t);
+extern void run();
+
/* 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);
extern void cputchar(char);
extern void cputs(unsigned char *);
extern char * readline();
+extern void putc(void *, char);
--- /dev/null
+/*
+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
/* 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)
#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();
/* 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();
#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
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 */
}
/* 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 */
#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) {
*reg = *reg | (val << shift);
break;
case CLRBIT:
- *reg = (val << shift);
+ *reg = *reg & ~(val << shift);
break;
}
}
*reg = *reg | (val << shift);
break;
case CLRBIT:
+ *reg = *reg & ~(val << shift);
break;
}
}
}
+void putc(void *p, char c) {
+
+ cputchar(c);
+
+}
+
void cputs(unsigned char *str) {
int i;
--- /dev/null
+/*
+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
#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();
--- /dev/null
+/* (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
+
+}
#include <sys/robsys.h>
#include <sys/mmap.h>
-#include <lib/stdio.h>
+#include <lib/tinyprintf.h>
#include <lib/regfunc.h>
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;
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');
}
#include <sys/robsys.h>
#include <sys/mmap.h>
-#include <lib/regfunc.h> // TODO
+#include <lib/regfunc.h>
+#include <lib/stdio.h>
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);
+
+
}
#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
* */
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) {
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;
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# ");