/*************************************************************************** * Copyright (C) 01/2008 by Olaf Rempel * * razzor@kopf-tisch.de * * * * 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 "AT91SAM7S256.h" #include "at91_pitc.h" #include "at91_sysc.h" #include "board.h" /* PIV is 20bit -> min. 3Hz @48MHz MCK */ #define HZ_TO_PIV(HZ) (MCK / (16 * HZ)) static LIST_HEAD(timer_list); volatile static uint32_t pitc_ticks; void pitc_schedule_timer(struct pitc_timer *timer) { timer->nextrun = timer->interval + pitc_ticks; struct pitc_timer *search; list_for_each_entry(search, &timer_list, list) if (search->nextrun > timer->nextrun) break; list_add_tail(&timer->list, &search->list); } static void pitc_isr(uint32_t status) { /* get Ticks and clear interrupt */ pitc_ticks += (*AT91C_PITC_PIVR & AT91C_PITC_PICNT) >> 20; struct pitc_timer *search, *tmp; list_for_each_entry_safe(search, tmp, &timer_list, list) { /* if this entry not scheduled yet, abort search */ if (pitc_ticks < search->nextrun) break; /* remove from list */ list_del(&search->list); /* exec handler */ if (search->func(search) == PITC_REMOVE_TIMER) { /* one-shot timer, mark as completed */ search->nextrun = 0x00; continue; } /* interval timer, reschedule it */ pitc_schedule_timer(search); } } uint32_t pitc_get_ticks(void) { return pitc_ticks; } void at91_pitc_init(void) { sysc_register_isr(AT91_SYSIRQ_PIT, &pitc_isr); *AT91C_PITC_PIMR = (AT91C_PITC_PIV & HZ_TO_PIV(1000)) | AT91C_PITC_PITEN | AT91C_PITC_PITIEN; }