int main(void) { uint8_t system_state=0, i2c_resets=0, si446x_resets=0;//used to track button press functionality and any errors uint8_t sensors=0; uint32_t repetition_counter=0; //Used to detect any I2C lockup uint8_t L3GD20_Data_Buffer_old[8]; //Used to test for noise in the gyro data (indicating that it is working) uint8_t UplinkFlags=0,CutFlags=0; uint16_t UplinkBytes=0; //Counters and flags for telemetry uint32_t last_telemetry=0,cutofftime=0,indtest=0,badgyro=0,permission_time=0,countdown_time=0,last_cuttest=0; uint16_t sentence_counter=0; uint8_t silab; //Cutdown config stuff here, atm uses hardcoded polygon defined in polygon.h static const int32_t Geofence[UK_GEOFENCE_POINTS*2]=UK_GEOFENCE; RTC_t RTC_time; _REENT_INIT_PTR(&my_reent); _impure_ptr = &my_reent; SystemInit(); //Sets up the clk setup_gpio(); //Initialised pins, and detects boot source DBGMCU_Config(DBGMCU_IWDG_STOP, ENABLE); //Watchdog stopped during JTAG halt RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);/* Enable PWR and BKP clocks */ PWR_BackupAccessCmd(ENABLE);/* Allow access to BKP Domain */ uint16_t shutdown_lock=BKP_ReadBackupRegister(BKP_DR3); //Holds the shutdown lock setting uint16_t reset_counter=BKP_ReadBackupRegister(BKP_DR2); //The number of consecutive failed reboot cycles PWR_BackupAccessCmd(DISABLE); if(RCC->CSR&RCC_CSR_IWDGRSTF && shutdown_lock!=SHUTDOWNLOCK_MAGIC) {//Watchdog reset, turn off RCC->CSR|=RCC_CSR_RMVF; //Reset the reset flags shutdown(); } if(USB_SOURCE==bootsource) { RCC->CFGR &= ~(uint32_t)RCC_CFGR_PPRE1_DIV16; RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV4;//Swap the ABP1 bus to run at 12mhz rather than 4 if we booted from USB, makes USB fast enough } SysTick_Configuration(); //Start up system timer at 100Hz for uSD card functionality Watchdog_Config(WATCHDOG_TIMEOUT); //Set the watchdog Watchdog_Reset(); //Reset watchdog as soon as possible incase it is still running at power on rtc_init(); //Real time clock initialise - (keeps time unchanged if set) Usarts_Init(); ISR_Config(); rprintfInit(__usart_send_char); //Printf over the bluetooth if(USB_SOURCE==bootsource) { Set_System(); //This actually just inits the storage layer Set_USBClock(); USB_Interrupts_Config(); USB_Init(); uint32_t nojack=0x000FFFFF; //Countdown timer - a few hundered ms of 0v on jack detect forces a shutdown while (bDeviceState != CONFIGURED) { //Wait for USB config - timeout causes shutdown if((Millis>10000 && bDeviceState == UNCONNECTED)|| !nojack) //No USB cable - shutdown (Charger pin will be set to open drain, cant be disabled without usb) shutdown(); if(GET_VBUS_STATE) //Jack detect resets the countdown nojack=0x0FFFFF; nojack--; Watchdog_Reset(); //Reset watchdog here, if we are stalled here the Millis timeout should catch us } PWR_BackupAccessCmd(ENABLE); /* Allow access to BKP Domain */ BKP_WriteBackupRegister(BKP_DR3,0x0000);//Wipe the shutdown lock setting PWR_BackupAccessCmd(DISABLE); while(1) { if(!(Millis%1000) && bDeviceState == SUSPENDED) { Delay(100); if(!GET_VBUS_STATE) shutdown(); } Watchdog_Reset(); __WFI(); //Sleep mode } } if(!GET_PWR_STATE && !(CoreDebug->DHCSR&0x00000001) && shutdown_lock!=SHUTDOWNLOCK_MAGIC) {//Check here to make sure the power button is still pressed, if not, sleep if no debug and not in always on flight mode shutdown(); //This means a glitch on the supply line, or a power glitch results in sleep } // check to see if battery has enough charge to start ADC_Configuration(); //We leave this a bit later to allow stabilisation { uint32_t t=Millis; while(Millis<(t+100)){__WFI();} //Sensor+inst amplifier takes about 100ms to stabilise after power on } if(Battery_Voltage<BATTERY_STARTUP_LIMIT) { //We will have to turn off if(reset_counter<10) shutdown(); } Watchdog_Reset(); //Card Init can take a second or two // system has passed battery level check and so file can be opened {//Context uint8_t silabs_header[5]={}; uint8_t* silabs_header_=NULL; //Pointer to the array (if all goes ok) if((f_err_code = f_mount(0, &FATFS_Obj)))Usart_Send_Str((char*)"FatFs mount error\r\n");//This should only error if internal error else { //FATFS initialised ok, try init the card, this also sets up the SPI1 if(!(f_err_code=f_open(&FATFS_logfile,(const TCHAR*)"time.txt",FA_OPEN_EXISTING|FA_READ|FA_WRITE))){//Try to open time file get system time if(!f_stat((const TCHAR *)"time.txt",&FATFS_info)) {//Get file info if(FATFS_info.fsize<5) { //Empty file RTC_time.year=(FATFS_info.fdate>>9)+1980;//populate the time struct (FAT start==1980, RTC.year==0) RTC_time.month=(FATFS_info.fdate>>5)&0x000F; RTC_time.mday=FATFS_info.fdate&0x001F; RTC_time.hour=(FATFS_info.ftime>>11)&0x001F; RTC_time.min=(FATFS_info.ftime>>5)&0x003F; RTC_time.sec=(FATFS_info.ftime<<1)&0x003E; rtc_settime(&RTC_time); rprintfInit(__fat_print_char);//printf to the open file printf("RTC set to %d/%d/%d %d:%d:%d\n",RTC_time.mday,RTC_time.month,RTC_time.year,\ RTC_time.hour,RTC_time.min,RTC_time.sec); } } f_close(&FATFS_logfile); //Close the time.txt file } // load settings if file exists Watchdog_Reset(); //Card Init can take a second or two if(!f_open(&FATFS_logfile,(const TCHAR *)"settings.dat",FA_OPEN_EXISTING | FA_READ)) { UINT br; int8_t rtc_correction; f_read(&FATFS_logfile, (void*)(&rtc_correction),sizeof(rtc_correction),&br); //Use the setting to apply correction to the RTC if(br && (rtc_correction<30) && (rtc_correction>-92) && rtc_correction ) { PWR_BackupAccessCmd(ENABLE);/* Allow access to BKP Domain */ uint16_t tweaked_prescale = (0x0001<<15)-2;/* Try to run the RTC slightly too fast so it can be corrected either way */ RTC_WaitForSynchro(); /* Wait for RTC registers synchronization */ if( RTC->PRLL != tweaked_prescale ) {/*Note that there is a 0.5ppm offset here (correction 0==0.5ppm slow)*/ RTC_SetPrescaler(tweaked_prescale); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767-2+1) */ RTC_WaitForLastTask(); } BKP_SetRTCCalibrationValue((uint8_t) ((int16_t)31-(21*(int16_t)rtc_correction)/(int16_t)20) ); BKP_RTCOutputConfig(BKP_RTCOutputSource_None);/* Ensure any output is disabled here */ /* Lock access to BKP Domain */ PWR_BackupAccessCmd(DISABLE); } else if(br && ((uint8_t)rtc_correction==0x91) ) {/* 0x91 magic flag sets the RTC clock output on */ PWR_BackupAccessCmd(ENABLE);/* Allow access to BKP Domain */ BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);/* Output a 512Hz reference clock on the TAMPER pin*/ PWR_BackupAccessCmd(DISABLE); } if(br) { f_read(&FATFS_logfile, (void*)(&shutdown_lock),sizeof(shutdown_lock),&br);/*This needs to be set with the same magic flag value*/ if(br==2) { PWR_BackupAccessCmd(ENABLE);/* Allow access to BKP Domain */ BKP_WriteBackupRegister(BKP_DR3,shutdown_lock);//Wipe the shutdown lock setting PWR_BackupAccessCmd(DISABLE); } } if(br==2) { //Read was successful, next try to read 5 bytes of packet header f_read(&FATFS_logfile, (void*)(silabs_header),5,&br); if(br!=5) silabs_header_=silabs_header; } f_close(&FATFS_logfile); //Close the settings.dat file } #ifndef SINGLE_LOGFILE rtc_gettime(&RTC_time); //Get the RTC time and put a timestamp on the start of the file rprintfInit(__str_print_char); //Print to the string printf("%02d-%02d-%02dT%02d-%02d-%02d-%s.csv",RTC_time.year,RTC_time.month,RTC_time.mday,RTC_time.hour,RTC_time.min,RTC_time.sec,"Log");//Timestamp name rprintfInit(__usart_send_char); //Printf over the bluetooth #endif Watchdog_Reset(); //Card Init can take a second or two if((f_err_code=f_open(&FATFS_logfile,(TCHAR*)LOGFILE_NAME,FA_CREATE_ALWAYS | FA_WRITE))) {//Present Delay(10000); if((f_err_code=f_open(&FATFS_logfile,(TCHAR*)LOGFILE_NAME,FA_CREATE_ALWAYS | FA_WRITE))) {//Try again printf("FatFs drive error %d\r\n",f_err_code); if(f_err_code==FR_DISK_ERR || f_err_code==FR_NOT_READY) Usart_Send_Str((char*)"No uSD card inserted?\r\n"); } } else { Watchdog_Reset(); //Card Init can take a second or two print_string[strlen(print_string)-4]=0x00;//Wipe the .csv off the string strcat(print_string,"_gyro.wav"); if((f_err_code=f_open(&FATFS_wavfile_gyro,(TCHAR*)LOGFILE_NAME,FA_CREATE_ALWAYS | FA_WRITE))) {//Present printf("FatFs drive error %d\r\n",f_err_code); if(f_err_code==FR_DISK_ERR || f_err_code==FR_NOT_READY) Usart_Send_Str((char*)"No uSD card inserted?\r\n"); } else { //We have a mounted card f_err_code=f_lseek(&FATFS_logfile, PRE_SIZE);// Pre-allocate clusters if (f_err_code || f_tell(&FATFS_logfile) != PRE_SIZE)// Check if the file size has been increased correctly Usart_Send_Str((char*)"Pre-Allocation error\r\n"); else { if((f_err_code=f_lseek(&FATFS_logfile, 0)))//Seek back to start of file to start writing Usart_Send_Str((char*)"Seek error\r\n"); else rprintfInit(__str_print_char);//Printf to the logfile } if(f_err_code) f_close(&FATFS_logfile);//Close the already opened file on error else file_opened=1; //So we know to close the file properly on shutdown if(file_opened==1) { Watchdog_Reset(); //Card Init can take a second or two if (f_err_code || f_tell(&FATFS_wavfile_gyro) != PRE_SIZE)// Check if the file size has been increased correctly Usart_Send_Str((char*)"Pre-Allocation error\r\n"); else { if((f_err_code=f_lseek(&FATFS_logfile, 0)))//Seek back to start of file to start writing Usart_Send_Str((char*)"Seek error\r\n"); else rprintfInit(__str_print_char);//Printf to the logfile } if(f_err_code) f_close(&FATFS_wavfile_gyro);//Close the already opened file on error else file_opened|=2; //So we know to close the file properly on shutdown } } } } f_err_code|=write_wave_header(&FATFS_wavfile_gyro, 4, 100, 16);//4 channels, last channel is for the current rpm Watchdog_Reset(); //Card Init can take a second or two //Setup and test the silabs radio silab=si446x_setup(silabs_header_); if(silab!=0x44) { //Should return the device code print_string[0]=0x00; printf("Silabs: %02x\n",silab); f_puts("Silabs detect error, got:",&FATFS_logfile); f_puts(print_string,&FATFS_logfile); shutdown_filesystem(ERR, file_opened);//So we log that something went wrong in the logfile shutdown(); } }//Context
/** * @brief Calibration of External crystal oscillator auto(through Timer * * @param None * @retval : None */ void AutoClockCalibration(void) { RCC_ClocksTypeDef ClockValue; uint16_t TimerPrescalerValue=0x0003; uint16_t CountWait; uint16_t DeviationInteger; uint32_t CalibrationTimer; float f32_Deviation; TIM_ICInitTypeDef TIM_ICInitStructure; TIM_DeInit(TIM2); BKP_TamperPinCmd(DISABLE); BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock); /* TIM2 configuration: PWM Input mode ------------------------ The external signal is connected to TIM2 CH2 pin (PA.01), The Rising edge is used as active edge, The TIM2 CCR2 is used to compute the frequency value The TIM2 CCR1 is used to compute the duty cycle value ------------------------------------------------------------ */ TIM_PrescalerConfig(TIM2,TimerPrescalerValue,TIM_PSCReloadMode_Immediate); TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0x00; TIM_PWMIConfig(TIM2, &TIM_ICInitStructure); TIM_ICInit(TIM2, &TIM_ICInitStructure); /* Select the TIM2 Input Trigger: TI2FP2 */ TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2); /* Select the slave Mode: Reset Mode */ TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset); /* Enable the Master/Slave Mode */ TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable); /* TIM enable Counter */ TIM_Cmd(TIM2, ENABLE); LCD_Clear(Blue2); LCD_DisplayString(Line4,Column1,"Please Wait....."); /* Wait for 2 seconds */ CalibrationTimer = RTC_GetCounter(); while((RTC_GetCounter() - CalibrationTimer) < 2) { } RCC_GetClocksFreq(&ClockValue); TimerFrequency=(ClockValue.PCLK1_Frequency * 2)/(TimerPrescalerValue+1); /* Enable the CC2 Interrupt Request */ TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE); /* Wait for 2 seconds */ CalibrationTimer = RTC_GetCounter(); while((RTC_GetCounter() - CalibrationTimer) < 2) { } if(!(TIM_GetFlagStatus(TIM2, TIM_FLAG_CC1))) /* There is no signal at the timer TIM2 peripheral input */ { LCD_Clear(Blue2); LCD_DisplayString(Line3,Column0,"Please connect wire"); LCD_DisplayString(Line4,Column0,"link between PC13"); LCD_DisplayString(Line5,Column0,"and PA1"); LCD_DisplayString(Line7,Column0,"No calibration done"); } else { /* Calulate Deviation in ppm using the formula : Deviation in ppm = (Deviation from 511.968/511.968)*1 million*/ if(f32_Frequency > 511.968) { f32_Deviation=((f32_Frequency-511.968)/511.968)*1000000; } else { f32_Deviation=((511.968-f32_Frequency)/511.968)*1000000; } DeviationInteger = (uint16_t)f32_Deviation; if(f32_Deviation >= (DeviationInteger + 0.5)) { DeviationInteger = ((uint16_t)f32_Deviation)+1; } CountWait=0; /* Frequency deviation in ppm should be les than equal to 121 ppm*/ if(DeviationInteger <= 121) { while(CountWait<128) { if(CalibrationPpm[CountWait] == DeviationInteger) break; CountWait++; } BKP_SetRTCCalibrationValue(CountWait); LCD_Clear(Blue2); LCD_DisplayString(Line4,Column1,"Calibration Value"); LCD_DisplayChar(Line5,Column10,(CountWait%10)+0x30); CountWait=CountWait/10; LCD_DisplayChar(Line5,Column9,(CountWait%10)+0x30); CountWait=CountWait/10; if(CountWait>0) { LCD_DisplayChar(Line5,Column8,(CountWait%10)+0x30); } } else /* Frequency deviation in ppm is more than 121 ppm, hence calibration can not be done */ { LCD_Clear(Blue2); LCD_DisplayString(Line3,Column1,"Out Of Calibration"); LCD_DisplayString(Line4,Column4,"Range"); } } BKP_RTCOutputConfig(BKP_RTCOutputSource_None); TIM_ITConfig(TIM2, TIM_IT_CC2, DISABLE); TIM_Cmd(TIM2, DISABLE); TIM_DeInit(TIM2); CalibrationTimer=RTC_GetCounter(); /* Wait for 2 seconds */ while((RTC_GetCounter() - CalibrationTimer) < 5) { } MenuInit(); }
static rt_err_t rt_rtc_control(rt_device_t dev, rt_uint8_t cmd, void *args) { rt_time_t *time; unsigned char calivalue; RT_ASSERT(dev != RT_NULL); switch (cmd) { case RT_DEVICE_CTRL_RTC_GET_TIME: time = (rt_time_t *)args; /* read device */ *time = RTC_GetCounter(); break; case RT_DEVICE_CTRL_RTC_SET_TIME: time = (rt_time_t *)args; /* Enable PWR and BKP clocks */ //RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); /* Allow access to BKP Domain */ PWR_BackupAccessCmd(ENABLE); /* Wait until last write operation on RTC registers has finished */ RTC_WaitForLastTask(); /* Change the current time */ RTC_SetCounter(*time); /* Wait until last write operation on RTC registers has finished */ RTC_WaitForLastTask(); BKP_WriteBackupRegister(RTC_SET_FLAG_BKP16BITS, 0xA5A5); PWR_BackupAccessCmd(DISABLE); break; case RT_DEVICE_CTRL_RTC_CALI_SET: /*calibration clock default*/ if (RT_EOK == get_rtc_cali_param(&calivalue)) { if (RTC_CALIBRATION_DEF_VALUE == calivalue) { rt_kprintf("rtc not cfg cali val\n"); } else if (calivalue<=0x7f) { PWR_BackupAccessCmd(ENABLE); BKP_SetRTCCalibrationValue(calivalue); PWR_BackupAccessCmd(DISABLE); } else rt_kprintf("rtc calivalue(%d) error\n", calivalue); } else { rt_kprintf("get rtc cali value fail\n"); } break; default: break; } return RT_EOK; }
/******************************************************************************* * Function Name : AutoClockCalibration * Description : Calibration of External crystal oscillator auto(through Timer peripheral) * Input : None * Output : None * Return : None *******************************************************************************/ void AutoClockCalibration(void) { RCC_ClocksTypeDef ClockValue; u16 u16_TimerPrescalerValue=0x0003; u16 u16_CountWait; u16 u16_DeviationInteger; u32 u32_CalibrationTimer; float f32_Deviation; TIM_ICInitTypeDef TIM_ICInitStructure; TIM_DeInit(TIM2); BKP_TamperPinCmd(DISABLE); BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock); /* TIM2 configuration: PWM Input mode ------------------------ The external signal is connected to TIM2 CH2 pin (PA.01), The Rising edge is used as active edge, The TIM2 CCR2 is used to compute the frequency value The TIM2 CCR1 is used to compute the duty cycle value ------------------------------------------------------------ */ TIM_PrescalerConfig(TIM2,u16_TimerPrescalerValue,TIM_PSCReloadMode_Immediate); TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0x00; TIM_PWMIConfig(TIM2, &TIM_ICInitStructure); TIM_ICInit(TIM2, &TIM_ICInitStructure); /* Select the TIM2 Input Trigger: TI2FP2 */ TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2); /* Select the slave Mode: Reset Mode */ TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset); /* Enable the Master/Slave Mode */ TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable); /* TIM enable u16_Counter */ TIM_Cmd(TIM2, ENABLE); /* Wait for 2 seconds */ u32_CalibrationTimer = RTC_GetCounter(); while((RTC_GetCounter() - u32_CalibrationTimer) < 2) { } RCC_GetClocksFreq(&ClockValue); u32_TimerFrequency=(ClockValue.PCLK1_Frequency * 2)/(u16_TimerPrescalerValue+1); /* Enable the CC2 Interrupt Request */ TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE); /* Wait for 2 seconds */ u32_CalibrationTimer = RTC_GetCounter(); while((RTC_GetCounter() - u32_CalibrationTimer) < 2) { } if(!(TIM_GetFlagStatus(TIM2, TIM_FLAG_CC1))) /* There is no signal at the timer TIM2 peripheral input */ { } else { /* Calulate Deviation in ppm using the formula : Deviation in ppm = (Deviation from 511.968/511.968)*1 million*/ if(f32_Frequency > 511.968) { f32_Deviation=((f32_Frequency-511.968)/511.968)*1000000; } else { f32_Deviation=((511.968-f32_Frequency)/511.968)*1000000; } u16_DeviationInteger = (u16)f32_Deviation; if(f32_Deviation >= (u16_DeviationInteger + 0.5)) { u16_DeviationInteger = ((u16)f32_Deviation)+1; } u16_CountWait=0; /* Frequency deviation in ppm should be les than equal to 121 ppm*/ if(u16_DeviationInteger <= 121) { while(u16_CountWait<128) { if(u8_CalibrationPpm[u16_CountWait] == u16_DeviationInteger) break; u16_CountWait++; } BKP_SetRTCCalibrationValue(u16_CountWait); u16_CountWait=u16_CountWait/10; u16_CountWait=u16_CountWait/10; if(u16_CountWait>0) { } } else /* Frequency deviation in ppm is more than 121 ppm, hence calibration can not be done */ { } } BKP_RTCOutputConfig(BKP_RTCOutputSource_None); TIM_ITConfig(TIM2, TIM_IT_CC2, DISABLE); TIM_Cmd(TIM2, DISABLE); TIM_DeInit(TIM2); u32_CalibrationTimer=RTC_GetCounter(); /* Wait for 2 seconds */ while((RTC_GetCounter() - u32_CalibrationTimer) < 5) { } //MenuInit(); }