Added feedback board firmware

This commit is contained in:
Gregor Riepl 2021-01-17 15:37:57 +01:00
parent e2b28730dd
commit 42726c06c2
3 changed files with 273 additions and 0 deletions

115
feedback/firmware/Makefile Normal file
View file

@ -0,0 +1,115 @@
PRG = feedback
AVRCANLIB_PATH = ../../avr-can-lib
OBJ = main.o \
$(AVRCANLIB_PATH)/src/at90can_buffer.o \
$(AVRCANLIB_PATH)/src/at90can.o \
$(AVRCANLIB_PATH)/src/at90can_disable_dyn_filter.o \
$(AVRCANLIB_PATH)/src/at90can_error_register.o \
$(AVRCANLIB_PATH)/src/at90can_get_buf_message.o \
$(AVRCANLIB_PATH)/src/at90can_get_dyn_filter.o \
$(AVRCANLIB_PATH)/src/at90can_get_message.o \
$(AVRCANLIB_PATH)/src/at90can_send_buf_message.o \
$(AVRCANLIB_PATH)/src/at90can_send_message.o \
$(AVRCANLIB_PATH)/src/at90can_set_dyn_filter.o \
$(AVRCANLIB_PATH)/src/at90can_set_mode.o \
$(AVRCANLIB_PATH)/src/can_buffer.o
# These were defined for the avr-can-lib, but they really, really
# shouldn't be used there because they affect the whole program.
OPTIMIZE = -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
PROGRAMMER = usbtiny
MCU_TARGET = atmega32m1
DEFS = -DF_CPU=16000000UL -DHAS_CAN_CONFIG_H
INCLUDES = -I. -I$(AVRCANLIB_PATH)
LIBS =
LFUSE = 0xdf
HFUSE = 0xd9
EFUSE = 0xfe
EXTRA_CLEAN_FILES =
# You should not have to change anything below here.
CC = avr-gcc
DUDE = avrdude
HOST_CC = gcc
HOST_CFLAGS = -O0 -g
HOST_LDFLAGS =
# Override is only needed by avr-lib build system.
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) $(INCLUDES)
override LDFLAGS = -Wl,-Map,$(PRG).map
DUDEFLAGS = -c $(PROGRAMMER) -p $(MCU_TARGET)
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
all: $(PRG).elf lst text eeprom
$(PRG).elf: $(OBJ) $(LIBS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
clean:
rm -f $(OBJ) $(PRG).elf $(PRG).lst $(PRG).map $(PRG).bin $(PRG).hex $(PRG).srec $(PRG)_eeprom.bin $(PRG)_eeprom.hex $(PRG)_eeprom.srec $(EXTRA_CLEAN_FILES)
lst: $(PRG).lst
%.lst: %.elf
$(OBJDUMP) -h -S $< > $@
# Rules for flashing, EEPROM writing and fuse bit setting
flash: $(PRG).hex $(PRG)_eeprom.hex
$(DUDE) $(DUDEFLAGS) -U eeprom:w:$(PRG)_eeprom.hex:i -U flash:w:$(PRG).hex:i
flashprg: $(PRG).hex
$(DUDE) $(DUDEFLAGS) -U flash:w:$(PRG).hex:i
flasheep: $(PRG)_eeprom.hex
$(DUDE) $(DUDEFLAGS) -U eeprom:w:$(PRG)_eeprom.hex:i
fuse:
$(DUDE) $(DUDEFLAGS) -U hfuse:w:$(HFUSE):m -U lfuse:w:$(LFUSE):m -U efuse:w:$(EFUSE):m
# Rules for building the .text rom images
text: hex bin srec
hex: $(PRG).hex
bin: $(PRG).bin
srec: $(PRG).srec
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.srec: %.elf
$(OBJCOPY) -j .text -j .data -O srec $< $@
%.bin: %.elf
$(OBJCOPY) -j .text -j .data -O binary $< $@
# Rules for building the .eeprom rom images
eeprom: ehex ebin esrec
ehex: $(PRG)_eeprom.hex
ebin: $(PRG)_eeprom.bin
esrec: $(PRG)_eeprom.srec
%_eeprom.hex: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ \
|| { echo empty $@ not generated; exit 0; }
%_eeprom.srec: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O srec $< $@ \
|| { echo empty $@ not generated; exit 0; }
%_eeprom.bin: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O binary $< $@ \
|| { echo empty $@ not generated; exit 0; }

View file

@ -0,0 +1,79 @@
#ifndef CONFIG_H
#define CONFIG_H
#define CAN_CONFIG_LOADED
// -----------------------------------------------------------------------------
/* Global settings for building the can-lib and application program.
*
* The following two #defines must be set identically for the can-lib and
* your application program. They control the underlying CAN struct. If the
* settings disagree, the underlying CAN struct will be broken, with
* unpredictable results.
* If can.h detects that any of the #defines is not defined, it will set them
* to the default values shown here, so it is in your own interest to have a
* consistent setting. Ommiting the #defines in both can-lib and application
* program will apply the defaults in a consistent way too.
*
* Select if you want to use 29 bit identifiers.
*/
#define SUPPORT_EXTENDED_CANID 1
/* Select if you want to use timestamps.
* Timestamps are sourced from a register internal to the AT90CAN.
* Selecting them on any other controller will have no effect, they will
* be 0 all the time.
*/
#define SUPPORT_TIMESTAMPS 0
// -----------------------------------------------------------------------------
/* Global settings for building the can-lib.
*
* Select ONE CAN controller for which you are building the can-lib.
*/
#define SUPPORT_MCP2515 0
#define SUPPORT_AT90CAN 1
#define SUPPORT_SJA1000 0
// -----------------------------------------------------------------------------
/* Setting for MCP2515
*
* Declare which pins you are using for communication.
* Remember NOT to use them in your application!
* It is a good idea to use bits from the port that carries MOSI, MISO, SCK.
*/
#define MCP2515_CS B,4
#define MCP2515_INT B,2
// -----------------------------------------------------------------------------
// Setting for SJA1000
#define SJA1000_INT E,0
#define SJA1000_MEMORY_MAPPED 1
// memory-mapped interface
#define SJA1000_BASE_ADDR 0x8000 // for ATMega162
/*
// port-interface
#define SJA1000_WR D,6
#define SJA1000_RD D,7
#define SJA1000_ALE E,1
#define SJA1000_CS C,0
#define SJA1000_DATA A
*/
// -----------------------------------------------------------------------------
// Setting for AT90CAN
// Number of CAN messages which are buffered in RAM additinally to the MObs
#define CAN_RX_BUFFER_SIZE 16
#define CAN_TX_BUFFER_SIZE 8
// only available if CAN_TX_BUFFER_SIZE > 0
#define CAN_FORCE_TX_ORDER 1
#endif // CONFIG_H

79
feedback/firmware/main.c Normal file
View file

@ -0,0 +1,79 @@
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <can.h>
static void init() {
// Set PB as input, pull-up off
DDRB = 0;
// Set PC0/4/6 as input, pull-up off
DDRC &= ~(_BV(DDC0) | _BV(DDC4) | _BV(DDC6));
// Initialize CAN interface
can_init(BITRATE_125_KBPS);
// Regular receive/transmit mode
can_set_mode(NORMAL_MODE);
// Filter for status requests
can_filter_t filter = {
.id = 0x10,
.mask = 0x7ff,
.flags = {
.rtr = 1,
.extended = 0,
},
};
can_set_filter(0, &filter);
// Enable interrupts to start reception
sei();
}
static void send_status() {
// Get GPIO state
// PB -> invert -> Dend..Hend, Dempty..Fempty
uint8_t statusl = ~PINB;
// PC0,6,4 -> invert -> Gempty, Hempty, Reset
uint8_t pinc = ~PINC;
uint8_t gempty = (pinc & _BV(0)) ? _BV(0) : 0;
uint8_t hempty = (pinc & _BV(6)) ? _BV(1) : 0;
uint8_t swres = (pinc & _BV(4)) ? _BV(2) : 0;
uint8_t statush = gempty | hempty | swres;
if (can_check_free_buffer()) {
can_t msg = {
.id = 0x10,
.flags = {
.rtr = 0,
},
.length = 2,
.data = { statush, statusl, },
};
can_send_message(&msg);
}
}
static void loop() {
// Check for new messages
if (can_check_message()) {
can_t msg = { 0 };
uint8_t status = can_get_message(&msg);
if (status != 0) {
switch (msg.id) {
case 0x10:
if (msg.flags.rtr) {
send_status();
}
}
}
}
}
int main() {
init();
while (1) {
loop();
}
}