__task void main_task(void) { // State processing uint16_t flags = 0; // LED gpio_led_state_t hid_led_value = GPIO_LED_ON; gpio_led_state_t cdc_led_value = GPIO_LED_ON; gpio_led_state_t msc_led_value = GPIO_LED_ON; // USB uint32_t usb_state_count = USB_BUSY_TIME; // thread running after usb connected started uint8_t thread_started = 0; // button state main_reset_state_t main_reset_button_state = MAIN_RESET_RELEASED; // Initialize settings config_init(); // Initialize our serial mailbox os_mbx_init(&serial_mailbox, sizeof(serial_mailbox)); // Get a reference to this task main_task_id = os_tsk_self(); // leds gpio_init(); // Turn off LED gpio_set_hid_led(GPIO_LED_ON); gpio_set_cdc_led(GPIO_LED_ON); gpio_set_msc_led(GPIO_LED_ON); // do some init with the target before USB and files are configured prerun_target_config(); // Update versions and IDs info_init(); // USB usbd_init(); vfs_user_enable(true); usbd_connect(0); usb_state = USB_CONNECTING; usb_state_count = USB_CONNECT_DELAY; // Start timer tasks os_tsk_create_user(timer_task_30mS, TIMER_TASK_30_PRIORITY, (void *)stk_timer_30_task, TIMER_TASK_30_STACK); // Target running target_set_state(RESET_RUN); while(1) { os_evt_wait_or( FLAGS_MAIN_RESET // Put target in reset state | FLAGS_MAIN_90MS // 90mS tick | FLAGS_MAIN_30MS // 30mS tick | FLAGS_MAIN_POWERDOWN // Power down interface | FLAGS_MAIN_DISABLEDEBUG // Disable target debug | FLAGS_MAIN_PROC_USB // process usb events ,NO_TIMEOUT); // Find out what event happened flags = os_evt_get(); if (flags & FLAGS_MAIN_PROC_USB) { USBD_Handler(); } if (flags & FLAGS_MAIN_RESET) { target_set_state(RESET_RUN); } if (flags & FLAGS_MAIN_POWERDOWN) { // Disable debug target_set_state(NO_DEBUG); // Disconnect USB usbd_connect(0); // Turn off LED gpio_set_hid_led(GPIO_LED_OFF); gpio_set_cdc_led(GPIO_LED_OFF); gpio_set_msc_led(GPIO_LED_OFF); // TODO: put the interface chip in sleep mode while(1); } if (flags & FLAGS_MAIN_DISABLEDEBUG) { // Disable debug target_set_state(NO_DEBUG); } if (flags & FLAGS_MAIN_90MS) { // Update USB busy status vfs_user_periodic(90); // FLAGS_MAIN_90MS // Update USB connect status switch (usb_state) { case USB_DISCONNECTING: usb_state = USB_DISCONNECTED; usbd_connect(0); break; case USB_CONNECTING: // Wait before connecting if (DECZERO(usb_state_count) == 0) { usbd_connect(1); usb_state = USB_CHECK_CONNECTED; } break; case USB_CHECK_CONNECTED: if(usbd_configured()) { if (!thread_started) { os_tsk_create_user(hid_process, DAP_TASK_PRIORITY, (void *)stk_dap_task, DAP_TASK_STACK); serial_task_id = os_tsk_create_user(serial_process, SERIAL_TASK_PRIORITY, (void *)stk_serial_task, SERIAL_TASK_STACK); thread_started = 1; } usb_state = USB_CONNECTED; } break; case USB_CONNECTED: case USB_DISCONNECTED: default: break; } } // 30mS tick used for flashing LED when USB is busy if (flags & FLAGS_MAIN_30MS) { // handle reset button without eventing switch (main_reset_button_state) { default: case MAIN_RESET_RELEASED: if (0 == gpio_get_sw_reset()) { main_reset_button_state = MAIN_RESET_PRESSED; target_forward_reset(true); } break; case MAIN_RESET_PRESSED: // ToDo: add a counter to do a mass erase or target recovery after xxx seconds of being held if (1 == gpio_get_sw_reset()) { main_reset_button_state = MAIN_RESET_TARGET; } break; case MAIN_RESET_TARGET: target_forward_reset(false); main_reset_button_state = MAIN_RESET_RELEASED; break; } if (hid_led_usb_activity && ((hid_led_state == MAIN_LED_FLASH) || (hid_led_state == MAIN_LED_FLASH_PERMANENT))) { // Flash DAP LED ONCE if (hid_led_value) { hid_led_value = GPIO_LED_OFF; } else { hid_led_value = GPIO_LED_ON; // Turn on if (hid_led_state == MAIN_LED_FLASH) { hid_led_usb_activity = 0; } } // Update hardware gpio_set_hid_led(hid_led_value); } if (msc_led_usb_activity && ((msc_led_state == MAIN_LED_FLASH) || (msc_led_state == MAIN_LED_FLASH_PERMANENT))) { // Flash MSD LED ONCE if (msc_led_value) { msc_led_value = GPIO_LED_OFF; } else { msc_led_value = GPIO_LED_ON; // Turn on if (msc_led_state == MAIN_LED_FLASH) { msc_led_usb_activity = 0; } } // Update hardware gpio_set_msc_led(msc_led_value); } if (cdc_led_usb_activity && ((cdc_led_state == MAIN_LED_FLASH) || (cdc_led_state == MAIN_LED_FLASH_PERMANENT))) { // Flash CDC LED ONCE if (cdc_led_value) { cdc_led_value = GPIO_LED_OFF; } else { cdc_led_value = GPIO_LED_ON; // Turn on if (cdc_led_state == MAIN_LED_FLASH) { cdc_led_usb_activity = 0; } } // Update hardware gpio_set_cdc_led(cdc_led_value); } } } }
void gpio_init(void) { // enable clock for GPIO port 0 LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 6); #if defined(TARGET_POWER_HOLD) // Target PowerHOLD port PIN_PWH_IOCON = PIN_PWH_IOCON_INIT; LPC_GPIO->CLR[PIN_PWH_PORT] = PIN_PWH; LPC_GPIO->DIR[PIN_PWH_PORT] |= PIN_PWH; #endif // configure GPIO-LED as output #if defined(CONTROLLED_POWER_LED) // Power led (red) PIN_POW_LED_IOCON = PIN_POW_LED_IOCON_INIT; LPC_GPIO->CLR[PIN_POW_LED_PORT] = PIN_POW_LED; LPC_GPIO->DIR[PIN_POW_LED_PORT] |= PIN_POW_LED; #endif // DAP led (green) PIN_DAP_LED_IOCON = PIN_DAP_LED_IOCON_INIT; LPC_GPIO->SET[PIN_DAP_LED_PORT] = PIN_DAP_LED; LPC_GPIO->DIR[PIN_DAP_LED_PORT] |= PIN_DAP_LED; // MSD led (red) PIN_MSD_LED_IOCON = PIN_MSD_LED_IOCON_INIT; LPC_GPIO->SET[PIN_MSD_LED_PORT] = PIN_MSD_LED; LPC_GPIO->DIR[PIN_MSD_LED_PORT] |= PIN_MSD_LED; // Serial LED (blue) PIN_CDC_LED_IOCON = PIN_CDC_LED_IOCON_INIT; LPC_GPIO->SET[PIN_CDC_LED_PORT] = PIN_CDC_LED; LPC_GPIO->DIR[PIN_CDC_LED_PORT] |= PIN_CDC_LED; // configure Button(s) as input PIN_RESET_IN_IOCON = PIN_RESET_IN_IOCON_INIT; LPC_GPIO->DIR[PIN_RESET_IN_PORT] &= ~PIN_RESET_IN; PIN_RESET_IN_FWRD_IOCON = PIN_RESET_IN_FWRD_IOCON_INIT; LPC_GPIO->DIR[PIN_RESET_IN_FWRD_PORT] &= ~PIN_RESET_IN_FWRD; #if !defined(PIN_nRESET_FET_DRIVE) // open drain logic for reset button PIN_nRESET_IOCON = PIN_nRESET_IOCON_INIT; LPC_GPIO->CLR[PIN_nRESET_PORT] = PIN_nRESET; LPC_GPIO->DIR[PIN_nRESET_PORT] &= ~PIN_nRESET; #else // FET drive logic for reset button PIN_nRESET_IOCON = PIN_nRESET_IOCON_INIT; LPC_GPIO->CLR[PIN_nRESET_PORT] = PIN_nRESET; LPC_GPIO->DIR[PIN_nRESET_PORT] |= PIN_nRESET; #endif /* Enable AHB clock to the FlexInt, GroupedInt domain. */ LPC_SYSCON->SYSAHBCLKCTRL |= ((1 << 19) | (1 << 23) | (1 << 24)); // Give the cap on the reset button time to charge busy_wait(10000); if ((gpio_get_sw_reset() == 0) || config_ram_get_initial_hold_in_bl()) { IRQn_Type irq; // Disable SYSTICK timer and interrupt before calling into ISP SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk); // Disable all nvic interrupts for (irq = (IRQn_Type)0; irq < (IRQn_Type)32; irq++) { NVIC_DisableIRQ(irq); NVIC_ClearPendingIRQ(irq); } // If switching to "bootloader" mode then setup the watchdog // so it will exit CRP mode after ~30 seconds if (config_ram_get_initial_hold_in_bl()) { LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 15); // Enable watchdog module LPC_SYSCON->PDRUNCFG &= ~(1 << 6); // Enable watchdog clock (WDOSC) LPC_SYSCON->WDTOSCCTRL = (0xF << 5); // Set max frequency - 2.3MHz LPC_WWDT->CLKSEL = (1 << 0); // Select watchdog clock LPC_WWDT->TC = 0x00FFFFFF; // Set time to reset to ~29s LPC_WWDT->MOD = (1 << 0) | (1 << 1); // Enable watchdog and set reset LPC_WWDT->FEED = 0xAA; // Enable watchdog LPC_WWDT->FEED = 0x55; } ReinvokeISP(); } }