1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00
RIOT/pkg/openwsn/patches/radiotimer.c.patch
2014-05-14 15:06:50 +02:00

241 lines
7.7 KiB
Diff

*** stock_iot-lab_M3/openwsn/radiotimer.c Thu Apr 24 11:19:40 2014
--- riot-openwsn-wip/openwsn/radiotimer.c Thu Apr 24 16:55:54 2014
***************
*** 0 ****
--- 1,235 ----
+ /**
+ \brief openmoteSTM32 definition of the "radiotimer" bsp module.
+
+ On openmoteSTM32, we use RTC for the radiotimer module.
+
+ \author Thomas Watteyne <watteyne@eecs.berkeley.edu>, February 2012.
+ \author Chang Tengfei <tengfei.chang@gmail.com>, July 2012.
+ */
+
+ #include "stdint.h"
+
+ #include "stm32f10x_lib.h"
+ #include "leds_ow.h"
+ #include "radiotimer.h"
+ #include "board_info.h"
+
+ #include "rcc.h"
+ #include "nvic.h"
+
+ #define ENABLE_DEBUG (0)
+ #include "debug.h"
+
+
+ //=========================== variables =======================================
+
+ enum radiotimer_irqstatus_enum{
+ RADIOTIMER_NONE = 0x00, //alarm interrupt default status
+ RADIOTIMER_OVERFLOW = 0x01, //alarm interrupt caused by overflow
+ RADIOTIMER_COMPARE = 0x02, //alarm interrupt caused by compare
+ };
+
+ typedef struct {
+ radiotimer_compare_cbt overflow_cb;
+ radiotimer_compare_cbt compare_cb;
+ uint8_t overflowORcompare;//indicate RTC alarm interrupt status
+ uint16_t currentSlotPeriod;
+ } radiotimer_vars_t;
+
+ volatile radiotimer_vars_t radiotimer_vars;
+
+ //=========================== prototypes ======================================
+
+ //=========================== public ==========================================
+
+ //===== admin
+
+ void radiotimer_init() {
+ // clear local variables
+ memset((void*)&radiotimer_vars,0,sizeof(radiotimer_vars_t));
+ }
+
+ void radiotimer_setOverflowCb(radiotimer_compare_cbt cb) {
+ radiotimer_vars.overflow_cb = cb;
+ }
+
+ void radiotimer_setCompareCb(radiotimer_compare_cbt cb) {
+ radiotimer_vars.compare_cb = cb;
+ }
+
+ void radiotimer_setStartFrameCb(radiotimer_capture_cbt cb) {
+ while(1);
+ }
+
+ void radiotimer_setEndFrameCb(radiotimer_capture_cbt cb) {
+ while(1);
+ }
+
+ void radiotimer_start(uint16_t period) {
+ //enable BKP and PWR, Clock
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP|RCC_APB1Periph_PWR , ENABLE);
+
+ // RTC clock source configuration
+ PWR_BackupAccessCmd(ENABLE); //Allow access to BKP Domain
+ RCC_LSEConfig(RCC_LSE_ON); //Enable LSE OSC
+ while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET); //Wait till LSE is ready
+ RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //Select the RTC Clock Source
+ RCC_RTCCLKCmd(ENABLE); //enable RTC
+
+ // RTC configuration
+ // Wait for RTC APB registers synchronisation
+ RTC_WaitForSynchro();
+
+ RTC_SetPrescaler(1); //use 16KHz clock
+ RTC_WaitForLastTask(); //Wait until last write operation on RTC registers has finished
+
+ //Set the RTC time counter to 0
+ RTC_SetCounter(0);
+ RTC_WaitForLastTask();
+
+ // Set the RTC time alarm(the length of slot)
+ RTC_SetAlarm(period);
+ RTC_WaitForLastTask();
+
+ radiotimer_vars.currentSlotPeriod = period;
+
+ //interrupt when reach alarm value
+ RTC_ClearFlag(RTC_IT_ALR);
+ RTC_ITConfig(RTC_IT_ALR, ENABLE);
+
+ //set radiotimer irpstatus
+ radiotimer_vars.overflowORcompare = RADIOTIMER_OVERFLOW;
+
+ //Configures EXTI line 17 to generate an interrupt on rising edge(alarm interrupt to wakeup board)
+ EXTI_ClearITPendingBit(EXTI_Line17);
+ EXTI_InitTypeDef EXTI_InitStructure;
+ EXTI_InitStructure.EXTI_Line = EXTI_Line17;
+ EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
+ EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
+ EXTI_InitStructure.EXTI_LineCmd = ENABLE;
+ EXTI_Init(&EXTI_InitStructure);
+
+ //Configure RTC Alarm interrupt:
+ //Configure NVIC: Preemption Priority = 1 and Sub Priority = 0
+ NVIC_InitTypeDef NVIC_InitStructure;
+ NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;
+ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
+ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
+ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+ NVIC_Init(&NVIC_InitStructure);
+ }
+
+ //===== direct access
+
+ uint16_t radiotimer_getValue() {
+ RTC_WaitForSynchro();
+ uint32_t counter = RTC_GetCounter();
+ return (uint16_t)counter;
+ }
+
+ void radiotimer_setPeriod(uint16_t period) {
+
+ RTC_ITConfig(RTC_IT_ALR, DISABLE);
+ //need to disable radio also in case that a radio interrupt is happening when set Alarm value
+
+
+ //Reset RTC Counter to begin a new slot
+ RTC_SetAlarm(period);
+ RTC_WaitForLastTask();
+
+ radiotimer_vars.currentSlotPeriod = period;
+
+ //set radiotimer irpstatus
+ radiotimer_vars.overflowORcompare = RADIOTIMER_OVERFLOW;
+ RTC_ClearFlag(RTC_IT_ALR);
+ RTC_ITConfig(RTC_IT_ALR, ENABLE);
+ }
+
+ extern uint32_t RTC_GetAlarm(void);
+ uint16_t radiotimer_getPeriod() {
+ RTC_WaitForSynchro();
+ uint32_t period = RTC_GetAlarm();
+ return (uint16_t)period;
+ }
+
+ //===== compare
+
+ void radiotimer_schedule(uint16_t offset) {
+ RTC_ITConfig(RTC_IT_ALR, DISABLE);
+ //need to disable radio also in case that a radio interrupt is happening
+
+ // Set the RTC alarm(RTC timer will alarm at next state of slot)
+ RTC_SetAlarm(offset);
+ RTC_WaitForLastTask();
+
+ //set radiotimer irpstatus
+ radiotimer_vars.overflowORcompare = RADIOTIMER_COMPARE;
+ RTC_ClearFlag(RTC_IT_ALR);
+ RTC_ITConfig(RTC_IT_ALR, ENABLE);
+ }
+
+ void radiotimer_cancel() {
+ RTC_ITConfig(RTC_IT_ALR, DISABLE);
+ //need to disable radio also in case that a radio interrupt is happening
+
+
+ // set RTC alarm (slotlength)
+ RTC_SetAlarm(radiotimer_vars.currentSlotPeriod);
+ RTC_WaitForLastTask();
+
+ //set radiotimer irpstatus
+ radiotimer_vars.overflowORcompare = RADIOTIMER_OVERFLOW;
+ RTC_ClearFlag(RTC_IT_ALR);
+ RTC_ITConfig(RTC_IT_ALR, ENABLE);
+ }
+
+ //===== capture
+
+ inline uint16_t radiotimer_getCapturedTime() {
+ RTC_WaitForSynchro();
+ uint32_t counter = RTC_GetCounter();
+ return (uint16_t)counter;
+ }
+
+ //=========================== private =========================================
+
+ //=========================== interrupt handlers ==============================
+
+ kick_scheduler_t radiotimer_isr() {
+ uint8_t taiv_temp = radiotimer_vars.overflowORcompare;
+ switch (taiv_temp) {
+ case RADIOTIMER_COMPARE:
+ DEBUG("%s cmp\n", __PRETTY_FUNCTION__);
+ if (radiotimer_vars.compare_cb!=NULL) {
+ RCC_Wakeup();
+ // call the callback
+ radiotimer_vars.compare_cb();
+ // kick the OS
+ return KICK_SCHEDULER;
+ }
+ break;
+ case RADIOTIMER_OVERFLOW: // timer overflows
+ DEBUG("%s of\n", __PRETTY_FUNCTION__);
+ if (radiotimer_vars.overflow_cb!=NULL) {
+
+ //Wait until last write operation on RTC registers has finished
+ RTC_WaitForLastTask();
+
+ //Set the RTC time counter to 0
+ RTC_SetCounter(0xffffffff);
+ RTC_WaitForLastTask();
+ RCC_Wakeup();
+ // call the callback
+ radiotimer_vars.overflow_cb();
+ DEBUG("returned...\n");
+ // kick the OS
+ return KICK_SCHEDULER;
+ }
+ break;
+ case RADIOTIMER_NONE: // this should not happen
+ DEBUG("%s none\n", __PRETTY_FUNCTION__);
+ default:
+ while(1); // this should not happen
+ }
+ return DO_NOT_KICK_SCHEDULER;
+ }