Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // usbpd_dpm_user.c
- [...]
- /**
- * @brief UserCableDetection reporting events on a specified port from CAD layer.
- * @param PortNum The handle of the port
- * @param State CAD state
- * @retval None
- */
- void USBPD_DPM_UserCableDetection(uint8_t PortNum, USBPD_CAD_EVENT State)
- {
- /* USER CODE BEGIN USBPD_DPM_UserCableDetection */
- user_usbpd_cable_detection_event(PortNum, State);
- /* USER CODE END USBPD_DPM_UserCableDetection */
- }
- /**
- * @brief function used to manage user timer.
- * @param PortNum Port number
- * @retval None
- */
- void USBPD_DPM_UserTimerCounter(uint8_t PortNum)
- {
- /* USER CODE BEGIN USBPD_DPM_UserTimerCounter */
- /* USER CODE END USBPD_DPM_UserTimerCounter */
- }
- /**
- * @}
- */
- /** @defgroup USBPD_USER_EXPORTED_FUNCTIONS_GROUP2 USBPD USER Exported Callbacks functions called by PE
- * @{
- */
- /**
- * @brief Callback function called by PE to inform DPM about PE event.
- * @param PortNum The current port number
- * @param EventVal @ref USBPD_NotifyEventValue_TypeDef
- * @retval None
- */
- void USBPD_DPM_Notification(uint8_t PortNum, USBPD_NotifyEventValue_TypeDef EventVal)
- {
- /* USER CODE BEGIN USBPD_DPM_Notification */
- user_usbpd_event_notification(PortNum, EventVal);
- /* USER CODE END USBPD_DPM_Notification */
- }
- /**
- * @brief Callback function called by PE layer when HardReset message received from PRL
- * @param PortNum The current port number
- * @param CurrentRole the current role
- * @param Status status on hard reset event
- * @retval None
- */
- void USBPD_DPM_HardReset(uint8_t PortNum, USBPD_PortPowerRole_TypeDef CurrentRole, USBPD_HR_Status_TypeDef Status)
- {
- /* USER CODE BEGIN USBPD_DPM_HardReset */
- uart_printf("DPM user debug [%u]: HardReset(), role=%lu, status=%u\r\n", PortNum, CurrentRole, Status);
- if (CurrentRole == USBPD_PORTPOWERROLE_SRC) {
- switch (Status)
- {
- case USBPD_HR_STATUS_WAIT_VBUS_VSAFE0V:
- DPM_TurnOffPower(PortNum, CurrentRole);
- break;
- case USBPD_HR_STATUS_WAIT_VBUS_VSAFE5V:
- DPM_TurnOnPower(PortNum, CurrentRole);
- break;
- default:
- break;
- }
- }
- /* USER CODE END USBPD_DPM_HardReset */
- }
- [...]
- /* USER CODE BEGIN USBPD_USER_PRIVATE_FUNCTIONS */
- static void DPM_AssertRd(uint8_t port) {
- USBPD_CAD_AssertRd(port);
- }
- static void DPM_AssertRp(uint8_t port) {
- USBPD_CAD_AssertRp(port);
- }
- static USBPD_StatusTypeDef DPM_TurnOnPower(uint8_t PortNum, USBPD_PortPowerRole_TypeDef Role)
- {
- USBPD_StatusTypeDef status;
- /* Enable the output */
- status = USBPD_PWR_IF_VBUSEnable(PortNum);
- if (USBPD_PORTPOWERROLE_src== Role)
- {
- /* Enable the output */
- USBPD_DPM_WaitForTime(20);
- }
- else
- {
- /* stop current sink */
- }
- return status;
- }
- static USBPD_StatusTypeDef DPM_TurnOffPower(uint8_t PortNum, USBPD_PortPowerRole_TypeDef Role)
- {
- USBPD_StatusTypeDef status;
- status = USBPD_PWR_IF_VBUSDisable(PortNum);
- return status;
- }
- /**
- * @brief Find PDO index that offers the most power without exceeding max sink voltage.
- * @param PortNum Port number
- * @param PtrRequestPowerDetails Sink requested power details structure pointer
- * @retval Index of PDO within source capabilities message (DPM_NO_SRC_PDO_FOUND indicating not found)
- */
- static uint32_t DPM_FindVoltageIndex(uint32_t PortNum, USBPD_DPM_SNKPowerRequestDetails_TypeDef* PtrRequestPowerDetails, uint8_t Method)
- {
- uint32_t *ptpdoarray;
- USBPD_PDO_TypeDef pdo;
- uint32_t voltage;
- uint32_t reqvoltage;
- uint32_t nbpdo;
- uint32_t allowablepower;
- uint32_t selpower;
- uint32_t allowablecurrent;
- uint32_t selcurrent;
- uint32_t curr_index = DPM_NO_SRC_PDO_FOUND;
- uint32_t temp_index;
- USBPD_USER_SettingsTypeDef *puser = (USBPD_USER_SettingsTypeDef *)&DPM_USER_Settings[PortNum];
- allowablepower = 0;
- selpower = 0;
- reqvoltage = 0;
- voltage = 0;
- selcurrent = 0;
- /* Search PDO index among Source PDO of Port */
- nbpdo = DPM_Ports[PortNum].DPM_NumberOfRcvSRCPDO;
- ptpdoarray = DPM_Ports[PortNum].DPM_ListOfRcvSRCPDO;
- /* search the best PDO in the list of source PDOs */
- for (temp_index = 0; temp_index < nbpdo; temp_index++)
- {
- pdo.d32 = ptpdoarray[temp_index];
- /* Check if the received source PDO is matching any of the SNK PDO */
- allowablepower = 0;
- if (USBPD_TRUE == USBPD_DPM_SNK_EvaluateMatchWithSRCPDO(PortNum, pdo.d32, &voltage, &allowablepower))
- {
- allowablecurrent = (allowablepower / voltage) * 1000U;
- /* Choose the best PDO depending on the user preferences */
- switch (Method)
- {
- case PDO_SEL_METHOD_MAX_PWR:
- if (allowablepower > selpower)
- {
- /* Consider the current PDO the best one until now */
- curr_index = temp_index;
- selpower = allowablepower;
- reqvoltage = voltage;
- selcurrent = allowablecurrent;
- }
- break;
- case PDO_SEL_METHOD_MIN_PWR:
- if ((allowablepower < selpower) || (selpower == 0))
- {
- /* Consider the current PDO the best one until now */
- curr_index = temp_index;
- selpower = allowablepower;
- reqvoltage = voltage;
- selcurrent = allowablecurrent;
- }
- break;
- case PDO_SEL_METHOD_MAX_VOLT:
- if (voltage > reqvoltage)
- {
- /* Consider the current PDO the best one until now */
- curr_index = temp_index;
- selpower = allowablepower;
- reqvoltage = voltage;
- selcurrent = allowablecurrent;
- }
- break;
- case PDO_SEL_METHOD_MIN_VOLT:
- if ((voltage < reqvoltage) || (reqvoltage == 0))
- {
- /* Consider the current PDO the best one until now */
- curr_index = temp_index;
- selpower = allowablepower;
- reqvoltage = voltage;
- selcurrent = allowablecurrent;
- }
- break;
- case PDO_SEL_METHOD_MAX_CUR:
- if (allowablecurrent > selcurrent)
- {
- /* Consider the current PDO the best one until now */
- curr_index = temp_index;
- selpower = allowablepower;
- reqvoltage = voltage;
- selcurrent = allowablecurrent;
- }
- break;
- case PDO_SEL_METHOD_MIN_CUR:
- if ((allowablecurrent < selcurrent) || (selcurrent == 0))
- {
- /* Consider the current PDO the best one until now */
- curr_index = temp_index;
- selpower = allowablepower;
- reqvoltage = voltage;
- selcurrent = allowablecurrent;
- }
- break;
- default:
- /* Default behavior: last PDO is selected */
- curr_index = temp_index;
- selpower = allowablepower;
- reqvoltage = voltage;
- selcurrent = allowablecurrent;
- }
- }
- }
- /* If a suitable PDO was found */
- if (curr_index != DPM_NO_SRC_PDO_FOUND)
- {
- /* Fill the request power details */
- PtrRequestPowerDetails->MaxOperatingCurrentInmAunits = puser->DPM_SNKRequestedPower.MaxOperatingCurrentInmAunits;
- PtrRequestPowerDetails->OperatingCurrentInmAunits = (1000U * selpower) / reqvoltage;
- PtrRequestPowerDetails->MaxOperatingPowerInmWunits = puser->DPM_SNKRequestedPower.MaxOperatingPowerInmWunits;
- PtrRequestPowerDetails->OperatingPowerInmWunits = selpower;
- PtrRequestPowerDetails->RequestedVoltageInmVunits = reqvoltage;
- #ifdef USER_USBPD_TRACE
- uart_printf("DPM user debug [%lu]: Selected sink PDO has V=%lumV I=%lumA\r\n", PortNum, reqvoltage,
- PtrRequestPowerDetails->OperatingCurrentInmAunits);
- #endif
- }
- return curr_index;
- }
- /**
- * @brief Build RDO to be used in Request message according to selected PDO from received SRC Capabilities
- * @param PortNum Port number
- * @param IndexSrcPDO Index on the selected SRC PDO (value between 0 to 6)
- * @param PtrRequestPowerDetails Sink requested power details structure pointer
- * @param Rdo Pointer on the RDO
- * @param PtrPowerObject Pointer on the selected power object
- * @retval None
- */
- void DPM_SNK_BuildRDOfromSelectedPDO(uint8_t PortNum, uint8_t IndexSrcPDO,
- USBPD_DPM_SNKPowerRequestDetails_TypeDef *PtrRequestPowerDetails,
- USBPD_SNKRDO_TypeDef* Rdo, USBPD_CORE_PDO_Type_TypeDef *PtrPowerObject)
- {
- uint32_t mv = 0, mw = 0, ma = 0, size;
- USBPD_PDO_TypeDef pdo;
- USBPD_SNKRDO_TypeDef rdo;
- USBPD_HandleTypeDef *pdhandle = &DPM_Ports[PortNum];
- USBPD_USER_SettingsTypeDef *puser = (USBPD_USER_SettingsTypeDef *)&DPM_USER_Settings[PortNum];
- uint32_t snkpdolist[USBPD_MAX_NB_PDO];
- USBPD_PDO_TypeDef snk_fixed_pdo;
- /* Initialize RDO */
- rdo.d32 = 0;
- /* Read SNK PDO list for retrieving useful data to fill in RDO */
- USBPD_PWR_IF_GetPortPDOs(PortNum, USBPD_CORE_DATATYPE_SNK_PDO, (uint8_t*)&snkpdolist[0], &size);
- /* Store value of 1st SNK PDO (Fixed) in local variable */
- snk_fixed_pdo.d32 = snkpdolist[0];
- /* Set common fields in RDO */
- pdo.d32 = pdhandle->DPM_ListOfRcvSRCPDO[0];
- rdo.GenericRDO.USBCommunicationsCapable = snk_fixed_pdo.SNKFixedPDO.USBCommunicationsCapable;
- if (USBPD_SPECIFICATION_REV2 < DPM_Params[PortNum].PE_SpecRevision)
- {
- rdo.FixedVariableRDO.UnchunkedExtendedMessage = DPM_Settings[PortNum].PE_PD3_Support.d.PE_UnchunkSupport;
- // DPM_Params[PortNum].PE_UnchunkSupport = USBPD_FALSE;
- // /* Set unchuncked bit if supported by port partner;*/
- // if (USBPD_TRUE == pdo.SRCFixedPDO.UnchunkedExtendedMessage)
- // {
- // DPM_Params[PortNum].PE_UnchunkSupport = USBPD_TRUE;
- // }
- }
- /* If no valid SNK PDO or if no SRC PDO match found (index>=nb of valid received SRC PDOs */
- if ((size < 1) || (IndexSrcPDO >= pdhandle->DPM_NumberOfRcvSRCPDO))
- {
- /* USBPD_DPM_EvaluateCapabilities: Mismatch, could not find desired pdo index */
- #ifdef _TRACE
- USBPD_TRACE_Add(USBPD_TRACE_DEBUG, PortNum, 0, (uint8_t *)"DPM_SNK_BuildRDOfromSelectedPDO: Pb in SRC PDO selection",
- sizeof("DPM_SNK_BuildRDOfromSelectedPDO: Pb in SRC PDO selection"));
- #endif /* _TRACE */
- rdo.FixedVariableRDO.ObjectPosition = 1;
- rdo.FixedVariableRDO.OperatingCurrentIn10mAunits = pdo.SRCFixedPDO.MaxCurrentIn10mAunits;
- rdo.FixedVariableRDO.MaxOperatingCurrent10mAunits = pdo.SRCFixedPDO.MaxCurrentIn10mAunits;
- rdo.FixedVariableRDO.CapabilityMismatch = 1;
- rdo.FixedVariableRDO.USBCommunicationsCapable = snk_fixed_pdo.SNKFixedPDO.USBCommunicationsCapable;
- DPM_Ports[PortNum].DPM_RequestedCurrent = puser->DPM_SNKRequestedPower.MaxOperatingCurrentInmAunits;
- /* USBPD_DPM_EvaluateCapabilities: Mismatch, could not find desired pdo index */
- pdhandle->DPM_RequestDOMsg = rdo.d32;
- return;
- }
- /* Set the Object position */
- rdo.GenericRDO.ObjectPosition = IndexSrcPDO + 1;
- rdo.GenericRDO.NoUSBSuspend = 0;
- /* Extract power information from Power Data Object */
- pdo.d32 = pdhandle->DPM_ListOfRcvSRCPDO[IndexSrcPDO];
- *PtrPowerObject = pdo.GenericPDO.PowerObject;
- /* Retrieve request details from SRC PDO selection */
- mv = PtrRequestPowerDetails->RequestedVoltageInmVunits;
- ma = PtrRequestPowerDetails->OperatingCurrentInmAunits;
- switch(pdo.GenericPDO.PowerObject)
- {
- case USBPD_CORE_PDO_TYPE_FIXED:
- case USBPD_CORE_PDO_TYPE_VARIABLE:
- {
- /* USBPD_DPM_EvaluateCapabilities: Mismatch, less power offered than the operating power */
- ma = USBPD_MIN(ma, puser->DPM_SNKRequestedPower.MaxOperatingCurrentInmAunits);
- mw = (ma * mv)/1000; /* mW */
- DPM_Ports[PortNum].DPM_RequestedCurrent = ma;
- rdo.FixedVariableRDO.OperatingCurrentIn10mAunits = ma / 10;
- rdo.FixedVariableRDO.MaxOperatingCurrent10mAunits = ma / 10;
- if(mw < puser->DPM_SNKRequestedPower.OperatingPowerInmWunits)
- {
- /* USBPD_DPM_EvaluateCapabilities: Mismatch, less power offered than the operating power */
- rdo.FixedVariableRDO.MaxOperatingCurrent10mAunits = puser->DPM_SNKRequestedPower.MaxOperatingCurrentInmAunits / 10;
- rdo.FixedVariableRDO.CapabilityMismatch = 1;
- }
- }
- break;
- case USBPD_CORE_PDO_TYPE_BATTERY:
- {
- /* USBPD_DPM_EvaluateCapabilities: Battery Request Data Object */
- mw = USBPD_MIN(PtrRequestPowerDetails->OperatingPowerInmWunits, puser->DPM_SNKRequestedPower.MaxOperatingPowerInmWunits); /* mW */
- ma = (1000 * mw) / mv; /* mA */
- ma = USBPD_MIN(ma, puser->DPM_SNKRequestedPower.MaxOperatingCurrentInmAunits);
- DPM_Ports[PortNum].DPM_RequestedCurrent = ma;
- mw = (ma * mv)/1000; /* mW */
- rdo.BatteryRDO.OperatingPowerIn250mWunits = mw / 250;
- rdo.BatteryRDO.MaxOperatingPowerIn250mWunits = mw / 250;
- if(mw < puser->DPM_SNKRequestedPower.OperatingPowerInmWunits)
- {
- /* Mismatch, less power offered than the operating power */
- rdo.BatteryRDO.CapabilityMismatch = 1;
- }
- }
- break;
- // case USBPD_CORE_PDO_TYPE_APDO:
- // {
- // DPM_Ports[PortNum].DPM_RequestedCurrent = ma;
- // rdo.ProgRDO.ObjectPosition = IndexSrcPDO + 1;
- // rdo.ProgRDO.OperatingCurrentIn50mAunits = ma / 50;
- // rdo.ProgRDO.OutputVoltageIn20mV = mv / 20;
- // }
- // break;
- default:
- break;
- }
- pdhandle->DPM_RequestDOMsg = rdo.d32;
- pdhandle->DPM_RDOPosition = rdo.GenericRDO.ObjectPosition;
- Rdo->d32 = pdhandle->DPM_RequestDOMsg;
- /* Get the requested voltage */
- pdhandle->DPM_RequestedVoltage = mv;
- }
- /* USER CODE END USBPD_USER_PRIVATE_FUNCTIONS */
- [...]
- // user_usbpd.c
- struct {
- enum {
- SOURCE,
- SINK
- } role;
- USBPD_PWR_VBUSDetectCallbackFunc* vbus_detect_callback;
- } drp = {
- .role = SOURCE,
- .vbus_detect_callback = NULL
- };
- /**
- * @brief Get actual voltage level measured on the VBUS line.
- * @param Instance Type-C port identifier
- * This parameter can be take one of the following values:
- * @arg @ref USBPD_PWR_TYPE_C_PORT_1
- * @arg @ref USBPD_PWR_TYPE_C_PORT_2
- * @param pVoltage Pointer on measured voltage level (in mV)
- * @retval BSP status
- */
- int32_t BSP_USBPD_PWR_VBUSGetVoltage(uint32_t Instance, uint32_t *pVoltage) {
- switch (Instance) {
- case USBPD_PWR_TYPE_C_PORT_1: // UFP: port 0, UCPD1
- *pVoltage = 1000 * (uint32_t)(V_VBUS_UFP() + 0.5f);
- return BSP_ERROR_NONE;
- case USBPD_PWR_TYPE_C_PORT_2: // DRP: port 1, UCPD2
- *pVoltage = 1000 * (uint32_t)(V_VBUS_DRP() + 0.5f);
- return BSP_ERROR_NONE;
- default:
- return BSP_ERROR_WRONG_PARAM;
- }
- }
- /**
- * @brief Get actual current level measured on the VBUS line.
- * @param Instance Type-C port identifier
- * This parameter can be take one of the following values:
- * @arg @ref USBPD_PWR_TYPE_C_PORT_1
- * @arg @ref USBPD_PWR_TYPE_C_PORT_2
- * @param pCurrent Pointer on measured current level (in mA)
- * @retval BSP status
- */
- int32_t BSP_USBPD_PWR_VBUSGetCurrent(uint32_t Instance, int32_t *pCurrent) {
- switch (Instance) {
- case USBPD_PWR_TYPE_C_PORT_1: // UFP: port 0, UCPD1
- *pCurrent = 0;
- return BSP_ERROR_NONE;
- case USBPD_PWR_TYPE_C_PORT_2: // DRP: port 1, UCPD2
- *pCurrent = 1000 * (uint32_t)(I_DRP() + 0.5f);
- return BSP_ERROR_NONE;
- default:
- return BSP_ERROR_WRONG_PARAM;
- }
- }
- /**
- * Called by remapped trace macros in user_usbpd_trace.h. These macros are called by
- * various USBPD files, and print USBPD debug info.
- */
- void user_usbpd_trace(UserTraceUSBPD trace_type, uint8_t port, char* message) {
- const char type_pwr_user_dbg[] = "DPM pwr user debug";
- const char type_pwr_if_dbg[] = "DPM pwr if debug";
- const char type_dpm_user_dbg[] = "DPM user debug";
- const char type_dpm_user_err[] = "DPM user error";
- const char type_unknown[] = "UNKNOWN";
- const char* type_ptr;
- switch (trace_type) {
- case PD_TRACE_PWR_USER_DEBUG:
- type_ptr = type_pwr_user_dbg;
- break;
- case PD_TRACE_PWR_IF_DEBUG:
- type_ptr = type_pwr_if_dbg;
- break;
- case PD_TRACE_DPM_USER_DEBUG:
- type_ptr = type_dpm_user_dbg;
- break;
- case PD_TRACE_DPM_USER_ERROR:
- type_ptr = type_dpm_user_err;
- break;
- default:
- type_ptr = type_unknown;
- }
- uart_printf("%s [%u]: %s\r\n", type_ptr, port, message);
- }
- /**
- * Overrides default error handler. assert() will tell you which error handler got called (the default solution is
- * a simple `while(1);` ).
- */
- void USBPD_DPM_ErrorHandler(void) {
- assert(false);
- }
- /**
- * Read V_UFP in blocking mode. For use only when the main ADC DMA loop is not active, ie. before the FreeRTOS
- * scheduler is started.
- */
- float adc_get_v_ufp_blocking(void) {
- // HAL_ADCEx_Calibration_Start(&hadc1);
- while (!LL_ADC_IsActiveFlag_CCRDY(ADC1));
- // Save current sequencer settings to restore later
- uint32_t channels_initial = LL_ADC_REG_GetSequencerChannels(ADC1);
- // Enable only UFP channel
- LL_ADC_REG_SetSequencerChannels(ADC1, 0x1);
- // Wait for changes to take effect
- while (!LL_ADC_IsActiveFlag_CCRDY(ADC1));
- HAL_ADC_Start(&hadc1);
- while (!LL_ADC_IsActiveFlag_EOC(ADC1));
- float v_ufp = VI_MONITOR_SCALE_FACTORS[0] * (float) (ADC1->DR);
- HAL_ADC_Stop(&hadc1);
- LL_ADC_REG_SetSequencerChannels(ADC1, channels_initial);
- while (!LL_ADC_IsActiveFlag_CCRDY(ADC1));
- return v_ufp;
- }
- /**
- * Init function for power delivery. Runs before the FreeRTOS scheduler starts.
- */
- int32_t BSP_USBPD_PWR_Init(uint32_t Instance) {
- if (Instance >= USBPD_PWR_INSTANCES_NBR) {
- return BSP_ERROR_WRONG_PARAM;
- }
- if (Instance == DRP_PORT_NUM) {
- tcpp03_init();
- } else {
- // Disable dead battery in port protection IC. UCPD hardware will handle this from now on.
- HAL_GPIO_WritePin(nDB_UFP_GPIO_Port, nDB_UFP_Pin, 1);
- }
- return BSP_ERROR_NONE;
- }
- /**
- * Called from USBPD_DPM_UserCableDetection ISR when a port partner (phone/computer) is attached or detached. Sets the USB
- * redriver mux orientation based on the detected voltages on the CC1/CC2 pins. Also saves any changes to implicit
- * contracts to g_ufp_implicit_contract / g_drp_implicit_contract.
- *
- * port: port number (0=UFP, 1=DRP)
- * event: attach/detach/other event type (see enum definition)
- */
- void user_usbpd_cable_detection_event(uint8_t port, USBPD_CAD_EVENT event) {
- assert(port <= 1);
- update_implicit_contract(port);
- char contract_str[8];
- user_usbpd_implicit_contract_enum_to_string(port, contract_str);
- uart_printf("Cable detect event [%u]: %s\r\n", port, contract_str);
- uart_printf("Cable detect event: USBPD contract type from DPM_Params: %u\r\n", DPM_Params[port].PE_Power);
- if (port == UFP_PORT_NUM) {
- switch (event) {
- case USBPD_CAD_EVENT_ATTEMC:
- case USBPD_CAD_EVENT_ATTACHED:
- if (g_ufp_implicit_contract != IMPL_CONTRACT_NONE || V_VBUS_UFP() > 4.0f) {
- // UFP is supplying power, isolate DRP VBUS.
- // tcpp03_set_isolated();
- }
- DPM_Ports[port].DPM_IsConnected = 1;
- break;
- }
- }
- if (port == DRP_PORT_NUM) {
- if (cable_flipped(port)) { // If voltage is on CC2 pin
- HAL_GPIO_WritePin(USB_MUX_SEL_GPIO_Port, USB_MUX_SEL_Pin, 0); // Route TX/RX_AP <-> TX/RX_Con_2
- } else {
- HAL_GPIO_WritePin(USB_MUX_SEL_GPIO_Port, USB_MUX_SEL_Pin, 1); // Route TX/RX_AP <-> TX/RX_Con_1
- }
- switch (event) {
- case USBPD_CAD_EVENT_ATTEMC:
- case USBPD_CAD_EVENT_ATTACHED:
- if (DPM_Params[port].PE_PowerRole == USBPD_PORTPOWERROLE_SRC) {
- USBPD_PWR_IF_VBUSEnable(port);
- }
- DPM_Ports[port].DPM_IsConnected = 1;
- break;
- case USBPD_CAD_EVENT_DETACHED:
- case USBPD_CAD_EVENT_EMC:
- default:
- if (DPM_Params[port].PE_PowerRole == USBPD_PORTPOWERROLE_SRC) {
- USBPD_PWR_IF_VBUSDisable(port);
- }
- memset(&DPM_Ports[port], 0, sizeof(DPM_Ports[port]));
- break;
- }
- }
- }
- bool cable_flipped(uint8_t port) {
- UCPD_TypeDef* ucpd;
- if (port == 0) {
- ucpd = UCPD1;
- } else {
- ucpd = UCPD2;
- }
- return LL_UCPD_GetTypeCVstateCC2(ucpd) != LL_UCPD_SNK_CC2_VOPEN;
- }
- /**
- * Updates the global implicit contract variable for a specific port.
- *
- * Note that this doesn't check for VBUS voltage -- a noncompliant cable could
- * still apply voltage to VBUS without signalling an implicit contract via the CC pins.
- */
- void update_implicit_contract(uint8_t port) {
- UCPD_TypeDef* ucpd;
- uint8_t* g_new_implicit_contract;
- if (port == 0) {
- ucpd = UCPD1;
- g_new_implicit_contract = &g_ufp_implicit_contract;
- } else {
- ucpd = UCPD2;
- g_new_implicit_contract = &g_drp_implicit_contract;
- }
- // Work out the implicit contract from the CC pins
- switch (LL_UCPD_GetTypeCVstateCC1(ucpd)) {
- case LL_UCPD_SNK_CC1_VRP30A:
- *g_new_implicit_contract = IMPL_CONTRACT_3A;
- break;
- case LL_UCPD_SNK_CC1_VRP15A:
- *g_new_implicit_contract = IMPL_CONTRACT_1_5A;
- break;
- case LL_UCPD_SNK_CC1_VRP:
- *g_new_implicit_contract = IMPL_CONTRACT_DEFAULT;
- break;
- case LL_UCPD_SNK_CC1_VOPEN:
- switch (LL_UCPD_GetTypeCVstateCC2(ucpd)) {
- case LL_UCPD_SNK_CC2_VRP30A:
- *g_new_implicit_contract = IMPL_CONTRACT_3A;
- break;
- case LL_UCPD_SNK_CC2_VRP15A:
- *g_new_implicit_contract = IMPL_CONTRACT_1_5A;
- break;
- case LL_UCPD_SNK_CC2_VRP:
- *g_new_implicit_contract = IMPL_CONTRACT_DEFAULT;
- break;
- case LL_UCPD_SNK_CC2_VOPEN:
- *g_new_implicit_contract = IMPL_CONTRACT_NONE;
- break;
- }
- break;
- }
- }
- void user_usbpd_implicit_contract_enum_to_string(ImplicitContract in_enum, char out_string[8]) {
- switch (in_enum) {
- case IMPL_CONTRACT_NONE:
- strcpy(out_string, "none");
- break;
- case IMPL_CONTRACT_DEFAULT:
- strcpy(out_string, "default");
- break;
- case IMPL_CONTRACT_1_5A:
- strcpy(out_string, "1.5A");
- break;
- case IMPL_CONTRACT_3A:
- strcpy(out_string, "3A");
- break;
- }
- }
- /**
- * @brief Check if a given source PDO matches sink requirements. Returns USBPD_TRUE if src_v == sink_v && src_i >= sink_i.
- * Customised from the original, largely by removing lots of code for variable / battery PDOs.
- *
- * @param PortNum Port number
- * @param SrcPDO Selected SRC PDO (32 bits)
- * @param PtrRequestedVoltage Pointer to voltage value that could be provided if SrcPDO is requested (only valid if USBPD_TRUE is returned) in mV
- * @param PtrRequestedPower Pointer to power value that could be provided if SrcPDO is requested (only valid if USBPD_TRUE is returned) in mW
- * @retval USBPD_FALSE or USBPD_TRUE (USBPD_TRUE returned if SrcPDO is matches SNK profile)
- */
- uint32_t USBPD_DPM_SNK_EvaluateMatchWithSRCPDO(uint8_t PortNum, uint32_t SrcPDO, uint32_t* PtrRequestedVoltage, uint32_t* PtrRequestedPower) {
- USBPD_PDO_TypeDef srcpdo, snkpdo;
- uint32_t match = USBPD_FALSE;
- uint32_t nbsnkpdo;
- uint32_t snkpdo_array[USBPD_MAX_NB_PDO];
- /* Retrieve SNK PDO list from PWR_IF storage : PDO values + nb of u32 written by PWR_IF (nb of PDOs) */
- USBPD_PWR_IF_GetPortPDOs(PortNum, USBPD_CORE_DATATYPE_SNK_PDO, (uint8_t*)snkpdo_array, &nbsnkpdo);
- if (nbsnkpdo == 0) {
- return USBPD_FALSE;
- }
- uint32_t max_req_pwr_mW = 0;
- uint32_t max_req_v_mV = 0;
- srcpdo.d32 = SrcPDO;
- if (srcpdo.GenericPDO.PowerObject == USBPD_CORE_PDO_TYPE_FIXED) {
- uint16_t v_src_mV = 50 * srcpdo.SRCFixedPDO.VoltageIn50mVunits;
- uint16_t i_src_mA = 10 * srcpdo.SRCFixedPDO.MaxCurrentIn10mAunits;
- /* Loop through SNK PDO list */
- for (size_t i = 0; i < nbsnkpdo; i++) {
- uint32_t req_pwr_mW = 0;
- uint32_t req_v_mV = 0;
- /* Retrieve SNK PDO value according to its type */
- snkpdo.d32 = snkpdo_array[i];
- if (snkpdo.GenericPDO.PowerObject == USBPD_CORE_PDO_TYPE_FIXED) {
- uint16_t v_snk_mV = 50 * snkpdo.SNKFixedPDO.VoltageIn50mVunits;
- uint16_t i_snk_mA = 10 * snkpdo.SNKFixedPDO.OperationalCurrentIn10mAunits;
- /* Match if :
- SNK Voltage == SRC Voltage
- &&
- SNK Op Current <= SRC Max Current
- Requested Voltage : SNK Voltage
- Requested Op Current : SNK Op Current
- Requested Max Current : SNK Op Current
- */
- if ((v_snk_mV == v_src_mV) && (i_snk_mA <= i_src_mA)) {
- req_pwr_mW = (uint32_t) v_snk_mV * (uint32_t) i_snk_mA / 1000;
- req_v_mV = v_snk_mV;
- }
- }
- if (req_pwr_mW > max_req_pwr_mW) {
- match = USBPD_TRUE;
- max_req_pwr_mW = req_pwr_mW;
- max_req_v_mV = req_v_mV;
- }
- }
- } else { // Non-fixed PDOs are not supported
- return USBPD_FALSE;
- }
- if (max_req_pwr_mW > 0) {
- *PtrRequestedPower = max_req_pwr_mW;
- *PtrRequestedVoltage = max_req_v_mV;
- }
- // if (match) {
- // uart_printf("Matched source PDO %08lx, (V=%lumV I=%lumA)\r\n", SrcPDO, max_req_v_mV, max_req_pwr_mW/max_req_v_mV*1000);
- // } else {
- // uart_printf("Failed to match source PDO %08lx\r\n", SrcPDO);
- // }
- return match;
- }
- void user_usbpd_event_notification(uint8_t port, USBPD_NotifyEventValue_TypeDef event) {
- assert(port <= 1);
- switch(event) {
- case USBPD_NOTIFY_POWER_EXPLICIT_CONTRACT: // Explicit contract ready, power available
- // Load the PDO that the device policy manager selected
- USBPD_PDO_TypeDef pdo;
- uint32_t dpo_pos = DPM_Ports[port].DPM_RDOPosition - 1;
- pdo.d32 = DPM_Ports[port].DPM_ListOfRcvSRCPDO[dpo_pos];
- uint16_t v_mV = 50 * pdo.SRCFixedPDO.VoltageIn50mVunits;
- uint16_t i_mA = 10 * pdo.SRCFixedPDO.MaxCurrentIn10mAunits;
- if (port == DRP_PORT_NUM) {
- g_drp_explicit_contract.v_mV = v_mV;
- g_drp_explicit_contract.i_mA = i_mA;
- } else {
- g_ufp_explicit_contract.v_mV = v_mV;
- g_ufp_explicit_contract.i_mA = i_mA;
- }
- g_power_update = true;
- uart_printf("DPM user debug [%u]: Explicit contract established (V=%umV I=%umA)\r\n", port, v_mV, i_mA);
- break;
- case USBPD_NOTIFY_REQUEST_ACCEPTED:
- break;
- case USBPD_NOTIFY_REQUEST_REJECTED:
- case USBPD_NOTIFY_REQUEST_WAIT:
- break;
- case USBPD_NOTIFY_POWER_SNK_READY:
- DPM_USER_DEBUG_TRACE(port, "Power sink ready");
- break;
- case USBPD_NOTIFY_POWER_SNK_STOP:
- DPM_USER_DEBUG_TRACE(port, "Power sink stopped");
- break;
- case USBPD_NOTIFY_POWER_SWAP_TO_SNK_DONE:
- DPM_USER_DEBUG_TRACE(port, "Sink ready");
- break;
- case USBPD_NOTIFY_STATE_SNK_READY:
- DPM_USER_DEBUG_TRACE(port, "Sink ready");
- break;
- case USBPD_NOTIFY_HARDRESET_RX:
- DPM_USER_DEBUG_TRACE(port, "Hard reset RX");
- break;
- case USBPD_NOTIFY_HARDRESET_TX:
- DPM_USER_DEBUG_TRACE(port, "Hard reset TX");
- break;
- case USBPD_NOTIFY_STATE_SRC_DISABLED:
- uart_puts("[33] Source/cable not capable of USB Type-C PD, fall back to legacy 5V VBUS.");
- break;
- case USBPD_NOTIFY_ALERT_RECEIVED :
- DPM_USER_DEBUG_TRACE(port, "Alert received");
- break;
- case USBPD_NOTIFY_CABLERESET_REQUESTED :
- DPM_USER_DEBUG_TRACE(port, "Cable reset requested");
- break;
- case USBPD_NOTIFY_MSG_NOT_SUPPORTED :
- DPM_USER_DEBUG_TRACE(port, "Message not supported");
- break;
- case USBPD_NOTIFY_PE_DISABLED :
- DPM_USER_DEBUG_TRACE(port, "Protocol engine disabled");
- break;
- case USBPD_NOTIFY_USBSTACK_START:
- DPM_USER_DEBUG_TRACE(port, "USB stack started");
- break;
- case USBPD_NOTIFY_USBSTACK_STOP:
- DPM_USER_DEBUG_TRACE(port, "USB stack stopped");
- break;
- case USBPD_NOTIFY_DATAROLESWAP_DFP :
- DPM_USER_DEBUG_TRACE(port, "Data role swapped to DFP");
- break;
- case USBPD_NOTIFY_DATAROLESWAP_UFP :
- DPM_USER_DEBUG_TRACE(port, "Data role swapped to UFP");
- break;
- case USBPD_NOTIFY_POWER_STATE_CHANGE:
- DPM_USER_DEBUG_TRACE(port, "Power state changed");
- break;
- default:
- uart_printf("DPM user debug: [%u] unhandled DPM notification: %u\r\n", port, event);
- break;
- }
- }
- int32_t BSP_USBPD_PWR_RegisterVBUSDetectCallback(uint32_t Instance,
- USBPD_PWR_VBUSDetectCallbackFunc *pfnVBUSDetectCallback) {
- int32_t ret = BSP_ERROR_NONE;
- /* Check if instance is valid */
- if ((Instance >= USBPD_PWR_INSTANCES_NBR) || (NULL == pfnVBUSDetectCallback))
- {
- ret = BSP_ERROR_WRONG_PARAM;
- }
- else
- {
- /* Set port callback for VBUS detection event */
- drp.vbus_detect_callback = pfnVBUSDetectCallback;
- }
- return ret;
- }
- /**
- * Set the power mode for a TCPP03-protected port (ie. a dual role port).
- */
- int32_t BSP_USBPD_PWR_SetPowerMode(uint32_t Instance, USBPD_PWR_PowerModeTypeDef PwrMode) {
- (void) PwrMode;
- if (Instance >= USBPD_PWR_INSTANCES_NBR) {
- return BSP_ERROR_WRONG_PARAM;
- } else if (Instance == DRP_PORT_NUM) {
- uint8_t flags = tcpp03_get_flags();
- if (flags & TCPP03_FLAG_VBUS_OK) {
- if (drp.vbus_detect_callback != NULL) {
- drp.vbus_detect_callback(Instance, VBUS_CONNECTED);
- }
- }
- } else {
- return BSP_ERROR_FEATURE_NOT_SUPPORTED;
- }
- return BSP_ERROR_NONE;
- }
- /**
- * Keeps track of which power role the DRP port is in. This is called by the USBPD stack when it changes the power role.
- *
- * VBUS (the TCPP03 FET gate drivers) is controlled by BSP_USBPD_PWR_VBUSOn() and BSP_USBPD_PWR_VBUSOff().
- */
- int32_t BSP_USBPD_PWR_SetRole(uint32_t PortNum, USBPD_PWR_PowerRoleTypeDef Role) {
- if (PortNum >= USBPD_PWR_INSTANCES_NBR) {
- return BSP_ERROR_WRONG_PARAM;
- } else {
- switch (Role) {
- case POWER_ROLE_SOURCE:
- drp.role = SOURCE;
- break;
- case POWER_ROLE_SINK:
- drp.role = SINK;
- break;
- case POWER_ROLE_DUAL:
- assert(false);
- break;
- }
- }
- return BSP_ERROR_NONE;
- }
- /**
- * Enable VBUS supply to a port (source/DRP only -- will fail if called on a sink port).
- */
- int32_t BSP_USBPD_PWR_VBUSOn(uint32_t PortNum) {
- if (PortNum >= USBPD_PWR_INSTANCES_NBR) {
- return BSP_ERROR_WRONG_PARAM;
- } else {
- if (PortNum == DRP_PORT_NUM && drp.role == SOURCE) {
- tcpp03_set_provider();
- } else {
- return BSP_ERROR_COMPONENT_FAILURE; // Only DRP port can be powered on
- }
- }
- return BSP_ERROR_NONE;
- }
- /**
- * Disable VBUS supply to a port (source only -- will fail if called on a sink port).
- */
- int32_t BSP_USBPD_PWR_VBUSOff(uint32_t PortNum) {
- if (PortNum >= USBPD_PWR_INSTANCES_NBR) {
- return BSP_ERROR_WRONG_PARAM;
- } else {
- if (PortNum == DRP_PORT_NUM && drp.role == SOURCE) {
- tcpp03_set_isolated();
- } else {
- return BSP_ERROR_COMPONENT_FAILURE; // Only DRP port can be powered on
- }
- }
- return BSP_ERROR_NONE;
- }
- /**
- * Check if VBUS supply is on for a given port. Note that this only check whether the VBUS FET is enabled,
- * not the voltage on the port (use BSP_USBPD_PWR_VBUSGetVoltage() for that).
- *
- * *pState: pointer to a uint8_t that will be set to 1 if VBUS is on, 0 if it is off.
- */
- int32_t BSP_USBPD_PWR_VBUSIsOn(uint32_t Instance, uint8_t *pState) {
- if (Instance >= USBPD_PWR_INSTANCES_NBR) {
- return BSP_ERROR_WRONG_PARAM;
- }
- if (pState == NULL) {
- return BSP_ERROR_WRONG_PARAM;
- }
- // Check if VBUS is on for the given port
- switch (Instance) {
- case USBPD_PWR_TYPE_C_PORT_1: // UFP: port 0, UCPD1
- *pState = 0;
- break;
- case USBPD_PWR_TYPE_C_PORT_2: // DRP: port 1, UCPD2
- uint8_t acks = tcpp03_get_acks();
- *pState = (acks & TCPP03_PROVIDER_GATE) ? 1 : 0;
- break;
- default:
- return BSP_ERROR_WRONG_PARAM;
- }
- return BSP_ERROR_NONE;
- }
- /**
- * No action is needed to 'set' VBUS to 5V, as it's connected to 5V_IN when the provider FET is enabled. This
- * function just checks that the requested voltage is 5V and the current is within limits.
- */
- int32_t BSP_USBPD_PWR_VBUSSetVoltage_Fixed(uint32_t PortNum,
- uint32_t VbusTargetInmv,
- uint32_t OperatingCurrent,
- uint32_t MaxOperatingCurrent) {
- switch (PortNum) {
- case USBPD_PWR_TYPE_C_PORT_1: // UFP: port 0, UCPD1
- return BSP_ERROR_FEATURE_NOT_SUPPORTED;
- break;
- case USBPD_PWR_TYPE_C_PORT_2: // DRP: port 1, UCPD2
- if (VbusTargetInmv == 5000 && OperatingCurrent <= 3000) {
- return BSP_ERROR_NONE;
- }
- break;
- }
- return BSP_ERROR_FEATURE_NOT_SUPPORTED;
- }
- /**
- * Empty function. Warnings are generated if not implemented.
- */
- int32_t BSP_USBPD_PWR_VBUSInit(uint32_t Instance) {
- if (Instance >= USBPD_PWR_INSTANCES_NBR) {
- return BSP_ERROR_WRONG_PARAM;
- }
- return BSP_ERROR_NONE;
- }
- /**
- * Return the port to the default state, as if the stack were not running.
- */
- int32_t BSP_USBPD_PWR_VBUSDeInit(uint32_t Instance) {
- if (Instance >= USBPD_PWR_INSTANCES_NBR) {
- return BSP_ERROR_WRONG_PARAM;
- }
- if (Instance == USBPD_PWR_TYPE_C_PORT_2) { // DRP port
- if (g_ufp_implicit_contract == IMPL_CONTRACT_NONE) {
- tcpp03_set_consumer();
- } else {
- tcpp03_set_isolated();
- }
- }
- return BSP_ERROR_NONE;
- }
Advertisement
Add Comment
Please, Sign In to add comment