From 7b5284023070b841293d0c5a6be0c6c345372cde Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Mon, 4 Dec 2017 15:19:25 +0100 Subject: Add basic system: LED GPIO on MSP430FR5969 Launchpad and faked GPIO on POSIX --- .gitignore | 2 + Makefile | 21 +++++ include/msp430fr5969lp/driver/gpio.h | 18 ++++ include/posix/driver/gpio.h | 19 +++++ src/arch/msp430fr5969lp/Makefile.inc | 37 ++++++++ src/arch/msp430fr5969lp/arch.cc | 150 +++++++++++++++++++++++++++++++++ src/arch/msp430fr5969lp/driver/gpio.cc | 43 ++++++++++ src/arch/posix/Makefile.inc | 24 ++++++ src/arch/posix/arch.cc | 13 +++ src/arch/posix/driver/gpio.cc | 31 +++++++ src/os/main.cc | 100 ++++++++++++++++++++++ 11 files changed, 458 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 include/msp430fr5969lp/driver/gpio.h create mode 100644 include/posix/driver/gpio.h create mode 100644 src/arch/msp430fr5969lp/Makefile.inc create mode 100644 src/arch/msp430fr5969lp/arch.cc create mode 100644 src/arch/msp430fr5969lp/driver/gpio.cc create mode 100644 src/arch/posix/Makefile.inc create mode 100644 src/arch/posix/arch.cc create mode 100644 src/arch/posix/driver/gpio.cc create mode 100644 src/os/main.cc 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 ©); + + 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 ©); + 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 + +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 + +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 + +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 + +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 [-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 \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; +} -- cgit v1.2.3