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.
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 }*/
Generated on Fri Aug 19 2022 07:33:34 by
1.7.2