Sara Ojeda / Mbed 2 deprecated prueba_hsens

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Clock.cpp Source File

Clock.cpp

00001 #include "Clock.h"
00002 #include "Log.h"
00003 #include "rtc_api.h"
00004 
00005 extern Log _;
00006 
00007 Clock* Clock::getInstance()
00008 {
00009     static Clock* instance = new Clock();
00010     return instance;
00011 }
00012 
00013 //para conseguir un ss de frecuencia mayor a 1ms
00014 //#define PREDIV_A 0x1F
00015 //#define PREDIV_S 0x3FF
00016 
00017 //valores por defecto
00018 #define PREDIV_A (0x7FUL)
00019 #define PREDIV_S (0xFFUL)
00020 
00021 
00022 Clock::Clock()
00023 {
00024     WakeUp::attach(HAL_PWR_DisableSleepOnExit);
00025 
00026     this->hibernate = false;
00027 }
00028 
00029 time_t Clock::getUnixTime()
00030 {
00031     return time(NULL);
00032 }
00033 
00034 uint32_t Clock::getMilliSeconds()
00035 {
00036 
00037     uint32_t intentos = 0;
00038     PWR->CR |= PWR_CR_DBP;
00039     while(((RTC->ISR & RTC_ISR_RSF) != 0) &&  intentos < 20){
00040         RTC->WPR = 0xCA;
00041         RTC->WPR = 0x53;
00042 
00043         RTC->ISR &=  ~RTC_ISR_RSF;
00044 
00045         intentos++;
00046     }
00047     if(intentos == 20){
00048         mbed_die();
00049     }
00050     intentos = 0;
00051 
00052     while(((RTC->ISR & RTC_ISR_RSF) == 0) &&  intentos < 2000) {
00053         intentos++;
00054     }
00055     if(intentos == 2000){
00056         mbed_die();
00057     }
00058 
00059 
00060     uint32_t ss = RTC->SSR;
00061     uint32_t tr = RTC->TR;
00062     uint32_t dr = RTC->DR;
00063 
00064     uint32_t milliseconds = ((tr>>12) & 0x7 ) * 600000  + ((tr>>8) & 0xF ) * 60000  + ((tr>>4) & 0x7) * 10000 + ((tr) & 0xF)*1000 + ((this->prediv_s - ss) * 1000) / (this->prediv_s + 1);
00065     return milliseconds;
00066 }
00067 
00068 const struct tm* Clock::getTmStruct()
00069 {
00070     time_t seconds = time(NULL);
00071     return localtime(&seconds);
00072 }
00073 
00074 const string Clock::getTimeAsAString()
00075 {
00076     time_t seconds = time(NULL);
00077     string str = ctime(&seconds);
00078     str.erase(str.size() - 1);// remove \n
00079     return str;
00080 }
00081 
00082 void Clock::updateUnixTime(time_t unixTime)
00083 {
00084     set_time(unixTime);
00085 }
00086 
00087 void Clock::programAlarm(uint32_t seconds)
00088 {
00089     // Clear Wakeup flag
00090     if (PWR->CSR & PWR_CSR_WUF) {
00091         PWR->CR |= PWR_CR_CWUF;
00092     }
00093 
00094     // Enable write access to RTC registers
00095     if (!(PWR->CR & PWR_CR_DBP)) {
00096         PWR->CR |= PWR_CR_DBP;
00097     }
00098 
00099     WakeUp::set(seconds);
00100 
00101     PWR->CR &= ~(PWR_CR_DBP);
00102 }
00103 
00104 void Clock::goToSleep() {
00105     uint32_t tmpreg = 0U;
00106     this->hibernate = true;
00107     /* Select the regulator state in Stop mode ---------------------------------*/
00108     tmpreg = PWR->CR;
00109 
00110     /* Clear PDDS and LPDS bits */
00111     CLEAR_BIT(tmpreg, (PWR_CR_PDDS | PWR_CR_LPSDSR));
00112 
00113     /* Set LPSDSR active to the converter run in low power mode */
00114     SET_BIT(tmpreg, PWR_CR_LPSDSR);
00115 
00116     /* Set ULP active ultra low power, this desative Vref regulated */
00117     SET_BIT(tmpreg, PWR_CR_ULP);
00118 
00119 
00120     /* Store the new value */
00121     PWR->CR = tmpreg;
00122 
00123     /* Set SLEEPDEEP bit of Cortex System Control Register */
00124     SET_BIT(SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
00125 
00126     /* Enable sleep on exit */
00127     HAL_PWR_EnableSleepOnExit();
00128 
00129     /* Request Wait For Interrupt */
00130     __WFI();
00131 
00132     /* Reset SLEEPDEEP bit of Cortex System Control Register */
00133     CLEAR_BIT(SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
00134 }
00135 
00136 void Clock::resetClockRegisters()
00137 {
00138     RCC->CR |= (uint32_t)0x00000100;
00139 
00140     /*!< Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], MCOSEL[2:0] and MCOPRE[2:0] bits */
00141     RCC->CFGR &= (uint32_t) 0x88FF400C;
00142 
00143     /*!< Reset HSION, HSIDIVEN, HSEON, CSSON and PLLON bits */
00144     RCC->CR &= (uint32_t)0xFEF6FFF6;
00145 
00146     /*!< Reset HSI48ON  bit */
00147     RCC->CRRCR &= (uint32_t)0xFFFFFFFE;
00148 
00149     /*!< Reset HSEBYP bit */
00150     RCC->CR &= (uint32_t)0xFFFBFFFF;
00151 
00152     /*!< Reset PLLSRC, PLLMUL[3:0] and PLLDIV[1:0] bits */
00153     RCC->CFGR &= (uint32_t)0xFF02FFFF;
00154 
00155     /*!< Disable all interrupts */
00156     RCC->CIER = 0x00000000;
00157 }
00158 
00159 void Clock::initClock()
00160 {
00161     resetClockRegisters();
00162     /* 1- If fail try to start with HSE and external xtal */
00163     if (SetSysClock_PLL_HSE(0) == 0)
00164     {
00165         /* 2- If fail start with HSI clock */
00166         if (SetSysClock_PLL_HSI() == 0)
00167         {
00168             mbed_die();
00169         }
00170     }
00171 
00172     if(!rtc_isenabled()) {
00173             rtc_init();
00174      }
00175 
00176     this->prediv_s = RTC->PRER & 0x00007FFF;
00177 
00178     uint32_t intentos = 0;
00179     PWR->CR |= PWR_CR_DBP;
00180     do {
00181         RTC->WPR = 0xCA;
00182         RTC->WPR = 0x53;
00183         RTC->ISR &=  ~RTC_ISR_RSF;
00184         intentos++;
00185     } while (((RTC->ISR & RTC_ISR_RSF) != 0) &&  intentos < 20);
00186     if(intentos == 20){
00187         mbed_die();
00188     }
00189     intentos = 0;
00190     while(((RTC->ISR & RTC_ISR_RSF) == 0) &&  intentos < 2000) {
00191         intentos++;
00192     }
00193     if(intentos == 2000){
00194         mbed_die();
00195     }
00196 
00197     this->hibernate = false;
00198 }
00199 
00200 uint8_t Clock::SetSysClock_PLL_HSE(uint8_t bypass)
00201 {
00202     RCC_ClkInitTypeDef RCC_ClkInitStruct;
00203     RCC_OscInitTypeDef RCC_OscInitStruct;
00204 
00205     /* Used to gain time after DeepSleep in case HSI is used */
00206     if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != RESET) {
00207         return 0;
00208     }
00209 
00210     /* The voltage scaling allows optimizing the power consumption when the device is
00211        clocked below the maximum system frequency, to update the voltage scaling value
00212        regarding system frequency refer to product datasheet. */
00213     __PWR_CLK_ENABLE();
00214     __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
00215 
00216     /* Enable HSE and  activate PLL with HSE as source */
00217     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
00218     if (bypass == 0) {
00219         RCC_OscInitStruct.HSEState          = RCC_HSE_ON; /* External 8 MHz xtal on OSC_IN/OSC_OUT */
00220     } else {
00221         RCC_OscInitStruct.HSEState          = RCC_HSE_BYPASS; /* External 8 MHz clock on OSC_IN */
00222     }
00223     RCC_OscInitStruct.HSIState            = RCC_HSI_OFF;
00224     RCC_OscInitStruct.HSI48State          = RCC_HSI48_OFF; /* For USB and RNG clock */
00225     // PLLCLK = (8 MHz * 8)/2 = 32 MHz
00226     RCC_OscInitStruct.PLL.PLLState        = RCC_PLL_ON;
00227     RCC_OscInitStruct.PLL.PLLSource       = RCC_PLLSOURCE_HSE;
00228     RCC_OscInitStruct.PLL.PLLMUL          = RCC_PLLMUL_8;
00229     RCC_OscInitStruct.PLL.PLLDIV          = RCC_PLLDIV_2;
00230     if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
00231         return 0; // FAIL
00232     }
00233 
00234     /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
00235     RCC_ClkInitStruct.ClockType      = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
00236     RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_PLLCLK; // 32 MHz
00237     RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV1;         // 32 MHz
00238     RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;           // 32 MHz
00239     RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;           // 32 MHz
00240     if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
00241         return 0; // FAIL
00242     }
00243 
00244     return 1; // OK
00245 }
00246 
00247 uint8_t Clock::SetSysClock_PLL_HSI(void)
00248 {
00249     RCC_ClkInitTypeDef RCC_ClkInitStruct;
00250     RCC_OscInitTypeDef RCC_OscInitStruct;
00251 
00252     /* The voltage scaling allows optimizing the power consumption when the device is
00253        clocked below the maximum system frequency, to update the voltage scaling value
00254        regarding system frequency refer to product datasheet. */
00255     __PWR_CLK_ENABLE();
00256     __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
00257 
00258     /* Enable HSI oscillators and activate PLL with HSI as source */
00259     RCC_OscInitStruct.OscillatorType      = RCC_OSCILLATORTYPE_HSI;
00260     RCC_OscInitStruct.HSEState            = RCC_HSE_OFF;
00261     RCC_OscInitStruct.HSIState            = RCC_HSI_ON;
00262     RCC_OscInitStruct.HSICalibrationValue = 16;
00263     RCC_OscInitStruct.HSI48State          = RCC_HSI48_ON; /* For USB and RNG clock */
00264     // PLLCLK = (16 MHz * 4)/2 = 32 MHz
00265     RCC_OscInitStruct.PLL.PLLState        = RCC_PLL_ON;
00266     RCC_OscInitStruct.PLL.PLLSource       = RCC_PLLSOURCE_HSI;
00267     RCC_OscInitStruct.PLL.PLLMUL          = RCC_PLLMUL_4;
00268     RCC_OscInitStruct.PLL.PLLDIV          = RCC_PLLDIV_2;
00269     if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
00270         return 0; // FAIL
00271     }
00272 
00273     /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
00274     RCC_ClkInitStruct.ClockType      = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
00275     RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_PLLCLK; // 32 MHz
00276     RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV1;         // 32 MHz
00277     RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;           // 32 MHz
00278     RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;           // 32 MHz
00279     if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
00280         return 0; // FAIL
00281     }
00282     return 1; // OK
00283 }
00284 
00285 uint8_t Clock::SetSysClock_MSI(){
00286 
00287     uint8_t intentos = 0;
00288 
00289    //asegurarme que MSI este desabilitado
00290 
00291    if((RCC->CR & RCC_CR_MSION) != 0) {
00292        //esta habilitado
00293        RCC->CR &= ~RCC_CR_MSION;
00294        while((RCC->CR & RCC_CR_MSIRDY) != 0 && intentos < 50){
00295                 intentos++;
00296        }
00297 
00298        if (intentos == 50) {
00299               return 0;
00300        }
00301    }
00302 
00303    //configurar frecuencia MSI 2.097MHz
00304    RCC->ICSCR = (RCC->ICSCR & (~RCC_ICSCR_MSIRANGE_Msk)) | RCC_ICSCR_MSIRANGE_5;
00305 
00306 
00307    //habilitar MSI y esperar que este listo
00308    RCC->CR |= RCC_CR_MSION;
00309 
00310    intentos = 0;
00311    while((RCC->CR & RCC_CR_MSIRDY) == 0 && intentos < 50){
00312        intentos++;
00313    }
00314 
00315    if (intentos == 50) {
00316        return 0;
00317    }
00318 
00319    // configurar como fuente de reloj del sistema MSI y configurara como reloj de despertar el MSI
00320 
00321    RCC->CFGR = RCC_CFGR_MCOPRE_DIV1 | RCC_CFGR_MCOSEL_NOCLOCK | RCC_CFGR_PLLDIV2 | RCC_CFGR_PLLMUL3
00322            | RCC_CFGR_PLLSRC_HSE /*| RCC_CFGR_STOPWUCK_Msk*/ | RCC_CFGR_PPRE2_DIV1 | RCC_CFGR_PPRE1_DIV1 | RCC_CFGR_HPRE_DIV1 | RCC_CFGR_SW_MSI;
00323 
00324 
00325    // comprobar que la fuente de reloj cambia a MSI
00326    intentos = 0;
00327   while((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SW_MSI && intentos < 50){
00328       intentos++;
00329   }
00330   if (intentos == 50) {
00331          return 0;
00332   }
00333 
00334   //desactivar el resto de fuentes de reloj.
00335   RCC->CR &= RCC_CR_MSION | RCC_CR_MSIRDY; // desactivar PLL HSE HSI16
00336   RCC->CRRCR = 0; // desactivar HSI48
00337 
00338   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3); // voltage select 1.2V
00339 
00340   return 1; //OK
00341 
00342 }
00343 
00344 
00345 void Clock::printClockInfo()
00346 {
00347     switch (__HAL_RCC_GET_SYSCLK_SOURCE()) {
00348         case RCC_SYSCLKSOURCE_STATUS_MSI:
00349             _.print("MSI used as system clock.").ln();
00350             break;
00351         case RCC_SYSCLKSOURCE_STATUS_HSI:
00352             _.print("HSI used as system clock.").ln();
00353             break;
00354         case RCC_SYSCLKSOURCE_STATUS_HSE:
00355             _.print("HSE used as system clock.").ln();
00356             break;
00357         case RCC_SYSCLKSOURCE_STATUS_PLLCLK:
00358             _.print("PLL used as system clock.").ln();
00359             if ((RCC->CFGR & RCC_CFGR_PLLSRC) == RCC_CFGR_PLLSRC_HSE) {
00360                 _.print("HSE oscillator clock selected as PLL input clock.").ln();
00361             } else {
00362                 _.print("HSI16 oscillator clock selected as PLL input clock.").ln();
00363             }
00364             break;
00365     }
00366     HAL_RCC_GetHCLKFreq();
00367     _.print("CPU SystemCoreClock is ").print(SystemCoreClock).print(" Hz").ln();
00368 }
00369 
00370 #define SCB_SIZE 9
00371 #define RCC_SIZE 21
00372 #define PWR_SIZE 2
00373 #define RTC_SIZE 25
00374 #define SYSCFG_SIZE 9
00375 #define TOTAL_SIZE SCB_SIZE + RCC_SIZE + PWR_SIZE + RTC_SIZE + SYSCFG_SIZE
00376 
00377 void Clock::readRegisters(){
00378     //SCB registers
00379 
00380     _.print("SCB\r\n");
00381     _.print("Offset\tValue\r\n");
00382     uint32_t pto = SCB_BASE;
00383     for(uint32_t i = 0 ; i < SCB_SIZE ; i++) {
00384         _.printf("0x%02X\t0x%08X\r\n",i*4,*(uint32_t *)(pto+i*4));
00385     }
00386 
00387     //RCC registers
00388 
00389     _.print("RCC\r\n");
00390     _.print("Offset\tValue\r\n");
00391     pto = RCC_BASE;
00392     for(uint32_t i = 0 ; i < RCC_SIZE ; i++) {
00393         _.printf("0x%02X\t0x%08X\r\n",i*4,*(uint32_t *)(pto+i*4));
00394     }
00395 
00396     //PWR registers
00397     _.print("PWR\r\n");
00398     _.print("Offset\tValue\r\n");
00399     pto = PWR_BASE;
00400     for(uint32_t i = 0 ; i < PWR_SIZE ; i++) {
00401         _.printf("0x%02X\t0x%08X\r\n",i*4,*(uint32_t *)(pto+i*4));
00402     }
00403 
00404     //RTC registers
00405     _.print("RTC\r\n");
00406     _.print("Offset\tValue\r\n");
00407     pto = RTC_BASE;
00408     for(uint32_t i = 0 ; i < RTC_SIZE ; i++) {
00409         _.printf("0x%02X\t0x%08X\r\n",i*4,*(uint32_t *)(pto+i*4));
00410     }
00411 
00412     //SYSCFG registers
00413     _.print("SYSCFG\r\n");
00414     _.print("Offset\tValue\r\n");
00415     pto = SYSCFG_BASE;
00416     for(uint32_t i = 0 ; i < SYSCFG_SIZE ; i++) {
00417         _.printf("0x%02X\t0x%08X\r\n",i*4,*(uint32_t *)(pto+i*4));
00418     }
00419     _.ln();
00420     _.flush();
00421 }
00422 
00423 
00424 /*void Clock::printRegisters(){
00425     bool deleteReg = false;
00426     if(this->registers!=NULL) {
00427         deleteReg = true;
00428     } else {
00429         this->registers = (uint32_t*)(Eeprom::getInstance()->readLongInt(Address::Register::BASE));
00430     }
00431     _.print("SCB\r\n");
00432     _.print("Offset\tValue\r\n");
00433 
00434     uint8_t p = 0;
00435 
00436     for(uint32_t i = 0 ; i < SCB_SIZE ; i++) {
00437         _.printf("0x%02X\t0x%08X\r\n",i*4,this->registers[p]);
00438         p++;
00439         if(p >= TOTAL_SIZE){
00440             return;
00441         }
00442     }
00443 
00444     _.print("RCC\r\n");
00445     _.print("Offset\tValue\r\n");
00446 
00447     for(uint32_t i = 0 ; i < RCC_SIZE ; i++) {
00448         _.printf("0x%02X\t0x%08X\r\n",i*4,this->registers[p]);
00449         p++;
00450         if(p >= TOTAL_SIZE){
00451             return;
00452         }
00453     }
00454 
00455     _.print("PWR\r\n");
00456     _.print("Offset\tValue\r\n");
00457 
00458     for(uint32_t i = 0 ; i < PWR_SIZE ; i++) {
00459         _.printf("0x%02X\t0x%08X\r\n",i*4,this->registers[p]);
00460         p++;
00461         if(p >= TOTAL_SIZE){
00462             return;
00463         }
00464     }
00465 
00466     _.print("RTC\r\n");
00467     _.print("Offset\tValue\r\n");
00468 
00469     for(uint32_t i = 0 ; i < RTC_SIZE ; i++) {
00470         _.printf("0x%02X\t0x%08X\r\n",i*4,this->registers[p]);
00471         p++;
00472         if(p >= TOTAL_SIZE){
00473             return;
00474         }
00475     }
00476 
00477     _.print("SYSCFG\r\n");
00478     _.print("Offset\tValue\r\n");
00479 
00480     for(uint32_t i = 0 ; i < SYSCFG_SIZE ; i++) {
00481         _.printf("0x%02X\t0x%08X\r\n",i*4,this->registers[p]);
00482         p++;
00483         if(p >= TOTAL_SIZE){
00484             return;
00485         }
00486     }
00487     if(deleteReg == true) {
00488         delete[] this->registers;
00489     }
00490     this->registers = NULL;
00491 
00492 
00493 
00494 }*/