/* 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);
}
Exemplo n.º 4
0
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
}