Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of lmic_MOTE_L152RC_2 by
TARGET_MOTE_L152RC/hal.cpp
- Committer:
- dudmuck
- Date:
- 2015-07-07
- Revision:
- 4:1a9a62cf220f
- Parent:
- 2:edb5d1f3deeb
- Child:
- 6:dfc048cda33f
File content as of revision 4:1a9a62cf220f:
/* HAL for MOTE_L152RC */ #include "mbed.h" #include "oslmic.h" #include "debug.h" #define RADIO_MOSI PB_15 #define RADIO_MISO PB_14 #define RADIO_SCLK PB_13 #define RADIO_NSS PB_12 #define RESET_PIN PC_2 #define RFSW1 PC_4 //NorAm_Mote RFSwitch_CNTR_1 #define RFSW2 PC_13 //NorAm_Mote RFSwitch_CNTR_2 static DigitalOut nss(RADIO_NSS); static SPI spi(RADIO_MOSI, RADIO_MISO, RADIO_SCLK); // (mosi, miso, sclk) static DigitalInOut rst(RESET_PIN); DigitalOut rfsw1(RFSW1); DigitalOut rfsw2(RFSW2); DigitalOut hdr_fem_ctx(PC_1); static InterruptIn dio0(PC_6); static InterruptIn dio1(PC_10); static InterruptIn dio2(PC_11); extern RTC_HandleTypeDef RtcHandle; // HAL state static struct { int irqlevel; } HAL; void radio_irq_handler (u1_t dio); static void dio0Irq( void ){ radio_irq_handler( 0 ); } static void dio1Irq( void ){ radio_irq_handler( 1 ); } static void dio2Irq( void ){ radio_irq_handler( 2 ); } void hal_disableIRQs() { __disable_irq(); HAL.irqlevel++; } void hal_enableIRQs() { if (--HAL.irqlevel == 0) { __enable_irq(); } } void hal_failed () { while (1) asm("nop"); } static void rtc_wkup_irq(void) { HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle); } void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc) { /* Clear Wake Up Flag */ __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); } /*void HAL_RCC_CCSCallback() { for (;;) asm("nop"); }*/ volatile uint32_t /*rcc_cr_a, rcc_cr_b,*/ rcc_cr_c; void hal_init (void) { memset(&HAL, 0x00, sizeof(HAL)); hal_disableIRQs(); #if USE_SMTC_RADIO_DRIVER #else // configure input lines dio0.mode(PullDown); dio0.rise(dio0Irq); dio0.enable_irq(); dio1.mode(PullDown); dio1.rise(dio1Irq); dio1.enable_irq(); dio2.mode(PullDown); dio2.rise(dio2Irq); dio2.enable_irq(); // configure reset line rst.input(); // configure spi spi.frequency(8000000); spi.format(8, 0); nss = 1; //RFSwitch_CNTR_2 = 1; #endif set_time(0); // initialize RTC /* Enable Ultra low power mode */ HAL_PWREx_EnableUltraLowPower(); /* Enable the fast wake up from Ultra low power mode */ HAL_PWREx_EnableFastWakeUp(); __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RtcHandle, RTC_FLAG_WUTF); NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)rtc_wkup_irq); NVIC_EnableIRQ(RTC_WKUP_IRQn); hdr_fem_ctx = 0; hal_enableIRQs(); GPIOA->MODER |= 0x01415500; // unused pins as outputs: PA4, PA5, PA6, PA7, PA8, (PA11,PA12 USB) GPIOB->MODER |= 0x00000401; // unused pins as outputs: PB0(HDR_DIO1), PB5 (PB10 pulled hi by LED), PB3-T_SWO GPIOC->MODER |= 0x00000041; // unused pins as outputs: PC0(HDR_FEM_CSD), PC3(SPI3_enable) } u4_t hal_ticks () { RTC_DateTypeDef dateStruct; RTC_TimeTypeDef timeStruct; struct tm timeinfo; uint16_t sub_seconds; RtcHandle.Instance = RTC; // Read actual date and time // Warning: the time must be read first! HAL_RTC_GetTime(&RtcHandle, &timeStruct, FORMAT_BIN); HAL_RTC_GetDate(&RtcHandle, &dateStruct, FORMAT_BIN); sub_seconds = 16384 - timeStruct.SubSeconds; // RTC_SSR counts down // Setup a tm structure based on the RTC timeinfo.tm_wday = dateStruct.WeekDay; timeinfo.tm_mon = dateStruct.Month - 1; timeinfo.tm_mday = dateStruct.Date; timeinfo.tm_year = dateStruct.Year + 100; timeinfo.tm_hour = timeStruct.Hours; timeinfo.tm_min = timeStruct.Minutes; timeinfo.tm_sec = timeStruct.Seconds; // Convert to timestamp time_t t = mktime(&timeinfo); // 14: SSR is driven at 16384Hz t <<= 14; return t | sub_seconds; } void hal_waitUntil (u4_t time) { while (hal_ticks() < time) asm("nop"); } volatile char deep_sleep; /* return 1 if target time is soon, return 0 if timer was programmed */ u1_t hal_checkTimer (u4_t time) { int d = time - hal_ticks(); HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle); __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RtcHandle, RTC_FLAG_WUTF); if (d < 0x10000) { // less than 4s deep_sleep = 0; if (d < 4) return 1; // very soon if (d > ms2osticks(100)) { d -= 13; // HSE_PLL startup time deep_sleep = 1; } // 61.035us steps HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, d, RTC_WAKEUPCLOCK_RTCCLK_DIV2); } else if (d < 0x20000) { // less than 8s d -= 6; // HSE_PLL startup time deep_sleep = 1; // 122us steps HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, d >> 1, RTC_WAKEUPCLOCK_RTCCLK_DIV4); } else if (d < 0x40000) { // less than 16s deep_sleep = 1; // 244us steps HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, d >> 2, RTC_WAKEUPCLOCK_RTCCLK_DIV8); } else if (d < 0x80000) { // less than 32s deep_sleep = 1; // 488us steps HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, d >> 3, RTC_WAKEUPCLOCK_RTCCLK_DIV16); } else { deep_sleep = 1; // 1s steps to 18hours HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, d >> 14, RTC_WAKEUPCLOCK_CK_SPRE_16BITS); /* RTC_WAKEUPCLOCK_CK_SPRE_17BITS: 18h to 36h */ /*for (;;) asm("nop");*/ } return 0; } //#define SLEEP_DEBUG 1 void hal_sleep () { #ifdef SLEEP_DEBUG u4_t start_tick, end_tick; volatile uint32_t time_asleep; #endif /* SLEEP_DEBUG */ #ifdef USE_DEBUGGER HAL_EnableDBGStopMode(); if (!DBGMCU->CR & DBGMCU_CR_DBG_STOP) for (;;) asm("nop"); #endif /* USE_DEBUGGER */ //printf("%x cr:%06x isr:%04x %d\r\n", RtcHandle.Instance->WUTR, RtcHandle.Instance->CR, RtcHandle.Instance->ISR, deep_sleep); //debug_done(); if (deep_sleep) debug_done(); // wait here if debug still printing if (__HAL_RTC_WAKEUPTIMER_GET_FLAG(&RtcHandle, RTC_FLAG_WUTF) == 0) { // set gpio for sleep #ifdef SLEEP_DEBUG start_tick = hal_ticks(); #endif /* SLEEP_DEBUG */ //hdr_fem_ctx = 1; if (deep_sleep) { #ifndef USE_DEBUGGER /* PA13 to undriven JTMS/SWDIO pin (from AF0 to GPIO), and PA2 */ GPIOA->MODER &= 0xf7ffffdf; GPIOB->MODER &= 0xffffdfff; // PB6 UART_TX to input #endif deepsleep(); // blocks until waking #ifndef USE_DEBUGGER /* PA13 back to JTMS/SWDIO pin (from GPIO to AF0), and PA2 */ GPIOA->MODER |= 0x08000020; GPIOB->MODER |= 0x00002000; // PB6 input to UART_TX #endif } else sleep(); // blocks until waking //hdr_fem_ctx = 0; #ifdef SLEEP_DEBUG end_tick = hal_ticks(); time_asleep = end_tick - start_tick; printf("%u = %u - %u\r\n", time_asleep, end_tick, start_tick); #endif /* SLEEP_DEBUG */ // restore gpio from sleep } } void hal_pin_nss (u1_t val) { nss = val; } u1_t hal_spi (u1_t out) { return spi.write(out); } // 0=RX 1=TX /*void hal_pin_rxtx (u1_t val) { rxtx = !val; }*/ #define OPMODE_LORA 0x80 #define OPMODE_MASK 0x07 #define OPMODE_SLEEP 0x00 #define OPMODE_STANDBY 0x01 #define OPMODE_FSTX 0x02 #define OPMODE_TX 0x03 #define OPMODE_FSRX 0x04 #define OPMODE_RX 0x05 #define OPMODE_RX_SINGLE 0x06 #define OPMODE_CAD 0x07 void hal_opmode(u1_t mode, u1_t pa_boost) { if (mode == OPMODE_TX) { // start of transmission if (pa_boost) { rfsw2 = 0; rfsw1 = 1; } else { rfsw2 = 1; rfsw1 = 0; } //hdr_fem_ctx = 0; // debug } else if (mode == OPMODE_RX || mode == OPMODE_RX_SINGLE || mode == OPMODE_CAD) { // start of reception rfsw2 = 1; rfsw1 = 1; //hdr_fem_ctx = 1; // debug } else { // RF switch shutdown rfsw2 = 0; rfsw1 = 0; //hdr_fem_ctx = 0; // debug } } void hal_pin_rst (u1_t val) { if (val == 0 || val == 1) { // drive pin rst.output(); rst = val; } else { // keep pin floating rst.input(); } }