| #include <string.h> |
| #include <time.h> |
| #include <signal.h> |
| #include "aboot-tiny.h" |
| #include "jacana_firmware.h" |
| #include "jacana_pvt.h" |
| #include "jacana_callback.h" |
| #include "jacana_serialport.h" |
| #include "jacana_clock.h" |
| #include "jacana_mem.h" |
| #include "jacana_log.h" |
| #include "jacana_usleep.h" |
| #include "jacana_download.h" |
| |
| #define GNSS_MODULE_FW_DOWNLOAD_TIMER_VALUE 5 |
| static timer_t gnss_module_fw_download_timer_id; |
| |
| /*---------------------------------------------------------------------------*/ |
| int jacana_aboot_tiny_force_stop(void) |
| { |
| jacana_aboot_tiny_set_result(ABOOT_TINY_ERROR_FORCE_STOP); |
| return aboot_tiny_stop(); |
| } |
| /*---------------------------------------------------------------------------*/ |
| |
| /* Safety Timer For FW Downloading...*/ |
| static int gnss_module_fw_download_timer_start(void) |
| { |
| int rc = 0; |
| struct itimerspec ts; |
| |
| memset (&ts, 0x00, sizeof (struct itimerspec)); |
| ts.it_value.tv_sec = GNSS_MODULE_FW_DOWNLOAD_TIMER_VALUE; |
| ts.it_value.tv_nsec = 0; |
| ts.it_interval.tv_sec = GNSS_MODULE_FW_DOWNLOAD_TIMER_VALUE; |
| ts.it_interval.tv_nsec = 0; |
| rc = timer_settime(gnss_module_fw_download_timer_id, 0, &ts, NULL); |
| jacana_log_printf("gnss download timer start."); |
| return rc; |
| } |
| |
| |
| static int gnss_module_fw_download_timer_stop(void) |
| { |
| int rc = 0; |
| struct itimerspec ts; |
| |
| memset (&ts, 0x00, sizeof (struct itimerspec)); |
| ts.it_value.tv_sec = 0; |
| ts.it_value.tv_nsec = 0; |
| ts.it_interval.tv_sec = 0; |
| ts.it_interval.tv_nsec = 0; |
| rc = timer_settime(gnss_module_fw_download_timer_id, 0, &ts, NULL); |
| jacana_log_printf("gnss download timer stop."); |
| return rc; |
| } |
| |
| |
| static void gps_state_fw_download(__attribute__( (unused)) union sigval sv) |
| { |
| if(aboot_tiny_is_running()) |
| { |
| jacana_aboot_tiny_force_stop(); |
| } |
| |
| jacana_log_printf("gnss download timer timeout."); |
| } |
| |
| static int gnss_module_fw_download_timer_init(void) |
| { |
| int rc = 0; |
| struct sigevent sigev; |
| |
| memset (&sigev, 0, sizeof (struct sigevent)); |
| sigev.sigev_value.sival_ptr = &gnss_module_fw_download_timer_id; |
| sigev.sigev_notify = SIGEV_THREAD; |
| sigev.sigev_notify_attributes = NULL; |
| sigev.sigev_notify_function = gps_state_fw_download; |
| rc = timer_create(CLOCK_REALTIME, &sigev, &gnss_module_fw_download_timer_id); |
| jacana_log_printf("gnss download timer init."); |
| return rc; |
| } |
| |
| /*---------------------------------------------------------------------------*/ |
| int |
| jacana_aboot_tiny_download(const char *dev, int baud) |
| { |
| /* Should be called at very beginning */ |
| aboot_tiny_init(jacana_aboot_tiny_callback); |
| |
| /* WDT Timer is created here. */ |
| gnss_module_fw_download_timer_init(); |
| |
| /* Set initial result as success */ |
| jacana_aboot_tiny_set_result(ABOOT_TINY_ERROR_SUCCESS); |
| |
| /* Log printf */ |
| aboot_tiny_log_printf = jacana_log_printf; |
| |
| /* Memory alloc/free */ |
| aboot_tiny_mem_alloc = jacana_mem_alloc; |
| aboot_tiny_mem_free = jacana_mem_free; |
| aboot_tiny_usleep = jacana_delay_usleep; |
| |
| /* Jacana clock init */ |
| jacana_clock_init(); |
| aboot_tiny_clock_get = jacana_clock_get; |
| |
| /* System platform init */ |
| aboot_tiny_platform_init(); |
| |
| /* Jacana uart init */ |
| if(jacana_serialport_init(dev, baud, aboot_tiny_uart_rx_callback) < 0) { |
| aboot_tiny_log_printf("error: open serial port failed\n"); |
| return -1; |
| } |
| aboot_tiny_uart_send = jacana_serialport_write; |
| |
| /* Get progress fixup size */ |
| void *priv = jacana_pvt_raw_open(); |
| if(!priv) { |
| aboot_tiny_log_printf("error: open pvt partition failed\n"); |
| return -1; |
| } |
| size_t pvt_size = jacana_pvt_raw_get_total_size(priv); |
| size_t progress_fixup = ((pvt_size + SPARSE_BLOCK_SZ - 1) |
| & ~(SPARSE_BLOCK_SZ - 1)) * 2; |
| jacana_pvt_raw_close(priv); |
| |
| /* Jacana firmware interface init */ |
| firmware_handle_t firmware; |
| pvt_info_t pvt_info; |
| firmware.pvt_info = &pvt_info; |
| priv = jacana_firmware_raw_open(); |
| if(!priv) { |
| aboot_tiny_log_printf("error: open jacana firmware partition failed\n"); |
| return -1; |
| } |
| if(jacana_firmware_open(&firmware, priv) < 0) { |
| jacana_firmware_raw_close(priv); |
| aboot_tiny_log_printf("error: open jacana firmware failed\n"); |
| return -1; |
| } |
| aboot_tiny_firmware_read_line = jacana_firmware_read_line; |
| aboot_tiny_firmware_read_data = jacana_firmware_read_data; |
| |
| gnss_module_fw_download_timer_start(); |
| /* Start download engine */ |
| if(aboot_tiny_start(&firmware, progress_fixup, true) < 0) { |
| jacana_firmware_raw_close(priv); |
| jacana_firmware_close(&firmware); |
| aboot_tiny_log_printf("error: start aboot engine failed\n"); |
| return -1; |
| } |
| |
| /* customize timeout parameter in second */ |
| aboot_tiny_set_link_lost_timeout(3); |
| aboot_tiny_set_cmd_response_timeout(2); |
| |
| /* Enter main event loops */ |
| aboot_tiny_main_loop(); |
| |
| /* Close serialport device */ |
| jacana_serialport_exit(); |
| |
| gnss_module_fw_download_timer_stop(); |
| /** |
| * firmware already closed when switch to pvt download, |
| * so we need close pvt here |
| */ |
| priv = firmware.priv; |
| jacana_pvt_close(&firmware); |
| jacana_pvt_raw_close(priv); |
| |
| int rc = (int)jacana_aboot_tiny_get_result(); |
| if(rc) { |
| aboot_tiny_log_printf("Jacana download failed with error code %d.\n", rc); |
| } |
| |
| return -rc; |
| } |
| /*---------------------------------------------------------------------------*/ |