Initial commit

This commit is contained in:
sebastian laptop 2011-10-06 14:53:21 +02:00
commit 7b50230314
4 changed files with 381 additions and 0 deletions

80
Makefile Normal file
View File

@ -0,0 +1,80 @@
#
# Makefile
# Created on: Sep 28, 2011
# Author: sebastian
#
# This file is part of the RingLock-library for Atmel AVR MCUS.
#
# RingLock 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.
#
# RingLock 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 RingLock. If not, see <http://www.gnu.org/licenses/>.
#
# Copyright Sebastian Schumb (sebastian_at_sebastians-site_de) 2011
#
SRC = main.c include/ringlock.c
TARGET = ringlock-$(AVRMCU)-$(LOCKROLE)
OBJDIR = bin/$(AVRMCU)-$(LOCKROLE)
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
OBJ = $(SRC:%.c=$(OBJDIR)/%.o)
CFLAGS = -Os -Wall -Wstrict-prototypes
CFLAGS += -fshort-enums -fpack-struct -funsigned-char -funsigned-bitfields
CFLAGS += -mmcu=$(AVRMCU) -DF_CPU=$(F_CPU)UL
ifeq "$(LOCKROLE)" "master"
CFLAGS += -DRL_MASTER
endif
all: start $(OBJDIR)/$(TARGET).hex size
@echo "Done !"
start:
@echo " _____ _ _ _"
@echo "| ___ (_) | | | |"
@echo "| |_/ /_ _ __ __ _| | ___ ___| | __"
@echo "| /| | '_ \ / _\` | | / _ \ / __| |/ /"
@echo "| |\ \| | | | | (_| | |____| (_) | (__| < "
@echo "\_| \_|_|_| |_|\__, \_____/ \___/ \___|_|\_\\"
@echo " __/ |"
@echo " |___/"
@echo
@echo "Software based token passing mutex for AVR microcontrollers"
@echo
@echo ":: Building for $(AVRMCU)"
@echo ":: Role is $(LOCKROLE)"
@echo ":: MCU operating frequency is $(F_CPU)Hz"
$(OBJDIR)/%.o : %.c
@mkdir -p $$(dirname $@)
$(CC) $(CFLAGS) -c $< -o $@
$(OBJDIR)/$(TARGET).elf : $(OBJ)
$(CC) $(CFLAGS) $+ -o $@
$(OBJDIR)/$(TARGET).hex : $(OBJDIR)/$(TARGET).elf
$(OBJCOPY) -O ihex $< $@
size : $(OBJDIR)/$(TARGET).elf
@echo
@$(SIZE) $(OBJDIR)/$(TARGET).hex
@echo
clean :
@rm -rf $(OBJDIR)

72
include/ringlock.c Normal file
View File

@ -0,0 +1,72 @@
/*
* ringlock.c
*
* Created on: Sep 28, 2011
* Author: sebastian
*
* This file is part of the RingLock-library for Atmel AVR MCUS.
*
* RingLock 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.
*
* RingLock 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 RingLock. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright Sebastian Schumb (sebastian_at_sebastians-site_de) 2011
*/
#include "ringlock.h"
void rl_init(void) {
//Setting up pin to pass on the token
RL_OUT_DDR |= (1 << RL_OUT);
RL_OUT_PORT &= ~(1 << RL_OUT);
//Setting up the interrupt use to receive the token
RL_INT_DDR &= ~(1 << RL_INT_PIN);
RL_INT_CONFIG |= RL_INT_CBITS;
RL_INT_ENABLE |= (1 << RL_INT_EBITS);
rl_request_token = 0;
#ifdef RL_MASTER
rl_have_token = 1; //Master haz the token
rl_to_setup(); //Fire up the timer
rl_to_start();
#else
rl_have_token = 0;
#endif
}
/*
* Interrupt used for getting the token and timeout
*/
ISR(RL_INT) {
rl_have_token = 1;
if(!rl_request_token) {
rl_release_lock();
}
else {
rl_request_token = 0;
}
#ifdef RL_MASTER
rl_to_reset(); // reset the timeout
#endif
}
#ifdef RL_MASTER
ISR(RL_TO_INT, ISR_ALIASOF(RL_INT)); // if we have a timeout,
// we just pretend to have the token
#endif

151
include/ringlock.h Normal file
View File

@ -0,0 +1,151 @@
/*
* ringlock.h
*
* Created on: Sep 28, 2011
* Author: sebastian
*
* This file is part of the RingLock-library for Atmel AVR MCUS.
*
* RingLock 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.
*
* RingLock 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 RingLock. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright Sebastian Schumb (sebastian_at_sebastians-site_de) 2011
*/
#ifndef RINGLOCK_H_
#define RINGLOCK_H_ RINGLOCK_H_
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#ifdef __AVR_ATmega32__
/*
* Config for the Port that passes the token on
*/
#define RL_OUT_PORT PORTD // Port used for passing the token,
#define RL_OUT_DDR DDRD // DDRD for that port
#define RL_OUT PD5 // and the pin we want to use
/*
* Config for the external interrupt
*/
#define RL_INT_DDR DDRD // DDR
#define RL_INT_PIN PIN2 // and the Pin used for the interrupt
#define RL_INT INT0_vect // The timer interrupt
#define RL_INT_CONFIG MCUCR // Interrupt config register
#define RL_INT_CBITS ((1 << ISC00) | (1 << ISC01)) // bits to set in this register
#define RL_INT_ENABLE GICR // Global Interrupt Register
#define RL_INT_EBITS INT0 // Bit that enables the interrupt
/*
* Timer config
* The master has a timeout timer, just in case a token gets lost,
* or you have a controller with messed up code in the ring ...
*/
#define RL_TO_TIME 10 //timeout in milliseconds
#define RL_TO_INT TIMER0_COMP_vect //timer interrupt
/*
* You can't use the config register and bits approach from above for timers,
* e.g. some mcus split TCCR in two registers.
* Therefore I cheated a little and used static inline functions,
* to make the timers configurable.
*/
// function called to setup the timer
static inline void rl_to_setup(void) {
TCCR0 |= (1 << WGM01);
TIMSK |= (1 << OCIE0);
OCR0 = ((RL_TO_TIME * F_CPU/1000) / 1024); //1024 is prescaler
}
// function called to start the timer
static inline void rl_to_start(void) {
TCCR0 |= (1<<CS00) | (1<<CS02);
}
// function called to reset the timer
static inline void rl_to_reset(void) {
TCCR0 &= ~((1<<CS00) | (1<<CS02));
TCNT0 = 0;
rl_to_start();
}
#elif defined __AVR_ATmega8__
/*
* Config for the Port that passes the token on
* Explanation see above ...
*/
#define RL_OUT_PORT PORTD
#define RL_OUT_DDR DDRD
#define RL_OUT PD0
/*
* Config for the external interrupt
* Explanation see above ...
*/
#define RL_INT_DDR DDRD
#define RL_INT_PIN PD2
#define RL_INT INT0_vect
#define RL_INT_CONFIG MCUCR
#define RL_INT_CBITS ((1 << ISC00) | (1 << ISC01))
#define RL_INT_ENABLE GICR
#define RL_INT_EBITS INT0
/*
* TODO: Add timer config here ;)
*/
#else
#error "MCU is not supported. Please add it to ringlock.h"
#endif
/*
* Config ends here
*/
volatile uint8_t rl_request_token; // set if the controller should keep the token
volatile uint8_t rl_have_token; // set if the controller has the token
/*
* Functions for manipulation the token
* The next two functions might seem necessary,
* but we don't want people fiddling with the flags directly.
*/
static inline void rl_request_lock(void) {
rl_request_token = 1;
}
static inline uint8_t rl_have_lock(void) {
return rl_have_token;
}
static inline void rl_release_lock(void) { // used to release the token
if(rl_have_token) { // make sure we have the token
rl_have_token = 0;
RL_OUT_PORT |= (1 << RL_OUT);
_delay_us(1); // give the signal time to raise
RL_OUT_PORT &= ~(1 << RL_OUT);
}
}
void rl_init(void);
#endif /* RINGLOCK_H_ */

78
main.c Normal file
View File

@ -0,0 +1,78 @@
/*
* main.c
*
* Created on: Sep 28, 2011
* Author: sebastian
*
* Makefile
* Created on: Sep 28, 2011
* Author: sebastian
*
* This file is part of the RingLock-library for Atmel AVR MCUS.
*
* RingLock 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.
*
* RingLock 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 RingLock. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright Sebastian Schumb (sebastian_at_sebastians-site_de) 2011
*/
#include <avr/io.h>
#include <util/delay.h>
#include "include/ringlock.h"
#define BAUD 9600UL // baudrate
// Some calculations ...
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // rounding magic
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Real baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Error in 0,1%
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010)) // Make sure your UBRR_VAL will work
#error Baudrate error is bigger then 1% !
#endif
int main(void) {
rl_init();
UBRRH = UBRR_VAL >> 8; //Setting baudrate
UBRRL = UBRR_VAL & 0xFF;
UCSRB |= (1<<TXEN); // UART TX
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // Asynchronous 8N1
sei();
while(1) {
rl_request_lock(); // Request a log
while(!rl_have_lock()); // Wait for it
while (!(UCSRA & (1<<UDRE))); // Make sure the uart is ready to go
#ifdef RL_MASTER
UDR = 'A'; // Master send A
#else
UDR = 'B'; // Slave send B
#endif
while (!(UCSRA & (1<< TXC))); // waiting for the uart to finish transmission
UCSRA |= (1 << TXC); // resetting the TXC bit
_delay_us(250); // We need to make sure, that no other mcu
// is sending during our stop bit.
rl_release_lock(); // Stop bit is over, the other can talk.
}
return 0;
}