board_rzusb.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * fw/board_rzusb.c - RZUSB Board-specific functions (for boot loader and application)
  3. *
  4. * Written 2016 by Stefan Schmidt
  5. * Copyright 2016 Stefan Schmidt
  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. #include <stdbool.h>
  13. #include <stdint.h>
  14. #include <avr/io.h>
  15. #include <avr/interrupt.h>
  16. #include <avr/boot.h>
  17. #define F_CPU 8000000UL
  18. #include <util/delay.h>
  19. #include "usb.h"
  20. #include "at86rf230.h"
  21. #include "board.h"
  22. #include "spi.h"
  23. #include "usb/usb.h"
  24. static bool spi_initialized = 0;
  25. void reset_rf(void)
  26. {
  27. /* set up all the outputs; default port value is 0 */
  28. DDRB = 0;
  29. DDRC = 0;
  30. DDRD = 0;
  31. PORTB = 0;
  32. PORTC = 0;
  33. PORTD = 0;
  34. OUT(LED);
  35. OUT(nRST_RF); /* this also resets the transceiver */
  36. OUT(SLP_TR);
  37. spi_init();
  38. /* AT86RF231 data sheet, 12.4.13, reset pulse width: 625 ns (min) */
  39. CLR(nRST_RF);
  40. _delay_us(2);
  41. SET(nRST_RF);
  42. /* 12.4.14: SPI access latency after reset: 625 ns (min) */
  43. _delay_us(2);
  44. /* we must restore TRX_CTRL_0 after each reset (9.6.4) */
  45. set_clkm();
  46. }
  47. void led(bool on)
  48. {
  49. if (on)
  50. SET(LED);
  51. else
  52. CLR(LED);
  53. }
  54. void set_clkm(void)
  55. {
  56. /* switch CLKM to 8 MHz */
  57. /*
  58. * @@@ Note: Atmel advise against changing the external clock in
  59. * mid-flight. We should therefore switch to the RC clock first, then
  60. * crank up the external clock, and finally switch back to the external
  61. * clock. The clock switching procedure is described in the ATmega32U2
  62. * data sheet in secton 8.2.2.
  63. */
  64. spi_begin();
  65. spi_send(AT86RF230_REG_WRITE | REG_TRX_CTRL_0);
  66. spi_send(0x10);
  67. spi_end();
  68. /* TX_AUTO_CRC_ON, default disabled */
  69. spi_begin();
  70. spi_send(AT86RF230_REG_WRITE | 0x05);
  71. spi_send(0x80);
  72. spi_end();
  73. }
  74. void board_init(void)
  75. {
  76. /* Disable the watchdog timer */
  77. MCUSR = 0; /* Remove override */
  78. WDTCSR |= 1 << WDCE; /* Enable change */
  79. WDTCSR = 1 << WDCE; /* Disable watchdog while still enabling
  80. change */
  81. CLKPR = 1 << CLKPCE;
  82. /* We start with a 16 MHz/8 clock. Put the prescaler to 2. */
  83. CLKPR = 1 << CLKPS0;
  84. get_sernum();
  85. }
  86. void spi_begin(void)
  87. {
  88. if (!spi_initialized)
  89. spi_init();
  90. CLR(nSS);
  91. }
  92. void spi_off(void)
  93. {
  94. spi_initialized = 0;
  95. SPCR &= ~(1 << SPE);
  96. }
  97. void spi_init(void)
  98. {
  99. SET(nSS);
  100. OUT(SCLK);
  101. OUT(MOSI);
  102. OUT(nSS);
  103. IN(MISO);
  104. SPCR = (1 << SPE) | (1 << MSTR);
  105. SPSR = (1 << SPI2X);
  106. spi_initialized = 1;
  107. }
  108. void usb_init(void)
  109. {
  110. USBCON |= 1 << FRZCLK; /* freeze the clock */
  111. /* enable the PLL and wait for it to lock */
  112. /* TODO sheet page 50 For Atmel AT90USB128x only. Do not use with Atmel AT90USB64x. */
  113. /* FOR 8 XTAL Mhz only!!! */
  114. PLLCSR = ((1 << PLLP1) | (1 << PLLP0));
  115. PLLCSR |= 1 << PLLE;
  116. while (!(PLLCSR & (1 << PLOCK)));
  117. UHWCON |= (1 << UVREGE);
  118. USBCON &= ~((1 << USBE) | (1 << OTGPADE)); /* reset the controller */
  119. USBCON |= ((1 << USBE) | (1 << OTGPADE));
  120. USBCON &= ~(1 << FRZCLK); /* thaw the clock */
  121. UDCON &= ~(1 << DETACH); /* attach the pull-up */
  122. UDIEN = 1 << EORSTE; /* enable device interrupts */
  123. // UDCON |= 1 << RSTCPU; /* reset CPU on bus reset */
  124. ep_init();
  125. }
  126. void board_app_init(void)
  127. {
  128. /* enable timer input capture 1, trigger on rising edge */
  129. TCCR1B = (1 << ICES1);
  130. TIFR1 = (1 << ICF1);
  131. TIMSK1 = (1 << ICIE1);
  132. }