From 92af9d1735aab816bca994f513314cdcc8b9bd66 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 9 Oct 2008 20:57:51 +0200 Subject: Add pressure_control firmware skeleton. Signed-off-by: Michael Buesch --- pressure_control/firmware/Makefile | 92 +++++++++++++++++++++++++++++++++ pressure_control/firmware/calibration.h | 18 +++++++ pressure_control/firmware/main.c | 32 ++++++++++++ pressure_control/firmware/util.c | 78 ++++++++++++++++++++++++++++ pressure_control/firmware/util.h | 74 ++++++++++++++++++++++++++ 5 files changed, 294 insertions(+) create mode 100644 pressure_control/firmware/Makefile create mode 100644 pressure_control/firmware/calibration.h create mode 100644 pressure_control/firmware/main.c create mode 100644 pressure_control/firmware/util.c create mode 100644 pressure_control/firmware/util.h (limited to 'pressure_control/firmware') diff --git a/pressure_control/firmware/Makefile b/pressure_control/firmware/Makefile new file mode 100644 index 0000000..30eaaf6 --- /dev/null +++ b/pressure_control/firmware/Makefile @@ -0,0 +1,92 @@ +ARCH ?= atmega8 +AVRDUDE_ARCH ?= m8 +AVRDUDE ?= avrdude +AVRDUDE_SPEED ?= 1 +PROGRAMMER ?= avrisp2 +PROGPORT ?= usb + +CC = avr-gcc +OBJCOPY = avr-objcopy +SIZE = avr-size + +CFLAGS = -mmcu=$(ARCH) -std=gnu99 -g0 -O2 -fomit-frame-pointer -Wall -fpack-struct +CFLAGS += "-Dinline=inline __attribute__((__always_inline__))" + + +# The fuse bits +LFUSE = 0xE0 +HFUSE = 0xD9 + +OBJECTS = main.o util.o +NAME = pressure_control + +BIN = $(NAME).bin +HEX = $(NAME).hex +EEP = $(NAME).eep.hex + +all: $(HEX) + +main.o: util.h + +util.o: util.h calibration.h + +%.s: %.c + $(CC) $(CFLAGS) -S $*.c + +$(BIN): $(OBJECTS) + $(CC) $(CFLAGS) -o $(BIN) $(OBJECTS) $(LDFLAGS) + +$(HEX): $(BIN) + $(OBJCOPY) -R.eeprom -O ihex $(BIN) $(HEX) +# $(OBJCOPY) -j.eeprom --set-section-flags=.eeprom="alloc,load" \ +# --change-section-lma .eeprom=0 -O ihex $(BIN) $(EEP) + $(SIZE) $(BIN) + +avrdude: + $(AVRDUDE) -B $(AVRDUDE_SPEED) -p $(AVRDUDE_ARCH) \ + -c $(PROGRAMMER) -P $(PROGPORT) -t + +install_flash: + $(AVRDUDE) -B $(AVRDUDE_SPEED) -p $(AVRDUDE_ARCH) \ + -c $(PROGRAMMER) -P $(PROGPORT) -U flash:w:$(HEX) + +install_eeprom: + $(AVRDUDE) -B $(AVRDUDE_SPEED) -p $(AVRDUDE_ARCH) \ + -c $(PROGRAMMER) -P $(PROGPORT) -U eeprom:w:$(EEP) + +install: all install_flash + +# Reset the microcontroller through avrdude +reset: + $(AVRDUDE) -B $(AVRDUDE_SPEED) -p $(AVRDUDE_ARCH) \ + -c $(PROGRAMMER) -P $(PROGPORT) \ + -U signature:r:/dev/null:i -q -q + +writefuse: + $(AVRDUDE) -B 100 -p $(AVRDUDE_ARCH) \ + -c $(PROGRAMMER) -P $(PROGPORT) -q -q \ + -U lfuse:w:$(LFUSE):m \ + -U hfuse:w:$(HFUSE):m + +clean: + -rm -f *~ *.o $(BIN) + +distclean: clean + -rm -f *.s $(HEX) $(EEP) + +help: + @echo "Makefile" + @echo "" + @echo "Targets:" + @echo " all - build the firmware (default target)" + @echo " clean - remove object files" + @echo " distclean - remove object, binary and hex files" + @echo "" + @echo "Targets that operate on the device through avrdude:" + @echo " install - flash the program code" + @echo " writefuse - write the fuse bits" + @echo " reset - pull the external device reset pin" + @echo " avrdude - run avrdude in interactive mode" + @echo "" + @echo "Generic targets:" + @echo " *.s - create an assembly file from a *.c file" diff --git a/pressure_control/firmware/calibration.h b/pressure_control/firmware/calibration.h new file mode 100644 index 0000000..eb2f532 --- /dev/null +++ b/pressure_control/firmware/calibration.h @@ -0,0 +1,18 @@ +#ifndef CALIBRATION_H_ +#define CALIBRATION_H_ + +/**************************************************************************** + * Microcontroller CPU speed calibration * + ****************************************************************************/ + +/* CPU frequency in HZ */ +#define CPU_HZ 16000000 +/* 1ms timer calibration */ +#define DELAY_1MS_TIMERFREQ (1 << CS01) /* == CPU_FREQ/8 */ +#define DELAY_1MS_LOOP 80 +#define DELAY_1MS_LOOP_TIMES 25 +/* 1us delayloop calibration */ +#define DELAY_1US_LOOP 4 + + +#endif /* CALIBRATION_H_ */ diff --git a/pressure_control/firmware/main.c b/pressure_control/firmware/main.c new file mode 100644 index 0000000..949e5cb --- /dev/null +++ b/pressure_control/firmware/main.c @@ -0,0 +1,32 @@ +/* + * Pneumatic pressure controller. + * + * Copyright (C) 2008 Michael Buesch + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "util.h" + + +int main(void) +{ + cli(); + //TODO + sei(); + + while (1) { + //TODO + } +} diff --git a/pressure_control/firmware/util.c b/pressure_control/firmware/util.c new file mode 100644 index 0000000..3cecc46 --- /dev/null +++ b/pressure_control/firmware/util.c @@ -0,0 +1,78 @@ +/* + * Utility functions + * + * Copyright (C) 2008 Michael Buesch + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + */ + +#include "util.h" +#include "calibration.h" + +#include +#include + + +void mdelay(uint16_t msecs) +{ + uint8_t timer, i; + + TCCR0 = DELAY_1MS_TIMERFREQ; + do { + /* Delay one millisecond */ + for (i = DELAY_1MS_LOOP_TIMES; i; i--) { + TCNT0 = 0; + do { + timer = TCNT0; + } while (timer < DELAY_1MS_LOOP); + } + } while (--msecs); + TCCR0 = 0; +} + +void udelay(uint16_t usecs) +{ + uint8_t tmp; + + __asm__ __volatile__( + "1: \n" + " ldi %1, %2 \n" + "2: \n" + " dec %1 \n" + " brne 2b \n" + " dec %A3 \n" + " brne 1b \n" + " cp %B3, __zero_reg__ \n" + " breq 3f \n" + " dec %B3 \n" + " ldi %A3, 0xFF \n" + " rjmp 1b \n" + "3: \n" + : "=d" (usecs), + "=d" (tmp) + : "M" (DELAY_1US_LOOP), + "0" (usecs) + ); +} + +void panic(const prog_char *msg) +{ +//TODO + infinite_sleep(); +} + +void infinite_sleep(void) +{ + cli(); + set_sleep_mode(SLEEP_MODE_PWR_DOWN); + while (1) + sleep_mode(); +} diff --git a/pressure_control/firmware/util.h b/pressure_control/firmware/util.h new file mode 100644 index 0000000..758f6f8 --- /dev/null +++ b/pressure_control/firmware/util.h @@ -0,0 +1,74 @@ +#ifndef UTIL_H_ +#define UTIL_H_ + +#include +#include +#include +#include + +/* Some of these macros are derived from the Linux Kernel sources. */ + +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + +#define offsetof(type, member) ((size_t)&((type *)0)->member) + +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define max(a, b) ((a) > (b) ? (a) : (b)) + +#define abs(x) ({ \ + __typeof__(x) __x = (x); \ + (__x < 0) ? -__x : __x; \ + }) + +#define lo8(x) ((uint8_t)(x)) +#define hi8(x) ((uint8_t)((x) >> 8)) + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +/* Memory barrier. + * The CPU doesn't have runtime reordering, so we just + * need a compiler memory clobber. */ +#define mb() __asm__ __volatile__("" : : : "memory") + +/* Convert something indirectly to a string */ +#define __stringify(x) #x +#define stringify(x) __stringify(x) + +/* Assertions */ +void panic(const prog_char *msg) __attribute__((noreturn)); +#define BUILD_BUG_ON(x) ((void)sizeof(char[1 - 2 * !!(x)])) +#define BUG_ON(x) \ + do { \ + if (unlikely(x)) \ + panic(PSTR(__FILE__ \ + stringify(__LINE__))); \ + } while (0) + +void infinite_sleep(void) __attribute__((noreturn)); + +/* Delay */ +void mdelay(uint16_t msecs); +void udelay(uint16_t usecs); + +typedef _Bool bool; + +/* IRQ handling. + * We use a macro for irq_disable_save(), because stupid gcc is not + * able to properly optimize an inline function that returns a value. + */ +#define irq_disable_save() ({ \ + uint8_t sreg_flags = SREG; \ + cli(); \ + sreg_flags; \ + }) + +static inline void irq_restore(uint8_t sreg_flags) +{ + mb(); + SREG = sreg_flags; +} + +#define irqs_disabled() (!(SREG & (1 << SREG_I))) + +#endif /* UTIL_H_ */ -- cgit v1.2.3