Root/atusb/fw/board.c

1/*
2 * fw/board.c - Board-specific functions (for boot loader and application)
3 *
4 * Written 2011, 2013 by Werner Almesberger
5 * Copyright 2011, 2013 Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include <stdbool.h>
15#include <stdint.h>
16
17#include <avr/io.h>
18#include <avr/interrupt.h>
19#include <avr/boot.h>
20
21#define F_CPU 8000000UL
22#include <util/delay.h>
23
24#include "usb.h"
25#include "at86rf230.h"
26#include "board.h"
27#include "spi.h"
28
29
30uint8_t board_sernum[42] = { 42, USB_DT_STRING };
31
32
33static void set_clkm(void)
34{
35    /* switch CLKM to 8 MHz */
36
37    /*
38     * @@@ Note: Atmel advise against changing the external clock in
39     * mid-flight. We should therefore switch to the RC clock first, then
40     * crank up the external clock, and finally switch back to the external
41     * clock. The clock switching procedure is described in the ATmega32U2
42     * data sheet in secton 8.2.2.
43     */
44
45    spi_begin();
46    spi_send(AT86RF230_REG_WRITE | REG_TRX_CTRL_0);
47    spi_send(CLKM_CTRL_8MHz);
48    spi_end();
49}
50
51
52void reset_rf(void)
53{
54    /* set up all the outputs; default port value is 0 */
55
56    DDRB = 0;
57    DDRC = 0;
58    DDRD = 0;
59    PORTB = 0;
60    PORTC = 0;
61    PORTD = 0;
62
63    OUT(LED);
64    OUT(nRST_RF); /* this also resets the transceiver */
65    OUT(SLP_TR);
66
67    spi_init();
68
69    /* AT86RF231 data sheet, 12.4.13, reset pulse width: 625 ns (min) */
70
71    CLR(nRST_RF);
72    _delay_us(2);
73    SET(nRST_RF);
74
75    /* 12.4.14: SPI access latency after reset: 625 ns (min) */
76
77    _delay_us(2);
78
79    /* we must restore TRX_CTRL_0 after each reset (9.6.4) */
80
81    set_clkm();
82}
83
84
85void led(bool on)
86{
87    if (on)
88        SET(LED);
89    else
90        CLR(LED);
91}
92
93
94void panic(void)
95{
96    cli();
97    while (1) {
98        SET(LED);
99        _delay_ms(100);
100        CLR(LED);
101        _delay_ms(100);
102    }
103}
104
105
106static char hex(uint8_t nibble)
107{
108    return nibble < 10 ? '0'+nibble : 'a'+nibble-10;
109}
110
111
112static void get_sernum(void)
113{
114    uint8_t sig;
115    uint8_t i;
116
117    for (i = 0; i != 10; i++) {
118        sig = boot_signature_byte_get(i+0xe);
119        board_sernum[(i << 2)+2] = hex(sig >> 4);
120        board_sernum[(i << 2)+4] = hex(sig & 0xf);
121    }
122}
123
124
125void board_init(void)
126{
127    /* Disable the watchdog timer */
128
129    MCUSR = 0; /* Remove override */
130    WDTCSR |= 1 << WDCE; /* Enable change */
131    WDTCSR = 1 << WDCE; /* Disable watchdog while still enabling
132                   change */
133
134    /* We start with a 1 MHz/8 clock. Disable the prescaler. */
135
136    CLKPR = 1 << CLKPCE;
137    CLKPR = 0;
138
139    get_sernum();
140}
141

Archive Download this file



interactive