summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2017-12-04 15:19:25 +0100
committerDaniel Friesel <derf@finalrewind.org>2017-12-04 15:19:25 +0100
commit7b5284023070b841293d0c5a6be0c6c345372cde (patch)
tree5f2c70451cf61ef6744813cac3a221cef210b213
Add basic system: LED GPIO on MSP430FR5969 Launchpad and faked GPIO on POSIX
-rw-r--r--.gitignore2
-rw-r--r--Makefile21
-rw-r--r--include/msp430fr5969lp/driver/gpio.h18
-rw-r--r--include/posix/driver/gpio.h19
-rw-r--r--src/arch/msp430fr5969lp/Makefile.inc37
-rw-r--r--src/arch/msp430fr5969lp/arch.cc150
-rw-r--r--src/arch/msp430fr5969lp/driver/gpio.cc43
-rw-r--r--src/arch/posix/Makefile.inc24
-rw-r--r--src/arch/posix/arch.cc13
-rw-r--r--src/arch/posix/driver/gpio.cc31
-rw-r--r--src/os/main.cc100
11 files changed, 458 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d255f72
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.o
+/build
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..bd82543
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+default: build/system.elf
+
+INCLUDES = -Iinclude
+COMMON_FLAGS = -g -Os -Wall -Wextra -unused
+CFLAGS = -std=c99
+CXXFLAGS = -std=c++14
+
+TARGETS = src/os/main.cc
+
+ifeq (${arch}, msp430fr5969lp)
+include src/arch/msp430fr5969lp/Makefile.inc
+endif
+
+ifeq (${arch}, posix)
+include src/arch/posix/Makefile.inc
+endif
+
+clean: arch_clean
+ rm -f build/system.elf
+
+.PHONY: clean
diff --git a/include/msp430fr5969lp/driver/gpio.h b/include/msp430fr5969lp/driver/gpio.h
new file mode 100644
index 0000000..177e7c5
--- /dev/null
+++ b/include/msp430fr5969lp/driver/gpio.h
@@ -0,0 +1,18 @@
+#ifndef GPIO_H
+#define GPIO_H
+
+class GPIO {
+ private:
+ GPIO(const GPIO &copy);
+
+ public:
+ GPIO () {}
+ void setup();
+ void led_on(unsigned char id);
+ void led_off(unsigned char id);
+ void led_toggle(unsigned char id);
+};
+
+extern GPIO gpio;
+
+#endif
diff --git a/include/posix/driver/gpio.h b/include/posix/driver/gpio.h
new file mode 100644
index 0000000..0995729
--- /dev/null
+++ b/include/posix/driver/gpio.h
@@ -0,0 +1,19 @@
+#ifndef GPIO_H
+#define GPIO_H
+
+class GPIO {
+ private:
+ GPIO(const GPIO &copy);
+ unsigned char ledstate;
+
+ public:
+ GPIO () : ledstate(0) {}
+ void setup() {}
+ void led_on(unsigned char id);
+ void led_off(unsigned char id);
+ void led_toggle(unsigned char id);
+};
+
+extern GPIO gpio;
+
+#endif
diff --git a/src/arch/msp430fr5969lp/Makefile.inc b/src/arch/msp430fr5969lp/Makefile.inc
new file mode 100644
index 0000000..04069ae
--- /dev/null
+++ b/src/arch/msp430fr5969lp/Makefile.inc
@@ -0,0 +1,37 @@
+# vim:ft=make
+
+CPU = 430x
+MCU = msp430fr5969
+
+INCLUDES += -Iinclude/msp430fr5969lp -I/opt/msp430/ti/gcc/include
+COMMON_FLAGS += -mcpu=${CPU} -mmcu=${MCU}
+
+CC = /opt/msp430/ti/gcc/bin/msp430-elf-gcc
+CXX = /opt/msp430/ti/gcc/bin/msp430-elf-g++
+OBJCOPY = /opt/msp430/ti/gcc/bin/msp430-elf-objcopy
+
+TARGETS += src/arch/msp430fr5969lp/arch.cc src/arch/msp430fr5969lp/driver/gpio.cc
+
+OBJECTS = ${TARGETS:.cc=.o}
+
+.cc.o:
+ ${CXX} ${INCLUDES} ${COMMON_FLAGS} ${CXXFLAGS} -c -o $@ ${@:.o=.cc}
+
+build/system.elf: ${OBJECTS}
+ ${CXX} ${INCLUDES} ${COMMON_FLAGS} ${CXXFLAGS} \
+ -Wl,--library-path=/opt/msp430/ti/gcc/include/ \
+ -flto -o $@ ${OBJECTS}
+
+build/system.hex: build/system.elf
+ ${OBJCOPY} -O ihex ${@:.hex=.elf} $@
+
+program: build/system.hex
+ LD_LIBRARY_PATH=/home/derf/var/projects/msp430/MSP430Flasher_1.3.7 \
+ /home/derf/var/projects/msp430/MSP430Flasher_1.3.7/MSP430Flasher \
+ -w build/system.hex -v -g -z '[VCC]'
+
+arch_clean:
+ rm -f ${OBJECTS}
+ rm -f build/system.hex
+
+.PHONY: arch_clean program
diff --git a/src/arch/msp430fr5969lp/arch.cc b/src/arch/msp430fr5969lp/arch.cc
new file mode 100644
index 0000000..19416e1
--- /dev/null
+++ b/src/arch/msp430fr5969lp/arch.cc
@@ -0,0 +1,150 @@
+#include "arch.h"
+#include <msp430.h>
+
+void Arch::setup(void)
+{
+ WDTCTL = WDTPW | WDTHOLD;
+
+ PJSEL0 = BIT4 | BIT5;
+
+ PM5CTL0 &= ~LOCKLPM5;
+
+ FRCTL0 = FWPW;
+ FRCTL0_L = 0x10;
+ FRCTL0_H = 0xff;
+
+ // 16MHz DCO
+ CSCTL0_H = CSKEY >> 8;
+ CSCTL1 = DCORSEL | DCOFSEL_4;
+ CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK;
+ CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;
+ CSCTL0_H = 0;
+
+ // enable LXFT for RTC
+ CSCTL0_H = CSKEY >> 8;
+ CSCTL4 &= ~LFXTOFF;
+ while (SFRIFG1 & OFIFG) {
+ CSCTL5 &= ~LFXTOFFG;
+ SFRIFG1 &= ~OFIFG;
+ }
+ CSCTL0_H = 0;
+
+ __delay_cycles(1000000);
+ //P1OUT = 0;
+ //P4OUT = 0;
+}
+
+void Arch::idle_loop(void)
+{
+ while (1);
+}
+
+Arch arch;
+
+/*
+void uart_setup(void)
+{
+ UCA0CTLW0 = UCSWRST | UCSSEL__SMCLK;
+ UCA0MCTLW = UCOS16 | (2<<5) | 0xD600;
+ UCA0BR0 = 104;
+
+ UCA0IRCTL = 0;
+ UCA0ABCTL = 0;
+
+ P2SEL0 &= ~(BIT0 | BIT1);
+ P2SEL1 |= BIT0 | BIT1;
+ P2DIR |= BIT0;
+
+ UCA0CTLW0 &= ~UCSWRST;
+
+ UCA0IE |= UCRXIE;
+}
+
+void uart_putchar(char c)
+{
+ while (!(UCA0IFG & UCTXIFG));
+ UCA0TXBUF = c;
+
+ if (c == '\n')
+ uart_putchar('\r');
+}
+
+__attribute__((interrupt(USCI_A0_VECTOR))) void USCI_A0_ISR(void)
+{
+ static char prompt[64];
+ static unsigned int prompt_pos = 0;
+
+ char buf;
+ unsigned char raw_p_pos, parse_p_pos;
+
+ char parsed_prompt[64];
+ unsigned char argc = 0;
+ char *argv[32];
+
+ if (UCA0IFG & UCRXIFG) {
+ buf = UCA0RXBUF;
+ if (buf == '\r') {
+
+ uart_putchar('\n');
+ if (prompt_pos > 0) {
+
+ parse_p_pos = 0;
+ argv[0] = parsed_prompt;
+
+ for (raw_p_pos = 0; raw_p_pos < prompt_pos; raw_p_pos++) {
+ if (prompt[raw_p_pos] != ' ') {
+ parsed_prompt[parse_p_pos++] = prompt[raw_p_pos];
+ } else if ((raw_p_pos > 0) && (prompt[raw_p_pos-1] != ' ')) {
+ argc++;
+ parsed_prompt[parse_p_pos++] = 0;
+ argv[argc] = parsed_prompt + parse_p_pos;
+ }
+ }
+
+ if (parse_p_pos < 64)
+ parsed_prompt[parse_p_pos] = 0;
+ else
+ parsed_prompt[63] = 0;
+
+ check_command(argc, argv);
+ prompt_pos = 0;
+ *prompt = 0;
+ }
+ uart_puts(COL_YELLOW "msp430fr5969" COL_GREEN " > " COL_RESET);
+
+ } else if (buf == '\f') {
+
+ uart_puts("\n" COL_YELLOW "msp430fr5969" COL_GREEN " > " COL_RESET);
+ uart_nputs(prompt, prompt_pos);
+
+ } else if (buf == 0x7f) {
+
+ if (prompt_pos) {
+ prompt_pos--;
+ uart_puts("\e[D \e[D");
+ }
+
+ } else if (buf == 0x15) { // ^U
+
+ for ( ; prompt_pos > 0; prompt_pos-- )
+ uart_puts("\e[D \e[D");
+ *prompt = 0;
+
+ } else if (buf == 0x17) { // ^W
+
+ for ( ; (prompt_pos > 0) && (prompt[prompt_pos] != ' '); prompt_pos-- )
+ uart_puts("\e[D \e[D");
+ for ( ; (prompt_pos > 0) && (prompt[prompt_pos-1] == ' '); prompt_pos-- )
+ uart_puts("\e[D \e[D");
+ prompt[prompt_pos] = 0;
+
+ } else if (buf >= ' ') {
+
+ if (prompt_pos < sizeof(prompt)-1) {
+ prompt[prompt_pos++] = buf;
+ uart_putchar(buf);
+ }
+ }
+ }
+}
+*/
diff --git a/src/arch/msp430fr5969lp/driver/gpio.cc b/src/arch/msp430fr5969lp/driver/gpio.cc
new file mode 100644
index 0000000..e1179af
--- /dev/null
+++ b/src/arch/msp430fr5969lp/driver/gpio.cc
@@ -0,0 +1,43 @@
+#include "driver/gpio.h"
+#include <msp430.h>
+
+void GPIO::setup()
+{
+ P1OUT = 0;
+ P2OUT = 0;
+ P3OUT = 0;
+ P4OUT = 0;
+ P1DIR = BIT0;
+ P2DIR = 0;
+ P3DIR = 0;
+ P4DIR = BIT6;
+}
+
+void GPIO::led_on(unsigned char id)
+{
+ if (id == 0) {
+ P1OUT |= BIT0;
+ } else {
+ P4OUT |= BIT6;
+ }
+}
+
+void GPIO::led_off(unsigned char id)
+{
+ if (id == 0) {
+ P1OUT &= ~BIT0;
+ } else {
+ P4OUT &= ~BIT6;
+ }
+}
+
+void GPIO::led_toggle(unsigned char id)
+{
+ if (id == 0) {
+ P1OUT ^= BIT0;
+ } else {
+ P4OUT ^= BIT6;
+ }
+}
+
+GPIO gpio;
diff --git a/src/arch/posix/Makefile.inc b/src/arch/posix/Makefile.inc
new file mode 100644
index 0000000..caf16a7
--- /dev/null
+++ b/src/arch/posix/Makefile.inc
@@ -0,0 +1,24 @@
+# vim:ft=make
+
+CC = gcc
+CXX = g++
+
+INCLUDES += -Iinclude/posix
+TARGETS += src/arch/posix/arch.cc src/arch/posix/driver/gpio.cc
+
+OBJECTS = ${TARGETS:.cc=.o}
+
+.cc.o:
+ ${CXX} ${INCLUDES} ${COMMON_FLAGS} ${CXXFLAGS} -c -o $@ ${@:.o=.cc}
+
+build/system.elf: ${OBJECTS}
+ ${CXX} ${INCLUDES} ${COMMON_FLAGS} ${CXXFLAGS} \
+ -o $@ ${OBJECTS}
+
+run: build/system.elf
+ build/system.elf
+
+arch_clean:
+ rm -f ${OBJECTS}
+
+.PHONY: arch_clean program
diff --git a/src/arch/posix/arch.cc b/src/arch/posix/arch.cc
new file mode 100644
index 0000000..efcf90e
--- /dev/null
+++ b/src/arch/posix/arch.cc
@@ -0,0 +1,13 @@
+#include "arch.h"
+#include <unistd.h>
+
+void Arch::setup(void) { }
+
+void Arch::idle_loop(void)
+{
+ while (1) {
+ sleep(1);
+ }
+}
+
+Arch arch;
diff --git a/src/arch/posix/driver/gpio.cc b/src/arch/posix/driver/gpio.cc
new file mode 100644
index 0000000..25eed39
--- /dev/null
+++ b/src/arch/posix/driver/gpio.cc
@@ -0,0 +1,31 @@
+#include "driver/gpio.h"
+#include <stdio.h>
+
+void GPIO::led_on(unsigned char id)
+{
+ if (id < 8) {
+ printf("▶ LED %3d on\n", id);
+ ledstate |= (1 << id);
+ }
+}
+
+void GPIO::led_off(unsigned char id)
+{
+ if (id < 8) {
+ printf("▶ LED %3d off\n", id);
+ ledstate &= ~(1 << id);
+ }
+}
+
+void GPIO::led_toggle(unsigned char id)
+{
+ if (id < 8) {
+ if (ledstate & (1 << id)) {
+ led_off(id);
+ } else {
+ led_on(id);
+ }
+ }
+}
+
+GPIO gpio;
diff --git a/src/os/main.cc b/src/os/main.cc
new file mode 100644
index 0000000..fff8aec
--- /dev/null
+++ b/src/os/main.cc
@@ -0,0 +1,100 @@
+#include "arch.h"
+#include "driver/gpio.h"
+
+/*
+void check_command(unsigned char argc, char** argv)
+{
+ unsigned char i2c_rxbuf[16];
+ unsigned char i2c_txbuf[16];
+ float buf = 0;
+ int i;
+ if (!strcmp(argv[0], "i2c")) {
+ if (argc == 0) {
+ uart_puterr("Usage: i2c <on|off|detect|gettemp> [-u]\n");
+ return;
+ }
+ if (!strcmp(argv[1], "on")) {
+ if ((argc >= 2) && !strcmp(argv[2], "-u")) {
+ if (i2c_setup(1) < 0)
+ uart_puterr("Error initializing I²C: Line is busy\n");
+ } else {
+ if (i2c_setup(0) < 0)
+ uart_puterr("Error initializing I²C: Line is busy\n"
+ "Do you have hardware pullups on SDA/SCL?\n");
+ }
+ } else if (!strcmp(argv[1], "off")) {
+ uart_puterr("Error: not implemented yet\n");
+ } else if (!strcmp(argv[1], "detect")) {
+ i2c_scan();
+ } else if (!strcmp(argv[1], "tc74")) {
+ i2c_txbuf[0] = 0x00;
+ i2c_xmit(0x4d, 1, 1, i2c_txbuf, i2c_rxbuf);
+ uart_putint(i2c_rxbuf[0]);
+ uart_puts("°C\n");
+ } else if (!strcmp(argv[1], "lm75")) {
+ i2c_txbuf[0] = 0x00;
+ i2c_xmit(0x48, 1, 2, i2c_txbuf, i2c_rxbuf);
+ uart_putfloat(i2c_rxbuf[0] + (i2c_rxbuf[1] / 256.0));
+ uart_puts("°C\n");
+ }
+ else if (!strcmp(argv[1], "eepr")) {
+ i2c_rxbuf[0] = 0;
+ i2c_txbuf[0] = 0;
+ i2c_txbuf[1] = argv[2][0];
+ i2c_xmit(0x50, 2, 1, i2c_txbuf, i2c_rxbuf);
+ uart_putint(i2c_rxbuf[0]);
+ uart_puts("\n");
+ }
+ else if (!strcmp(argv[1], "eepw")) {
+ i2c_txbuf[0] = 0;
+ i2c_txbuf[1] = argv[2][0];
+ i2c_txbuf[2] = argv[3][0];
+ i2c_txbuf[3] = argv[3][1];
+ i2c_txbuf[4] = argv[3][2];
+ i2c_txbuf[5] = argv[3][3];
+ i2c_txbuf[6] = argv[3][4];
+ i2c_txbuf[7] = argv[3][5];
+ i2c_xmit(0x50, 8, 0, i2c_txbuf, i2c_rxbuf);
+ }
+ } else if (!strcmp(argv[0], "sensors")) {
+ for (i = 0; i < 32; i++) {
+ buf += adc_gettemp();
+ __delay_cycles(64000);
+ }
+ uart_puts("Temperature : ");
+ uart_putfloat(buf / 32);
+ uart_puts("°C avg / ");
+ uart_putfloat(adc_gettemp());
+ uart_puts("°C single\n Voltage : ");
+ uart_putfloat(adc_getvcc());
+ uart_puts("V\n");
+ } else if (!strcmp(argv[0], "spi")) {
+ if (argc == 0) {
+ uart_puterr("Usage: spi <on|off|sharp>\n");
+ return;
+ }
+ if (!strcmp(argv[1], "on")) {
+ spi_setup();
+ }
+ } else if (!strcmp(argv[0], "help")) {
+ uart_puts("Supported commands: i2c sensors\n");
+ } else {
+ uart_puterr("Unknown command\n");
+ }
+}
+*/
+
+int main(void)
+{
+ arch.setup();
+ gpio.setup();
+ gpio.led_on(1);
+ arch.idle_loop();
+
+ //uart_setup();
+ //uart_puts("\n" COL_YELLOW "dOS" COL_GREEN " > " COL_RESET);
+
+ //arch_idle_loop();
+
+ return 0;
+}