Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.c Source File

main.c

00001 /**
00002  * @file    main.c
00003  * @brief   DAPLink Bootloader application entry point
00004  *
00005  * DAPLink Interface Firmware
00006  * Copyright (c) 2009-2019, ARM Limited, All Rights Reserved
00007  * SPDX-License-Identifier: Apache-2.0
00008  *
00009  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00010  * not use this file except in compliance with the License.
00011  * You may obtain a copy of the License at
00012  *
00013  * http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  * Unless required by applicable law or agreed to in writing, software
00016  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00017  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018  * See the License for the specific language governing permissions and
00019  * limitations under the License.
00020  */
00021 
00022 #include "main.h"
00023 #include "gpio.h"
00024 #include "validation.h"
00025 #include "vfs_manager.h"
00026 #include "cmsis_os2.h"
00027 #include "rl_usb.h"
00028 #include "settings.h"
00029 #include "info.h"
00030 #include "target_config.h"
00031 #include "util.h"
00032 #include "cortex_m.h"
00033 #include "sdk.h"
00034 #include "target_board.h"
00035 
00036 //default msc led settings
00037 #ifndef MSC_LED_DEF
00038 #define MSC_LED_DEF GPIO_LED_ON
00039 #endif
00040 
00041 __asm void modify_stack_pointer_and_start_app(uint32_t r0_sp, uint32_t r1_pc)
00042 {
00043     MOV SP, R0
00044     BX R1
00045 }
00046 
00047 // Event flags for main task
00048 // Timers events
00049 #define FLAGS_MAIN_90MS         (1 << 0)
00050 #define FLAGS_MAIN_30MS         (1 << 1)
00051 // USB Events
00052 #define FLAGS_MAIN_PROC_USB     (1 << 9)
00053 // Used by msc when flashing a new binary
00054 #define FLAGS_LED_BLINK_30MS    (1 << 6)
00055 
00056 // Timing constants (in 90mS ticks)
00057 // USB busy time
00058 #define USB_BUSY_TIME           (33)
00059 // Delay before a USB device connect may occur
00060 #define USB_CONNECT_DELAY       (11)
00061 // Decrement to zero
00062 #define DECZERO(x)              (x ? --x : 0)
00063 #define NO_TIMEOUT              (0xffff)
00064 
00065 // Global state of usb used in
00066 main_usb_connect_t usb_state;
00067 
00068 // Reference to our main task
00069 osThreadId_t main_task_id;
00070 
00071 static uint8_t msc_led_usb_activity = 0;
00072 static main_led_state_t msc_led_state = MAIN_LED_FLASH;
00073 
00074 static main_usb_busy_t usb_busy;
00075 static uint32_t usb_busy_count;
00076 
00077 // Timer task, set flags every 30mS and 90mS
00078 void timer_task_30mS(void * arg)
00079 {
00080     static uint32_t i = 0;
00081     osThreadFlagsSet(main_task_id, FLAGS_MAIN_30MS);
00082     if (!(i++ % 3)) {
00083         osThreadFlagsSet(main_task_id, FLAGS_MAIN_90MS);
00084     }
00085 }
00086 
00087 // Flash MSC LED using 30mS tick
00088 void main_blink_msc_led(main_led_state_t state)
00089 {
00090     msc_led_usb_activity = 1;
00091     msc_led_state = state;
00092     return;
00093 }
00094 
00095 void USBD_SignalHandler()
00096 {
00097     osThreadFlagsSet(main_task_id, FLAGS_MAIN_PROC_USB);
00098 }
00099 
00100 void main_task(void * arg)
00101 {
00102     // State processing
00103     uint16_t flags;
00104     // LED
00105     gpio_led_state_t msc_led_value = MSC_LED_DEF;
00106     // USB
00107     uint32_t usb_state_count;
00108 
00109     if (config_ram_get_initial_hold_in_bl()) {
00110         // Delay for 1 second for VMs
00111         osDelay(100);
00112     }
00113 
00114     // Get a reference to this task
00115     main_task_id = osThreadGetId();
00116     // Set LED defaults
00117     gpio_set_hid_led(GPIO_LED_OFF);
00118     gpio_set_cdc_led(GPIO_LED_OFF);
00119     gpio_set_msc_led(msc_led_value);
00120     // Update version information file
00121     info_init();
00122     // USB
00123     usbd_init();
00124     vfs_mngr_init(true);
00125     usbd_connect(0);
00126     usb_busy = MAIN_USB_IDLE;
00127     usb_busy_count = 0;
00128     usb_state = MAIN_USB_CONNECTING;
00129     usb_state_count = USB_CONNECT_DELAY;
00130     // Start timer tasks
00131     osTimerId_t tmr_id = osTimerNew(timer_task_30mS, osTimerPeriodic, NULL, NULL);
00132     osTimerStart(tmr_id, 3);
00133 
00134     while (1) {
00135         // need to create a new event for programming failure
00136         flags = osThreadFlagsWait(FLAGS_MAIN_90MS     // 90mS tick
00137                         | FLAGS_MAIN_30MS            // 30mS tick
00138                         | FLAGS_MAIN_PROC_USB       // process usb events
00139                         , osFlagsWaitAny, 
00140                         osWaitForever);
00141 
00142         if (flags & FLAGS_MAIN_PROC_USB) {
00143             USBD_Handler();
00144         }
00145 
00146         if (flags & FLAGS_MAIN_90MS) {
00147             vfs_mngr_periodic(90); // FLAGS_MAIN_90MS
00148 
00149             // Update USB busy status
00150             switch (usb_busy) {
00151                 case MAIN_USB_ACTIVE:
00152                     if (DECZERO(usb_busy_count) == 0) {
00153                         usb_busy = MAIN_USB_IDLE;
00154                     }
00155 
00156                     break;
00157 
00158                 case MAIN_USB_IDLE:
00159                 default:
00160                     break;
00161             }
00162 
00163             // Update USB connect status
00164             switch (usb_state) {
00165                 case MAIN_USB_DISCONNECTING:
00166 
00167                     // Wait until USB is idle before disconnecting
00168                     if (usb_busy == MAIN_USB_IDLE && (DECZERO(usb_state_count) == 0)) {
00169                         usbd_connect(0);
00170                         usb_state = MAIN_USB_DISCONNECTED;
00171                     }
00172 
00173                     break;
00174 
00175                 case MAIN_USB_CONNECTING:
00176 
00177                     // Wait before connecting
00178                     if (DECZERO(usb_state_count) == 0) {
00179                         usbd_connect(1);
00180                         usb_state = MAIN_USB_CHECK_CONNECTED;
00181                     }
00182 
00183                     break;
00184 
00185                 case MAIN_USB_CHECK_CONNECTED:
00186                     if (usbd_configured()) {
00187                         usb_state = MAIN_USB_CONNECTED;
00188                     }
00189 
00190                     break;
00191 
00192                 case MAIN_USB_DISCONNECTED:
00193                     SystemReset();
00194                     break;
00195 
00196                 case MAIN_USB_CONNECTED:
00197                 default:
00198                     break;
00199             }
00200         }
00201 
00202         // 30mS tick used for flashing LED when USB is busy
00203         if (flags & FLAGS_MAIN_30MS) {
00204             if (msc_led_usb_activity) {
00205                 
00206                 if ((msc_led_state == MAIN_LED_FLASH) || (msc_led_state == MAIN_LED_FLASH_PERMANENT)) {
00207                     // Toggle LED value
00208                     msc_led_value = (GPIO_LED_ON == msc_led_value) ? GPIO_LED_OFF : GPIO_LED_ON;
00209                     // If in flash mode stop after one cycle but in bootloader LED stays on
00210                     if ((MSC_LED_DEF == msc_led_value) && (MAIN_LED_FLASH == msc_led_state)) {    
00211                         msc_led_usb_activity = 0;
00212                         msc_led_state = MAIN_LED_DEF;
00213                     }
00214 
00215                 }else{
00216                     //LED next state is MAIN_LED_DEF
00217                     msc_led_value = MSC_LED_DEF;
00218                     msc_led_usb_activity = 0;
00219                 }
00220 
00221                 // Update hardware
00222                 gpio_set_msc_led(msc_led_value);
00223             }
00224         }
00225     }
00226 }
00227 
00228 int main(void)
00229 {
00230     // initialize vendor sdk
00231     sdk_init();
00232     // init leds and button
00233     gpio_init();
00234     // init settings
00235     config_init();
00236 
00237     // check for invalid app image or rst button press. Should be checksum or CRC but NVIC validation is better than nothing.
00238     // If the interface has set the hold in bootloader setting don't jump to app
00239     if (!gpio_get_reset_btn() && g_board_info.target_cfg && validate_bin_nvic((uint8_t *)g_board_info.target_cfg->flash_regions[0].start) && !config_ram_get_initial_hold_in_bl()) {
00240         // change to the new vector table
00241         SCB->VTOR = g_board_info.target_cfg->flash_regions[0].start; //bootloaders should only have one flash region for interface
00242         // modify stack pointer and start app
00243         modify_stack_pointer_and_start_app((*(uint32_t *)(g_board_info.target_cfg->flash_regions[0].start)), (*(uint32_t *)(g_board_info.target_cfg->flash_regions[0].start + 4)));
00244     }
00245 
00246     // config the usb interface descriptor and web auth token before USB connects
00247     //unique_string_auth_config();
00248     // either the rst pin was pressed or we have an empty app region
00249     osKernelInitialize();                 // Initialize CMSIS-RTOS
00250     osThreadNew(main_task, NULL, NULL);    // Create application main thread
00251     osKernelStart();                      // Start thread execution
00252     for (;;) {}
00253 }