diff --git a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c index 7ea5b06..7a53d3b 100644 --- a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c +++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c @@ -379,6 +379,7 @@ HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd) hpcd->battery_charging_active = 0U; USBx->BCDR &= ~(USB_BCDR_BCDEN); + USBx->BCDR &= ~(USB_BCDR_DCDEN); return HAL_OK; } diff --git a/Inc/main.h b/Inc/main.h index 511c941..3f5dcc4 100644 --- a/Inc/main.h +++ b/Inc/main.h @@ -161,6 +161,7 @@ extern uint8_t mac_address[6]; extern char error_message[80]; extern int go_back_to_sleep; extern int usb_wake_state; +extern int charging_enabled; #define CxxErrorHandler() _Error_Handler(const_cast(__FILE__), __LINE__) diff --git a/Src/main.c b/Src/main.c index 982b4c4..8553624 100644 --- a/Src/main.c +++ b/Src/main.c @@ -154,8 +154,8 @@ char error_message[80] __attribute__((section(".bss3"))) = {0}; // USB power control -- need to renegotiate USB charging in STOP mode. int go_back_to_sleep __attribute__((section(".bss3"))); int stop_now __attribute__((section(".bss3"))); -int usb_wake_state; -int usb_stop_state; +int charging_enabled __attribute__((section(".bss3"))); +int usb_wake_state __attribute__((section(".bss3"))); /* USER CODE END PV */ @@ -182,6 +182,7 @@ extern void startAudioInputTask(void const * argument); extern void startModulatorTask(void const * argument); extern void beacon(void const * argument); extern void shutdown(void const * argument); +void encode_serial_number(void); void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); @@ -247,14 +248,13 @@ void configure_gpio_for_stop() HAL_GPIO_DeInit(BAT_LEVEL_GPIO_Port, BAT_LEVEL_Pin); HAL_GPIO_DeInit(BAT_DIVIDER_GPIO_Port, BAT_DIVIDER_Pin); - usb_stop_state = HAL_GPIO_ReadPin(USB_POWER_GPIO_Port, USB_POWER_Pin); - if (HAL_GPIO_ReadPin(USB_POWER_GPIO_Port, USB_POWER_Pin) == GPIO_PIN_RESET) + if (charging_enabled) { - HAL_GPIO_WritePin(GPIOB, USB_CE_Pin, GPIO_PIN_SET); - GPIO_InitStruct.Pin = USB_CE_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_PULLUP; // CE active low. - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + HAL_GPIO_WritePin(GPIOB, USB_CE_Pin, GPIO_PIN_RESET); + } + else + { + HAL_GPIO_DeInit(USB_CE_GPIO_Port, USB_CE_Pin); // Hi-Z } // Bluetooth module @@ -340,6 +340,14 @@ void enable_debug_gpio() HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } +/** + * Shutdown is used to enter stop mode in a clean state. This ensures that + * all IP have been reset & re-initialized to their default state when + * entering low-power stop mode. This is a work-around until we can + * determine what causes a high-discharge state after USB is enabled. + * + * @param argument is unused. + */ void shutdown(void const * argument) { UNUSED(argument); @@ -387,6 +395,7 @@ int main(void) if (!(RCC->CSR & RCC_CSR_SFTRSTF)) { go_back_to_sleep = 0; stop_now = 0; + usb_wake_state = 0; } /* USER CODE END 1 */ @@ -438,45 +447,47 @@ int main(void) encode_serial_number(); - // The Bluetooth module is powered on during MX_GPIO_Init(). BT_CMD - // has a weak pull-up on the BT module and is in OD mode. Pull the - // pin low during boot to enter Bluetooth programming mode. Here the - // BT_CMD pin is switched to input mode to detect the state. The - // TNC must be reset to exit programming mode. + if (!go_back_to_sleep) { + // The Bluetooth module is powered on during MX_GPIO_Init(). BT_CMD + // has a weak pull-up on the BT module and is in OD mode. Pull the + // pin low during boot to enter Bluetooth programming mode. Here the + // BT_CMD pin is switched to input mode to detect the state. The + // TNC must be reset to exit programming mode. - // Wait for BT module to settle. - GPIO_InitTypeDef GPIO_InitStructure; + // Wait for BT module to settle. + GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.Pin = BT_CMD_Pin; - GPIO_InitStructure.Mode = GPIO_MODE_INPUT; - GPIO_InitStructure.Pull = GPIO_PULLUP; - HAL_GPIO_Init(BT_CMD_GPIO_Port, &GPIO_InitStructure); - HAL_Delay(10); + GPIO_InitStructure.Pin = BT_CMD_Pin; + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = GPIO_PULLUP; + HAL_GPIO_Init(BT_CMD_GPIO_Port, &GPIO_InitStructure); + HAL_Delay(10); - if (HAL_GPIO_ReadPin(BT_CMD_GPIO_Port, BT_CMD_Pin) == GPIO_PIN_RESET) { - // Special test mode for programming the Bluetooth module. The TNC - // has the BT_CMD pin actively being pulled low. In this case we - // power on the BT module with BT_CMD held low and wait here without - // initializing the UART. We only exit via reset. - HAL_UART_MspDeInit(&huart3); + if (HAL_GPIO_ReadPin(BT_CMD_GPIO_Port, BT_CMD_Pin) == GPIO_PIN_RESET) { + // Special test mode for programming the Bluetooth module. The TNC + // has the BT_CMD pin actively being pulled low. In this case we + // power on the BT module with BT_CMD held low and wait here without + // initializing the UART. We only exit via reset. + HAL_UART_MspDeInit(&huart3); - HAL_GPIO_WritePin(BT_RESET_GPIO_Port, BT_RESET_Pin, GPIO_PIN_RESET); - HAL_Delay(1); - HAL_GPIO_WritePin(BT_RESET_GPIO_Port, BT_RESET_Pin, GPIO_PIN_SET); - HAL_Delay(200); + HAL_GPIO_WritePin(BT_RESET_GPIO_Port, BT_RESET_Pin, GPIO_PIN_RESET); + HAL_Delay(1); + HAL_GPIO_WritePin(BT_RESET_GPIO_Port, BT_RESET_Pin, GPIO_PIN_SET); + HAL_Delay(200); - printf("Bluetooth programming mode\r\n"); + printf("Bluetooth programming mode\r\n"); - while (1); + while (1); + } + + // Not in BT programming mode. Switch BT_CMD back to OD mode. + HAL_GPIO_WritePin(BT_CMD_GPIO_Port, BT_CMD_Pin, GPIO_PIN_SET); + GPIO_InitStructure.Pin = BT_CMD_Pin; + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; + GPIO_InitStructure.Pull = GPIO_PULLUP; + HAL_GPIO_Init(BT_CMD_GPIO_Port, &GPIO_InitStructure); } - // Not in BT programming mode. Switch BT_CMD back to OD mode. - HAL_GPIO_WritePin(BT_CMD_GPIO_Port, BT_CMD_Pin, GPIO_PIN_SET); - GPIO_InitStructure.Pin = BT_CMD_Pin; - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; - GPIO_InitStructure.Pull = GPIO_PULLUP; - HAL_GPIO_Init(BT_CMD_GPIO_Port, &GPIO_InitStructure); - /* USER CODE END 2 */ /* USER CODE BEGIN RTOS_MUTEX */ @@ -581,13 +592,16 @@ int main(void) if (HAL_OPAMP_Start(&hopamp1) != HAL_OK) Error_Handler(); if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK) Error_Handler(); - // Initialize the BM78 Bluetooth module and the RTC date/time the first time we boot. - if (!bm78_initialized()) { - bm78_initialize(); - memset(error_message, 0, sizeof(error_message)); - // init_rtc_date_time(); + if (!go_back_to_sleep) { + + // Initialize the BM78 Bluetooth module and the RTC date/time the first time we boot. + if (!bm78_initialized()) { + bm78_initialize(); + memset(error_message, 0, sizeof(error_message)); + // init_rtc_date_time(); + } + else bm78_wait_until_ready(); } - else bm78_wait_until_ready(); init_ioport(); initCDC(); @@ -1269,7 +1283,7 @@ void stop2() { osThreadSuspendAll(); - GPIO_PinState usb = HAL_GPIO_ReadPin(USB_POWER_GPIO_Port, USB_POWER_Pin); + int usb_stop_state = HAL_GPIO_ReadPin(USB_POWER_GPIO_Port, USB_POWER_Pin); HAL_OPAMP_DeInit(&hopamp1); HAL_TIM_PWM_DeInit(&htim1); @@ -1279,10 +1293,11 @@ void stop2() HAL_UART_DeInit(&huart3); HAL_PWR_DisablePVD(); + USB->BCDR = 0; HAL_PWREx_DisableVddUSB(); HAL_ADCEx_EnterADCDeepPowerDownMode(&hadc1); configure_gpio_for_stop(); - power_down_vdd(); + if (!usb_stop_state) power_down_vdd(); HAL_RCCEx_DisableLSCO(); @@ -1310,6 +1325,8 @@ void stop2() if (powerOnViaUSB()) { go_back_to_sleep = 0; } + } else { + charging_enabled = 0; } HAL_NVIC_SystemReset(); } @@ -1412,20 +1429,22 @@ void init_rtc_alarm() /* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void const * argument) { - /* init code for USB_DEVICE */ - MX_USB_DEVICE_Init(); - /* USER CODE BEGIN 5 */ - printf("startDefaultTask\r\n"); UNUSED(argument); if (HAL_GPIO_ReadPin(USB_POWER_GPIO_Port, USB_POWER_Pin) == GPIO_PIN_SET) { +#ifdef KISS_LOGGING printf("VBUS detected\r\n"); +#endif + MX_USB_DEVICE_Init(); HAL_PCD_MspInit(&hpcd_USB_FS); + HAL_PCDEx_ActivateBCD(&hpcd_USB_FS); HAL_PCDEx_BCD_VBUSDetect(&hpcd_USB_FS); } else { +#ifdef KISS_LOGGING printf("VBUS not detected\r\n"); +#endif } /* Infinite loop */ for(;;) @@ -1474,6 +1493,8 @@ void _Error_Handler(char *file, int line) #endif snprintf(error_message, sizeof(error_message), "Error: %s:%d", file, line); + stop_now = 0; + go_back_to_sleep = 0; NVIC_SystemReset(); /* USER CODE END Error_Handler_Debug */ } diff --git a/TNC/IOEventTask.cpp b/TNC/IOEventTask.cpp index 3b96bab..4367529 100644 --- a/TNC/IOEventTask.cpp +++ b/TNC/IOEventTask.cpp @@ -45,18 +45,21 @@ void startIOEventTask(void const*) indicate_on(); print_startup_banner(); + } - auto& hardware = kiss::settings(); + auto& hardware = kiss::settings(); - if (! hardware.load() or reset_requested or !hardware.crc_ok()) - { - if (reset_requested) { - INFO("Hardware reset requested."); - } - - hardware.init(); - hardware.store(); + if (! hardware.load() or reset_requested or !hardware.crc_ok()) + { + if (reset_requested) { + INFO("Hardware reset requested."); } + + hardware.init(); + hardware.store(); + } + + if (!go_back_to_sleep) { hardware.debug(); audio::init_log_volume(); @@ -96,9 +99,13 @@ void startIOEventTask(void const*) } } else { if (!usb_wake_state) { + DEBUG("USB disconnected -- shutdown"); shutdown(0); } else { - osTimerStart(usbShutdownTimerHandle, 2000); + DEBUG("USB connected -- negotiate"); + HAL_GPIO_WritePin(BT_SLEEP_GPIO_Port, BT_SLEEP_Pin, + GPIO_PIN_RESET); + osTimerStart(usbShutdownTimerHandle, 5000); } } @@ -135,9 +142,11 @@ void startIOEventTask(void const*) break; case CMD_USB_DISCONNECTED: INFO("VBUS Lost"); + charging_enabled = 0; if (powerOffViaUSB()) { shutdown(0); // ***NO RETURN*** } else { + hpcd_USB_FS.Instance->BCDR = 0; HAL_PCD_MspDeInit(&hpcd_USB_FS); HAL_GPIO_WritePin(USB_CE_GPIO_Port, USB_CE_Pin, GPIO_PIN_SET); if (ioport != getUsbPort()) @@ -257,6 +266,7 @@ void startIOEventTask(void const*) break; case CMD_USB_CONNECTED: INFO("VBUS Detected"); + MX_USB_DEVICE_Init(); HAL_PCD_MspInit(&hpcd_USB_FS); hpcd_USB_FS.Instance->BCDR = 0; HAL_PCDEx_ActivateBCD(&hpcd_USB_FS); @@ -265,24 +275,26 @@ void startIOEventTask(void const*) case CMD_USB_CHARGE_ENABLE: INFO("USB charging enabled"); HAL_GPIO_WritePin(USB_CE_GPIO_Port, USB_CE_Pin, GPIO_PIN_RESET); + charging_enabled = 1; + if (go_back_to_sleep) shutdown(0); break; case CMD_USB_DISCOVERY_COMPLETE: INFO("USB discovery complete"); osTimerStop(usbShutdownTimerHandle); - if (go_back_to_sleep) shutdown(0); USBD_Start(&hUsbDeviceFS); initCDC(); break; case CMD_USB_DISCOVERY_ERROR: // This happens when powering VBUS from a bench supply. osTimerStop(usbShutdownTimerHandle); + HAL_PCDEx_DeActivateBCD(&hpcd_USB_FS); if (HAL_GPIO_ReadPin(USB_POWER_GPIO_Port, USB_POWER_Pin) == GPIO_PIN_SET) { INFO("Not a recognized USB charging device"); INFO("USB charging enabled"); HAL_GPIO_WritePin(USB_CE_GPIO_Port, USB_CE_Pin, GPIO_PIN_RESET); + charging_enabled = 1; } - hpcd_USB_FS.Instance->BCDR = 0; if (go_back_to_sleep) shutdown(0); break; case CMD_BT_DEEP_SLEEP: diff --git a/TNC/KissHardware.cpp b/TNC/KissHardware.cpp index 4cc08b5..5588979 100644 --- a/TNC/KissHardware.cpp +++ b/TNC/KissHardware.cpp @@ -26,7 +26,7 @@ int powerOffViaUSB(void) namespace mobilinkd { namespace tnc { namespace kiss { -const char FIRMWARE_VERSION[] = "1.0.0"; +const char FIRMWARE_VERSION[] = "1.0.1"; const char HARDWARE_VERSION[] = "Mobilinkd TNC3 2.1.1"; Hardware& settings()