From 189cd03ffbf11a28e8ec839e63ebacc728d83959 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 12 May 2011 21:55:19 -0700 Subject: [PATCH] Add uart test --- ao-bringup-avr/Makefile | 15 +- ao-bringup-avr/ao-switch.c | 282 +++++++++++++++++++++++++++++++++++++ ao-bringup-avr/ao-uart.c | 135 ++++++++++++++++++ 3 files changed, 431 insertions(+), 1 deletion(-) create mode 100644 ao-bringup-avr/ao-switch.c create mode 100644 ao-bringup-avr/ao-uart.c diff --git a/ao-bringup-avr/Makefile b/ao-bringup-avr/Makefile index 593bf786..a110b50a 100644 --- a/ao-bringup-avr/Makefile +++ b/ao-bringup-avr/Makefile @@ -8,7 +8,7 @@ CC=avr-gcc OBJCOPY=avr-objcopy CFLAGS=-g -mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues -all: ao-blink.hex ao-switch.hex +all: ao-blink.hex ao-switch.hex ao-uart.hex ao-blink.hex: ao-blink avr-size ao-blink @@ -27,8 +27,21 @@ ao-switch: ao-switch.o ao-switch.s: ao-switch.c $(CC) $(CFLAGS) -S -o $@ ao-switch.c +ao-uart.hex: ao-uart + avr-size ao-uart + $(OBJCOPY) -R .eeprom -O ihex ao-uart $@ + +ao-uart: ao-uart.o + $(CC) $(CFLAGS) -o $@ ao-uart.o + +ao-uart.s: ao-uart.c + $(CC) $(CFLAGS) -S -o $@ ao-uart.c + load-blink: ao-blink.hex $(LOADCMD) $(LOADARG)ao-blink.hex load-switch: ao-switch.hex $(LOADCMD) $(LOADARG)ao-switch.hex + +load-uart: ao-uart.hex + $(LOADCMD) $(LOADARG)ao-uart.hex diff --git a/ao-bringup-avr/ao-switch.c b/ao-bringup-avr/ao-switch.c new file mode 100644 index 00000000..2e3f5a73 --- /dev/null +++ b/ao-bringup-avr/ao-switch.c @@ -0,0 +1,282 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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; version 2 of the License. + * + * 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, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#define TEENSY 0 +#if TEENSY +#define F_CPU 16000000UL // 16 MHz +#else +#define F_CPU 8000000UL // 8 MHz +#endif +#include + +#define LEDOUT PORTB7 +#define LEDPORT PORTB +#define LEDDDR DDRB +#define LEDDDRPIN DD7 + +static void +adc_start(void); + +ISR(TIMER1_COMPA_vect) +{ + adc_start(); +} + +static void +timer1_init(void) +{ + TCCR1A = ((0 << WGM11) | /* CTC mode, OCR1A */ + (0 << WGM10)); /* CTC mode, OCR1A */ + TCCR1B = ((0 << ICNC1) | /* no input capture noise canceler */ + (0 << ICES1) | /* input capture on falling edge (don't care) */ + (0 << WGM13) | /* CTC mode, OCR1A */ + (1 << WGM12) | /* CTC mode, OCR1A */ + (3 << CS10)); /* clk/64 from prescaler */ + +#if TEENSY + OCR1A = 2500; /* 16MHz clock */ +#else + OCR1A = 1250; /* 8MHz clock */ +#endif + + TIMSK1 = (1 << OCIE1A); /* Interrupt on compare match */ +} + +static void +clock_init(void) +{ + /* disable RC clock */ + CLKSEL0 &= ~(1 << RCE); + + /* Disable PLL */ + PLLCSR &= ~(1 << PLLE); + + /* Enable external clock */ + CLKSEL0 |= (1 << EXTE); + + /* wait for external clock to be ready */ + while ((CLKSTA & (1 << EXTON)) == 0) + ; + + /* select external clock */ + CLKSEL0 |= (1 << CLKS); + + /* Disable the clock prescaler */ + cli(); + CLKPR = (1 << CLKPCE); + CLKPR = 0; + sei(); + + /* Set up the PLL to use the crystal */ + + /* Use primary system clock as PLL source */ + PLLFRQ = ((0 << PINMUX) | /* Use primary clock */ + (0 << PLLUSB) | /* No divide by 2 for USB */ + (0 << PLLTM0) | /* Disable high speed timer */ + (0x4 << PDIV0)); /* 48MHz PLL clock */ + + /* Set the frequency of the crystal */ +#if TEENSY + PLLCSR |= (1 << PINDIV); /* For 16MHz crystal on Teensy board */ +#else + PLLCSR &= ~(1 << PINDIV); /* For 8MHz crystal on TeleScience board */ +#endif + + /* Enable the PLL */ + PLLCSR |= (1 << PLLE); + while (!(PLLCSR & (1 << PLOCK))) + ; +} + +static void +timer0_init(void) +{ + TCCR0A = ((1 << COM0A1) | + (0 << COM0A0) | + (1 << WGM01) | + (1 << WGM00)); + + OCR0A = 0x10; + OCR0B = 0; + TIMSK0 = 0; + + TCCR0B = ((0 << WGM02) | + (5 << CS00)); +} + +ISR(ADC_vect) +{ + OCR0A = ADCH; +} + +#define ADC_CHANNEL 0x25 /* Channel ADC13 */ +#define ADC_CHANNEL_LOW(c) (((c) & 0x1f) << MUX0) +#define ADC_CHANNEL_HIGH(c) ((((c) & 0x20) >> 5) << MUX5) + +#define ADCSRA_INIT ((1 << ADEN) | /* Enable ADC */ \ + (0 << ADATE) | /* No auto ADC trigger */ \ + (1 << ADIE) | /* Enable interrupt */ \ + (6 << ADPS0)) /* Prescale clock by 64 */ + +#define ADCSRB_INIT ((0 << ADHSM) | /* No high-speed mode */ \ + (0 << ACME) | /* Some comparitor thing */ \ + (0 << ADTS0)) /* Free running mode (don't care) */ + +static void +adc_start(void) +{ + ADMUX = ((0 << REFS1) | /* AVcc reference */ + (1 << REFS0) | /* AVcc reference */ + (1 << ADLAR) | /* Left-shift results */ + (ADC_CHANNEL_LOW(ADC_CHANNEL))); /* Select channel */ + + ADCSRB = ADCSRB_INIT | ADC_CHANNEL_HIGH(ADC_CHANNEL); + + ADCSRA = ADCSRA_INIT | (1 << ADSC); /* Start conversion */ +} + +static void +adc_init(void) +{ + ADCSRA = ADCSRA_INIT; + ADCSRB = ADCSRB_INIT; + DIDR0 |= (1 << 0); +} + +#define AO_STACK_SIZE 128 + +uint8_t new_stack[512]; +int stack_count; + +#define PUSH8(stack, val) (*--(stack) = (val)) + +#define PUSH16(stack, val) PUSH8(stack, ((uint16_t) (val))); PUSH8(stack, ((uint16_t) (val)) >> 8) + +void +count(int count) +{ + +} + +void +blink(void) +{ + while (1) { + LEDPORT ^= (1 << LEDOUT); + _delay_ms(200); + } +} + +void +function(void) +{ + return; +} + +void +init_stack(void (*f) (void)) +{ + uint8_t *stack = new_stack + AO_STACK_SIZE; + uint8_t i; + + /* Return address */ + PUSH16(stack, f); + +#if 0 + /* Clear register values */ + i = 32; + while (i--) + PUSH8(stack, 0); + + /* SREG with interrupts enabled */ + PUSH8(stack, 0x80); +#endif + stack_count = stack - new_stack; +} + +void +switch_stack(void) __attribute__((naked)); + +void +switch_stack(void) +{ +#if 0 + uint16_t a; + uint8_t l, h; + + a = (uint16_t) function; + l = a; + h = a >> 8; + asm("push %0" : : "r" (l)); + asm("push %0" : : "r" (h)); + asm("ret"); +#endif +#if 0 + asm("push r31; push r30"); + asm("push r29; push r28; push r27; push r26; push r25"); + asm("push r24; push r23; push r22; push r21; push r20"); + asm("push r19; push r18; push r17; push r16; push r15"); + asm("push r14; push r13; push r12; push r11; push r10"); + asm("push r9; push r8; push r7; push r6; push r5"); + asm("push r4; push r3; push r2; push r1; push r0"); + asm("in r0, __SREG__" "\n\t" + "push r0"); +#endif + uint8_t *sp = (new_stack + stack_count); + uint8_t sp_l, sp_h; + + sp_l = (uint16_t) sp; + sp_h = ((uint16_t) sp) >> 8; + asm("out __SP_H__,%0" : : "r" (sp_h) ); + asm("out __SP_L__,%0" : : "r" (sp_l) ); + blink(); +#if 0 + asm("pop r0" "\n\t" + "out __SREG__, r0"); + asm("pop r0; pop r1; pop r2; pop r3; pop r4"); + asm("pop r5; pop r6; pop r7; pop r8; pop r9"); + asm("pop r10; pop r11; pop r12; pop r13; pop r14"); + asm("pop r15; pop r16; pop r17; pop r18; pop r19"); + asm("pop r20; pop r21; pop r22; pop r23; pop r24"); + asm("pop r25; pop r26; pop r27; pop r28; pop r29"); + asm("pop r30; pop r31"); +#endif + asm("ret"); +} + +void back(void) +{ + switch_stack(); + blink(); +} + +void main(void) +{ +#if 0 + clock_init(); + adc_init(); + timer1_init(); + timer0_init(); +#endif + + LEDDDR |= (1 << LEDDDRPIN); + + init_stack(blink); + switch_stack(); +} diff --git a/ao-bringup-avr/ao-uart.c b/ao-bringup-avr/ao-uart.c new file mode 100644 index 00000000..3c290c1a --- /dev/null +++ b/ao-bringup-avr/ao-uart.c @@ -0,0 +1,135 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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; version 2 of the License. + * + * 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, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#define TEENSY 1 +#if TEENSY +#define F_CPU 16000000UL // 16 MHz +#else +#define F_CPU 8000000UL // 8 MHz +#endif +#include + +#define LEDOUT PORTB7 +#define LEDPORT PORTB +#define LEDDDR DDRB +#define LEDDDRPIN DD7 + +static void +timer1_init(void) +{ + TCCR1A = ((0 << WGM11) | /* CTC mode, OCR1A */ + (0 << WGM10)); /* CTC mode, OCR1A */ + TCCR1B = ((0 << ICNC1) | /* no input capture noise canceler */ + (0 << ICES1) | /* input capture on falling edge (don't care) */ + (0 << WGM13) | /* CTC mode, OCR1A */ + (1 << WGM12) | /* CTC mode, OCR1A */ + (3 << CS10)); /* clk/64 from prescaler */ + +#if TEENSY + OCR1A = 2500; /* 16MHz clock */ +#else + OCR1A = 1250; /* 8MHz clock */ +#endif + + TIMSK1 = (1 << OCIE1A); /* Interrupt on compare match */ +} + +static void +clock_init(void) +{ + /* disable RC clock */ + CLKSEL0 &= ~(1 << RCE); + + /* Disable PLL */ + PLLCSR &= ~(1 << PLLE); + + /* Enable external clock */ + CLKSEL0 |= (1 << EXTE); + + /* wait for external clock to be ready */ + while ((CLKSTA & (1 << EXTON)) == 0) + ; + + /* select external clock */ + CLKSEL0 |= (1 << CLKS); + + /* Disable the clock prescaler */ + cli(); + CLKPR = (1 << CLKPCE); + CLKPR = 0; + sei(); + + /* Set up the PLL to use the crystal */ + + /* Use primary system clock as PLL source */ + PLLFRQ = ((0 << PINMUX) | /* Use primary clock */ + (0 << PLLUSB) | /* No divide by 2 for USB */ + (0 << PLLTM0) | /* Disable high speed timer */ + (0x4 << PDIV0)); /* 48MHz PLL clock */ + + /* Set the frequency of the crystal */ +#if TEENSY + PLLCSR |= (1 << PINDIV); /* For 16MHz crystal on Teensy board */ +#else + PLLCSR &= ~(1 << PINDIV); /* For 8MHz crystal on TeleScience board */ +#endif + + /* Enable the PLL */ + PLLCSR |= (1 << PLLE); + while (!(PLLCSR & (1 << PLOCK))) + ; +} + +void +uart_send(char data) +{ + while (!(UCSR1A & (1 << UDRE1))) + ; + UDR1 = data; +} + +void +uart_init(uint16_t baud) +{ + PRR1 &= ~(1 << PRUSART1); + UBRR1L = baud; + UBRR1H = baud >> 8; + UCSR1A = 0; + UCSR1B = ((1 << RXEN1) | /* Enable receiver */ + (1 << TXEN1)); /* Enable transmitter */ + UCSR1C = ((0 << UMSEL10) | /* Asynchronous mode */ + (0 << UPM10) | /* No parity */ + (0 << USBS1) | /* 1 stop bit */ + (3 << UCSZ10) | /* 8 bit characters */ + (0 << UCPOL1)); /* MBZ for async mode */ +} + +int main(void) +{ + clock_init(); + timer1_init(); + uart_init(832); + + LEDDDR |= (1 << LEDDDRPIN); + + for (;;) { + LEDPORT ^= (1 << LEDOUT); + uart_send('H'); + } +} -- 2.47.2