Last active
December 11, 2015 18:25
-
-
Save Jartza/3b869fa4b6a4afcc19b2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* multitask.c | |
* | |
* very quick'n'dirty multitasker-example for attiny85 | |
* | |
* Created: 11.12.15 00:24:17 | |
* Author : jartza | |
*/ | |
#include <avr/io.h> | |
#include <util/delay.h> | |
#include <avr/interrupt.h> | |
volatile uint8_t stack_hi = 0x1; // Second task stack end hi (stack begin 0x1FF) | |
volatile uint8_t stack_lo = 0xDC; // Second task stack end lo (stack begin 0x1FF) | |
// | |
// task_1() and task_2() run simultaneously. | |
// | |
// Note: Most likely the delays are much longer than you'd expect as they also run simultaneously :) | |
// | |
void task_1() { | |
while (1) { | |
PORTB |= (1 << PB0); | |
_delay_ms(100); | |
PORTB &= ~(1 << PB0); | |
_delay_ms(100); | |
} | |
} | |
void task_2() { | |
while (1) { | |
PORTB |= (1 << PB2); | |
_delay_ms(100); | |
PORTB &= ~(1 << PB2); | |
_delay_ms(100); | |
} | |
} | |
void setup() { | |
DDRB |= (1 << PB0) | (1 << PB1) | (1 << PB2); | |
// Set up timer interrupt to run every 256 clock cycles | |
TCCR1 = 0; // Stop the timer | |
TCNT1 = 0; // Zero the timer | |
GTCCR = (1 << PSR1); // Reset the prescaler | |
OCR1A = 255; // Set the compare value | |
OCR1C = 255; | |
TIMSK = (1 << OCIE1A); // Interrupt on Compare Match A | |
// Start timer in CTC mode, set prescaler / 8. Switch every 2048 cycles. | |
TCCR1 = (1 << CTC1) | (1 << CS13); | |
// Initialize second stack | |
void (*ptr_to_task)() = task_2; | |
(*(volatile unsigned char *)0x1DD) = 128; // Store fake SREG to new stack :) 0x1E0 = beginning of stack stack... | |
(*(volatile unsigned char *)0x1FE) = ((unsigned char *)&ptr_to_task)[1]; // Push task_2 "return address" to the end of new stack | |
(*(volatile unsigned char *)0x1FF) = ((unsigned char *)&ptr_to_task)[0]; // return address being actually start address of task_2... | |
} | |
int main(void) | |
{ | |
setup(); | |
sei(); | |
task_1(); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
OBJECTS = main.o task.o | |
DEVICE = attiny85 | |
CLOCK = 8000000 | |
PROGRAMMER = -c usbasp | |
FUSES = -U lfuse:w:0xe2:m -U hfuse:w:0xDF:m -U efuse:w:0xFF:m -B 12 | |
AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE) | |
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) | |
all: main.hex | |
.c.o: | |
$(COMPILE) -c $< -o $@ | |
.S.o: | |
$(COMPILE) -x assembler-with-cpp -c $< -o $@ | |
.c.s: | |
$(COMPILE) -S $< -o $@ | |
flash: all | |
$(AVRDUDE) -U flash:w:main.hex:i | |
fuse: | |
$(AVRDUDE) $(FUSES) | |
install: flash fuse | |
load: all | |
main.hex | |
clean: | |
rm -f main.hex main.elf $(OBJECTS) | |
main.elf: $(OBJECTS) | |
$(COMPILE) -o main.elf $(OBJECTS) | |
main.hex: main.elf | |
rm -f main.hex | |
avr-objcopy -j .text -j .data -O ihex main.elf main.hex | |
avr-size --format=avr --mcu=$(DEVICE) main.elf | |
disasm: main.elf | |
avr-objdump -d main.elf | |
cpp: | |
$(COMPILE) -E main.c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <avr/io.h> | |
.global TIMER1_COMPA_vect | |
.extern stack_hi | |
.extern stack_lo | |
TIMER1_COMPA_vect: | |
; Push all registers | |
; | |
push r31 | |
push r30 | |
push r29 | |
push r28 | |
push r27 | |
push r26 | |
push r25 | |
push r24 | |
push r23 | |
push r22 | |
push r21 | |
push r20 | |
push r19 | |
push r18 | |
push r17 | |
push r16 | |
push r15 | |
push r14 | |
push r13 | |
push r12 | |
push r11 | |
push r10 | |
push r9 | |
push r8 | |
push r7 | |
push r6 | |
push r5 | |
push r4 | |
push r3 | |
push r2 | |
push r1 | |
push r0 | |
; Push status register | |
; | |
in r17, _SFR_IO_ADDR(SREG) | |
push r17 | |
; Switch stack address | |
; | |
in r18, _SFR_IO_ADDR(SPL) | |
in r19, _SFR_IO_ADDR(SPH) | |
lds r20, stack_lo | |
lds r21, stack_hi | |
sts stack_lo, r18 | |
sts stack_hi, r19 | |
out _SFR_IO_ADDR(SPL), r20 | |
out _SFR_IO_ADDR(SPH), r21 | |
; Return status register | |
; | |
pop r17 | |
out _SFR_IO_ADDR(SREG), r17 | |
; Return other registers | |
; | |
pop r0 | |
pop r1 | |
pop r2 | |
pop r3 | |
pop r4 | |
pop r5 | |
pop r6 | |
pop r7 | |
pop r8 | |
pop r9 | |
pop r10 | |
pop r11 | |
pop r12 | |
pop r13 | |
pop r14 | |
pop r15 | |
pop r16 | |
pop r17 | |
pop r18 | |
pop r19 | |
pop r20 | |
pop r21 | |
pop r22 | |
pop r23 | |
pop r24 | |
pop r25 | |
pop r26 | |
pop r27 | |
pop r28 | |
pop r29 | |
pop r30 | |
pop r31 | |
; Finally, return to other task :) | |
reti |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment