ARM7 based quadrocopter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
3.4KB

  1. /***************************************************************************
  2. * sam7fc - Periodic Timer Handling *
  3. * *
  4. * Copyright (C) 01/2008 by Olaf Rempel *
  5. * razzor@kopf-tisch.de *
  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; version 2 of the License *
  10. * *
  11. * This program is distributed in the hope that it will be useful, *
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  14. * GNU General Public License for more details. *
  15. * *
  16. * You should have received a copy of the GNU General Public License *
  17. * along with this program; if not, write to the *
  18. * Free Software Foundation, Inc., *
  19. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  20. ***************************************************************************/
  21. #include "AT91SAM7S256.h"
  22. #include "at91_pitc.h"
  23. #include "at91_sysc.h"
  24. #include "board.h"
  25. #define PITC_HZ 1000
  26. /* PIV is 20bit -> min. 3Hz @48MHz MCK */
  27. #define HZ_TO_PIV(HZ) (MCK / (16 * HZ))
  28. static LIST_HEAD(timer_list);
  29. volatile static uint32_t pitc_ticks;
  30. static void _pitc_schedule_timer(struct pitc_timer *timer)
  31. {
  32. timer->nextrun = timer->interval + pitc_ticks;
  33. struct pitc_timer *search;
  34. list_for_each_entry(search, &timer_list, list)
  35. if (search->nextrun > timer->nextrun)
  36. break;
  37. list_add_tail(&timer->list, &search->list);
  38. }
  39. void pitc_schedule_timer(struct pitc_timer *timer)
  40. {
  41. /* disable PITC interrupt */
  42. *AT91C_PITC_PIMR &= ~AT91C_PITC_PITIEN;
  43. /* check it timer is already running */
  44. if (timer->nextrun == 0 && timer->interval > 0)
  45. _pitc_schedule_timer(timer);
  46. // TODO: if timer is running, interval changes are delayed
  47. /* enable PITC interrupt */
  48. *AT91C_PITC_PIMR |= AT91C_PITC_PITIEN;
  49. }
  50. void pitc_remove_timer(struct pitc_timer *timer)
  51. {
  52. timer->interval = 0;
  53. }
  54. static void pitc_isr(uint32_t status)
  55. {
  56. /* get Ticks and clear interrupt */
  57. pitc_ticks += (*AT91C_PITC_PIVR & AT91C_PITC_PICNT) >> 20;
  58. struct pitc_timer *search, *tmp;
  59. list_for_each_entry_safe(search, tmp, &timer_list, list) {
  60. /* if this entry not scheduled yet, abort search */
  61. if (pitc_ticks < search->nextrun)
  62. break;
  63. /* remove from list */
  64. list_del(&search->list);
  65. /* exec handler */
  66. if ((search->interval == 0) || search->func(search) == PITC_REMOVE_TIMER) {
  67. /* one-shot timer, mark as completed */
  68. search->nextrun = 0;
  69. continue;
  70. }
  71. /* interval timer, reschedule it */
  72. _pitc_schedule_timer(search);
  73. }
  74. }
  75. uint32_t pitc_get_ticks(void)
  76. {
  77. return pitc_ticks;
  78. }
  79. void at91_pitc_init(void)
  80. {
  81. sysc_register_isr(AT91_SYSIRQ_PIT, &pitc_isr);
  82. *AT91C_PITC_PIMR = (AT91C_PITC_PIV & HZ_TO_PIV(PITC_HZ)) |
  83. AT91C_PITC_PITEN |
  84. AT91C_PITC_PITIEN;
  85. }