/* avoid that an alarm occurs when the device is on because this locks the ON key forever */ void rtc_enable_alarm(bool enable) { unsigned char data = rtc_read(0x0a); if (enable) { data |= 0xa0; /* turn bit d7=AFE and d5=ABE on */ } else data &= 0x5f; /* turn bit d7=AFE and d5=ABE off */ rtc_write(0x0a, data); /* check if alarm flag AF is off (as it should be) */ /* in some cases enabling the alarm results in an activated AF flag */ /* this should not happen, but it does */ /* if you know why, tell me! */ /* for now, we try again forever in this case */ while (rtc_check_alarm_flag()) /* on */ { data &= 0x5f; /* turn bit d7=AFE and d5=ABE off */ rtc_write(0x0a, data); sleep(HZ / 10); rtc_check_alarm_flag(); data |= 0xa0; /* turn bit d7=AFE and d5=ABE on */ rtc_write(0x0a, data); } }
/* (check for AF, which => started using wakeup alarm) */ bool rtc_check_alarm_started(bool release_alarm) { static bool alarm_state, run_before; bool rc; if (run_before) { rc = alarm_state; alarm_state &= ~release_alarm; } else { /* This call resets AF, so we store the state for later recall */ rc = alarm_state = rtc_check_alarm_flag(); run_before = true; } return rc; }
static void power_thread_rtc_process(void) { if (rtc_check_alarm_flag()) rtc_enable_alarm(false); }
void main(void) { unsigned char* loadbuffer; int buffer_size; int rc; int(*kernel_entry)(void); system_init(); kernel_init(); /* Need the kernel to sleep */ enable_interrupt(IRQ_FIQ_STATUS); lcd_init(); backlight_init(); button_init(); font_init(); adc_init(); lcd_setfont(FONT_SYSFIXED); /* These checks should only run if the bootloader is flashed */ if(GSTATUS3&0x02) { GSTATUS3&=0xFFFFFFFD; if(!(GPGDAT&BUTTON_POWER) && charger_inserted()) { while(!(GPGDAT&BUTTON_POWER) && charger_inserted()) { char msg[20]; if(charging_state()) { snprintf(msg,sizeof(msg),"Charging"); } else { snprintf(msg,sizeof(msg),"Charge Complete"); } reset_screen(); lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2, (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg); lcd_update(); #if defined(HAVE_RTC_ALARM) /* Check if the alarm went off while charging */ if(rtc_check_alarm_flag()) { GSTATUS3=1; /* Normally this is set in crt0.s */ break; } #endif } if(!(GPGDAT&BUTTON_POWER) #if defined(HAVE_RTC_ALARM) && !GSTATUS3 #endif ) { shutdown(); } } if(button_hold()) { const char msg[] = "HOLD is enabled"; reset_screen(); lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2, (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg); lcd_update(); sleep(2*HZ); shutdown(); } } power_init(); usb_init(); /* Enter USB mode without USB thread */ if(usb_detect() == USB_INSERTED) { const char msg[] = "Bootloader USB mode"; reset_screen(); lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2, (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg); lcd_update(); storage_enable(false); sleep(HZ/20); usb_enable(true); while (usb_detect() == USB_INSERTED) sleep(HZ); usb_enable(false); reset_screen(); lcd_update(); } reset_screen(); /* Show debug messages if button is pressed */ if(button_read_device()&BUTTON_A) verbose = true; printf("Rockbox boot loader"); printf("Version %s", rbversion); sleep(50); /* ATA seems to error without this pause */ rc = storage_init(); if(rc) { reset_screen(); error(EATA, rc, true); } filesystem_init(); rc = disk_mount_all(); if (rc<=0) { error(EDISK, rc, true); } printf("Loading firmware"); /* Flush out anything pending first */ commit_discard_idcache(); loadbuffer = (unsigned char*) 0x31000000; buffer_size = (unsigned char*)0x31400000 - loadbuffer; rc = load_firmware(loadbuffer, BOOTFILE, buffer_size); if(rc <= EFILE_EMPTY) error(EBOOTFILE, rc, true); storage_close(); system_prepare_fw_start(); commit_discard_idcache(); kernel_entry = (void*) loadbuffer; rc = kernel_entry(); #if 0 /* Halt */ while (1) core_idle(); #else /* Return and restart */ #endif }