Guest User

USBPD: Renegotiate contract on reset?

a guest
Jul 22nd, 2025
16
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 31.94 KB | None | 0 0
  1. // usbpd_dpm_user.c
  2.  
  3. [...]
  4.  
  5. /**
  6.   * @brief  UserCableDetection reporting events on a specified port from CAD layer.
  7.   * @param  PortNum The handle of the port
  8.   * @param  State CAD state
  9.   * @retval None
  10.   */
  11. void USBPD_DPM_UserCableDetection(uint8_t PortNum, USBPD_CAD_EVENT State)
  12. {
  13. /* USER CODE BEGIN USBPD_DPM_UserCableDetection */
  14.     user_usbpd_cable_detection_event(PortNum, State);
  15. /* USER CODE END USBPD_DPM_UserCableDetection */
  16. }
  17.  
  18. /**
  19.   * @brief  function used to manage user timer.
  20.   * @param  PortNum Port number
  21.   * @retval None
  22.   */
  23. void USBPD_DPM_UserTimerCounter(uint8_t PortNum)
  24. {
  25. /* USER CODE BEGIN USBPD_DPM_UserTimerCounter */
  26.  
  27. /* USER CODE END USBPD_DPM_UserTimerCounter */
  28. }
  29.  
  30. /**
  31.   * @}
  32.   */
  33.  
  34. /** @defgroup USBPD_USER_EXPORTED_FUNCTIONS_GROUP2 USBPD USER Exported Callbacks functions called by PE
  35.   * @{
  36.   */
  37.  
  38. /**
  39.   * @brief  Callback function called by PE to inform DPM about PE event.
  40.   * @param  PortNum The current port number
  41.   * @param  EventVal @ref USBPD_NotifyEventValue_TypeDef
  42.   * @retval None
  43.   */
  44. void USBPD_DPM_Notification(uint8_t PortNum, USBPD_NotifyEventValue_TypeDef EventVal)
  45. {
  46. /* USER CODE BEGIN USBPD_DPM_Notification */
  47.     user_usbpd_event_notification(PortNum, EventVal);
  48. /* USER CODE END USBPD_DPM_Notification */
  49. }
  50.  
  51. /**
  52.   * @brief  Callback function called by PE layer when HardReset message received from PRL
  53.   * @param  PortNum The current port number
  54.   * @param  CurrentRole the current role
  55.   * @param  Status status on hard reset event
  56.   * @retval None
  57.   */
  58. void USBPD_DPM_HardReset(uint8_t PortNum, USBPD_PortPowerRole_TypeDef CurrentRole, USBPD_HR_Status_TypeDef Status)
  59. {
  60. /* USER CODE BEGIN USBPD_DPM_HardReset */
  61.     uart_printf("DPM user debug [%u]: HardReset(), role=%lu, status=%u\r\n", PortNum, CurrentRole, Status);
  62.     if (CurrentRole == USBPD_PORTPOWERROLE_SRC) {
  63.         switch (Status)
  64.         {
  65.         case USBPD_HR_STATUS_WAIT_VBUS_VSAFE0V:
  66.             DPM_TurnOffPower(PortNum, CurrentRole);
  67.             break;
  68.         case USBPD_HR_STATUS_WAIT_VBUS_VSAFE5V:
  69.             DPM_TurnOnPower(PortNum, CurrentRole);
  70.             break;
  71.         default:
  72.             break;
  73.         }
  74.     }
  75. /* USER CODE END USBPD_DPM_HardReset */
  76. }
  77.  
  78. [...]
  79.  
  80. /* USER CODE BEGIN USBPD_USER_PRIVATE_FUNCTIONS */
  81.  
  82. static void DPM_AssertRd(uint8_t port) {
  83.     USBPD_CAD_AssertRd(port);
  84. }
  85.  
  86. static void DPM_AssertRp(uint8_t port) {
  87.     USBPD_CAD_AssertRp(port);
  88. }
  89.  
  90. static USBPD_StatusTypeDef DPM_TurnOnPower(uint8_t PortNum, USBPD_PortPowerRole_TypeDef Role)
  91. {
  92.   USBPD_StatusTypeDef status;
  93.   /* Enable the output */
  94.   status = USBPD_PWR_IF_VBUSEnable(PortNum);
  95.   if (USBPD_PORTPOWERROLE_src== Role)
  96.   {
  97.     /* Enable the output */
  98.     USBPD_DPM_WaitForTime(20);
  99.   }
  100.   else
  101.   {
  102.     /* stop current sink */
  103.   }
  104.   return status;
  105. }
  106.  
  107.  
  108. static USBPD_StatusTypeDef DPM_TurnOffPower(uint8_t PortNum, USBPD_PortPowerRole_TypeDef Role)
  109. {
  110.   USBPD_StatusTypeDef status;
  111.   status = USBPD_PWR_IF_VBUSDisable(PortNum);
  112.   return status;
  113. }
  114.  
  115.  
  116. /**
  117.   * @brief  Find PDO index that offers the most power without exceeding max sink voltage.
  118.   * @param  PortNum Port number
  119.   * @param  PtrRequestPowerDetails  Sink requested power details structure pointer
  120.   * @retval Index of PDO within source capabilities message (DPM_NO_SRC_PDO_FOUND indicating not found)
  121.   */
  122. static uint32_t DPM_FindVoltageIndex(uint32_t PortNum, USBPD_DPM_SNKPowerRequestDetails_TypeDef* PtrRequestPowerDetails, uint8_t Method)
  123. {
  124.     uint32_t *ptpdoarray;
  125.     USBPD_PDO_TypeDef  pdo;
  126.     uint32_t voltage;
  127.     uint32_t reqvoltage;
  128.     uint32_t nbpdo;
  129.     uint32_t allowablepower;
  130.     uint32_t selpower;
  131.     uint32_t allowablecurrent;
  132.     uint32_t selcurrent;
  133.     uint32_t curr_index = DPM_NO_SRC_PDO_FOUND;
  134.     uint32_t temp_index;
  135.     USBPD_USER_SettingsTypeDef *puser = (USBPD_USER_SettingsTypeDef *)&DPM_USER_Settings[PortNum];
  136.  
  137.     allowablepower = 0;
  138.     selpower       = 0;
  139.     reqvoltage     = 0;
  140.     voltage        = 0;
  141.     selcurrent     = 0;
  142.  
  143.     /* Search PDO index among Source PDO of Port */
  144.     nbpdo = DPM_Ports[PortNum].DPM_NumberOfRcvSRCPDO;
  145.     ptpdoarray = DPM_Ports[PortNum].DPM_ListOfRcvSRCPDO;
  146.  
  147.     /* search the best PDO in the list of source PDOs */
  148.     for (temp_index = 0; temp_index < nbpdo; temp_index++)
  149.     {
  150.         pdo.d32 = ptpdoarray[temp_index];
  151.  
  152.         /* Check if the received source PDO is matching any of the SNK PDO */
  153.         allowablepower = 0;
  154.         if (USBPD_TRUE == USBPD_DPM_SNK_EvaluateMatchWithSRCPDO(PortNum, pdo.d32, &voltage, &allowablepower))
  155.         {
  156.             allowablecurrent = (allowablepower / voltage) * 1000U;
  157.  
  158.             /* Choose the best PDO depending on the user preferences */
  159.             switch (Method)
  160.             {
  161.             case PDO_SEL_METHOD_MAX_PWR:
  162.                 if (allowablepower > selpower)
  163.                 {
  164.                     /* Consider the current PDO the best one until now */
  165.                     curr_index = temp_index;
  166.                     selpower   = allowablepower;
  167.                     reqvoltage = voltage;
  168.                     selcurrent = allowablecurrent;
  169.                 }
  170.                 break;
  171.  
  172.             case PDO_SEL_METHOD_MIN_PWR:
  173.                 if ((allowablepower < selpower) || (selpower == 0))
  174.                 {
  175.                     /* Consider the current PDO the best one until now */
  176.                     curr_index = temp_index;
  177.                     selpower   = allowablepower;
  178.                     reqvoltage = voltage;
  179.                     selcurrent = allowablecurrent;
  180.                 }
  181.                 break;
  182.  
  183.             case PDO_SEL_METHOD_MAX_VOLT:
  184.                 if (voltage > reqvoltage)
  185.                 {
  186.                     /* Consider the current PDO the best one until now */
  187.                     curr_index = temp_index;
  188.                     selpower   = allowablepower;
  189.                     reqvoltage = voltage;
  190.                     selcurrent = allowablecurrent;
  191.                 }
  192.                 break;
  193.  
  194.             case PDO_SEL_METHOD_MIN_VOLT:
  195.                 if ((voltage < reqvoltage) || (reqvoltage == 0))
  196.                 {
  197.                     /* Consider the current PDO the best one until now */
  198.                     curr_index = temp_index;
  199.                     selpower   = allowablepower;
  200.                     reqvoltage = voltage;
  201.                     selcurrent = allowablecurrent;
  202.                 }
  203.                 break;
  204.  
  205.             case PDO_SEL_METHOD_MAX_CUR:
  206.                 if (allowablecurrent > selcurrent)
  207.                 {
  208.                     /* Consider the current PDO the best one until now */
  209.                     curr_index = temp_index;
  210.                     selpower   = allowablepower;
  211.                     reqvoltage = voltage;
  212.                     selcurrent = allowablecurrent;
  213.                 }
  214.                 break;
  215.  
  216.             case PDO_SEL_METHOD_MIN_CUR:
  217.                 if ((allowablecurrent < selcurrent) || (selcurrent == 0))
  218.                 {
  219.                     /* Consider the current PDO the best one until now */
  220.                     curr_index = temp_index;
  221.                     selpower   = allowablepower;
  222.                     reqvoltage = voltage;
  223.                     selcurrent = allowablecurrent;
  224.                 }
  225.                 break;
  226.  
  227.             default:
  228.                 /* Default behavior: last PDO is selected */
  229.                 curr_index = temp_index;
  230.                 selpower   = allowablepower;
  231.                 reqvoltage = voltage;
  232.                 selcurrent = allowablecurrent;
  233.             }
  234.         }
  235.     }
  236.  
  237.     /* If a suitable PDO was found */
  238.     if (curr_index != DPM_NO_SRC_PDO_FOUND)
  239.     {
  240.         /* Fill the request power details */
  241.         PtrRequestPowerDetails->MaxOperatingCurrentInmAunits = puser->DPM_SNKRequestedPower.MaxOperatingCurrentInmAunits;
  242.         PtrRequestPowerDetails->OperatingCurrentInmAunits    = (1000U * selpower) / reqvoltage;
  243.         PtrRequestPowerDetails->MaxOperatingPowerInmWunits   = puser->DPM_SNKRequestedPower.MaxOperatingPowerInmWunits;
  244.         PtrRequestPowerDetails->OperatingPowerInmWunits      = selpower;
  245.         PtrRequestPowerDetails->RequestedVoltageInmVunits    = reqvoltage;
  246. #ifdef USER_USBPD_TRACE
  247.         uart_printf("DPM user debug [%lu]: Selected sink PDO has V=%lumV I=%lumA\r\n", PortNum, reqvoltage,
  248.                 PtrRequestPowerDetails->OperatingCurrentInmAunits);
  249. #endif
  250.     }
  251.  
  252.     return curr_index;
  253. }
  254.  
  255. /**
  256.   * @brief  Build RDO to be used in Request message according to selected PDO from received SRC Capabilities
  257.   * @param  PortNum           Port number
  258.   * @param  IndexSrcPDO       Index on the selected SRC PDO (value between 0 to 6)
  259.   * @param  PtrRequestPowerDetails  Sink requested power details structure pointer
  260.   * @param  Rdo               Pointer on the RDO
  261.   * @param  PtrPowerObject    Pointer on the selected power object
  262.   * @retval None
  263.   */
  264. void DPM_SNK_BuildRDOfromSelectedPDO(uint8_t PortNum, uint8_t IndexSrcPDO,
  265.                                      USBPD_DPM_SNKPowerRequestDetails_TypeDef *PtrRequestPowerDetails,
  266.                                      USBPD_SNKRDO_TypeDef* Rdo, USBPD_CORE_PDO_Type_TypeDef *PtrPowerObject)
  267. {
  268.   uint32_t mv = 0, mw = 0, ma = 0, size;
  269.   USBPD_PDO_TypeDef  pdo;
  270.   USBPD_SNKRDO_TypeDef rdo;
  271.   USBPD_HandleTypeDef *pdhandle = &DPM_Ports[PortNum];
  272.   USBPD_USER_SettingsTypeDef *puser = (USBPD_USER_SettingsTypeDef *)&DPM_USER_Settings[PortNum];
  273.   uint32_t snkpdolist[USBPD_MAX_NB_PDO];
  274.   USBPD_PDO_TypeDef snk_fixed_pdo;
  275.   /* Initialize RDO */
  276.   rdo.d32 = 0;
  277.   /* Read SNK PDO list for retrieving useful data to fill in RDO */
  278.   USBPD_PWR_IF_GetPortPDOs(PortNum, USBPD_CORE_DATATYPE_SNK_PDO, (uint8_t*)&snkpdolist[0], &size);
  279.   /* Store value of 1st SNK PDO (Fixed) in local variable */
  280.   snk_fixed_pdo.d32 = snkpdolist[0];
  281.   /* Set common fields in RDO */
  282.   pdo.d32 = pdhandle->DPM_ListOfRcvSRCPDO[0];
  283.   rdo.GenericRDO.USBCommunicationsCapable     = snk_fixed_pdo.SNKFixedPDO.USBCommunicationsCapable;
  284.   if (USBPD_SPECIFICATION_REV2 < DPM_Params[PortNum].PE_SpecRevision)
  285.   {
  286.     rdo.FixedVariableRDO.UnchunkedExtendedMessage = DPM_Settings[PortNum].PE_PD3_Support.d.PE_UnchunkSupport;
  287. //    DPM_Params[PortNum].PE_UnchunkSupport   = USBPD_FALSE;
  288. //    /* Set unchuncked bit if supported by port partner;*/
  289. //    if (USBPD_TRUE == pdo.SRCFixedPDO.UnchunkedExtendedMessage)
  290. //    {
  291. //      DPM_Params[PortNum].PE_UnchunkSupport   = USBPD_TRUE;
  292. //    }
  293.   }
  294.   /* If no valid SNK PDO or if no SRC PDO match found (index>=nb of valid received SRC PDOs */
  295.   if ((size < 1) || (IndexSrcPDO >= pdhandle->DPM_NumberOfRcvSRCPDO))
  296.   {
  297.     /* USBPD_DPM_EvaluateCapabilities: Mismatch, could not find desired pdo index */
  298. #ifdef _TRACE
  299.     USBPD_TRACE_Add(USBPD_TRACE_DEBUG, PortNum, 0, (uint8_t *)"DPM_SNK_BuildRDOfromSelectedPDO: Pb in SRC PDO selection",
  300.                     sizeof("DPM_SNK_BuildRDOfromSelectedPDO: Pb in SRC PDO selection"));
  301. #endif /* _TRACE */
  302.     rdo.FixedVariableRDO.ObjectPosition = 1;
  303.     rdo.FixedVariableRDO.OperatingCurrentIn10mAunits  = pdo.SRCFixedPDO.MaxCurrentIn10mAunits;
  304.     rdo.FixedVariableRDO.MaxOperatingCurrent10mAunits = pdo.SRCFixedPDO.MaxCurrentIn10mAunits;
  305.     rdo.FixedVariableRDO.CapabilityMismatch           = 1;
  306.     rdo.FixedVariableRDO.USBCommunicationsCapable     = snk_fixed_pdo.SNKFixedPDO.USBCommunicationsCapable;
  307.     DPM_Ports[PortNum].DPM_RequestedCurrent           = puser->DPM_SNKRequestedPower.MaxOperatingCurrentInmAunits;
  308.     /* USBPD_DPM_EvaluateCapabilities: Mismatch, could not find desired pdo index */
  309.     pdhandle->DPM_RequestDOMsg = rdo.d32;
  310.     return;
  311.   }
  312.   /* Set the Object position */
  313.   rdo.GenericRDO.ObjectPosition               = IndexSrcPDO + 1;
  314.   rdo.GenericRDO.NoUSBSuspend                 = 0;
  315.   /* Extract power information from Power Data Object */
  316.   pdo.d32 = pdhandle->DPM_ListOfRcvSRCPDO[IndexSrcPDO];
  317.   *PtrPowerObject = pdo.GenericPDO.PowerObject;
  318.   /* Retrieve request details from SRC PDO selection */
  319.   mv = PtrRequestPowerDetails->RequestedVoltageInmVunits;
  320.   ma = PtrRequestPowerDetails->OperatingCurrentInmAunits;
  321.   switch(pdo.GenericPDO.PowerObject)
  322.   {
  323.   case USBPD_CORE_PDO_TYPE_FIXED:
  324.   case USBPD_CORE_PDO_TYPE_VARIABLE:
  325.     {
  326.       /* USBPD_DPM_EvaluateCapabilities: Mismatch, less power offered than the operating power */
  327.       ma = USBPD_MIN(ma, puser->DPM_SNKRequestedPower.MaxOperatingCurrentInmAunits);
  328.       mw = (ma * mv)/1000; /* mW */
  329.       DPM_Ports[PortNum].DPM_RequestedCurrent           = ma;
  330.       rdo.FixedVariableRDO.OperatingCurrentIn10mAunits  = ma / 10;
  331.       rdo.FixedVariableRDO.MaxOperatingCurrent10mAunits = ma / 10;
  332.       if(mw < puser->DPM_SNKRequestedPower.OperatingPowerInmWunits)
  333.       {
  334.         /* USBPD_DPM_EvaluateCapabilities: Mismatch, less power offered than the operating power */
  335.         rdo.FixedVariableRDO.MaxOperatingCurrent10mAunits = puser->DPM_SNKRequestedPower.MaxOperatingCurrentInmAunits / 10;
  336.         rdo.FixedVariableRDO.CapabilityMismatch = 1;
  337.       }
  338.     }
  339.     break;
  340.   case USBPD_CORE_PDO_TYPE_BATTERY:
  341.     {
  342.       /* USBPD_DPM_EvaluateCapabilities: Battery Request Data Object */
  343.       mw = USBPD_MIN(PtrRequestPowerDetails->OperatingPowerInmWunits, puser->DPM_SNKRequestedPower.MaxOperatingPowerInmWunits); /* mW */
  344.       ma = (1000 * mw) / mv; /* mA */
  345.       ma = USBPD_MIN(ma, puser->DPM_SNKRequestedPower.MaxOperatingCurrentInmAunits);
  346.       DPM_Ports[PortNum].DPM_RequestedCurrent       = ma;
  347.       mw = (ma * mv)/1000; /* mW */
  348.       rdo.BatteryRDO.OperatingPowerIn250mWunits     = mw / 250;
  349.       rdo.BatteryRDO.MaxOperatingPowerIn250mWunits  = mw / 250;
  350.       if(mw < puser->DPM_SNKRequestedPower.OperatingPowerInmWunits)
  351.       {
  352.         /* Mismatch, less power offered than the operating power */
  353.         rdo.BatteryRDO.CapabilityMismatch = 1;
  354.       }
  355.     }
  356.     break;
  357. //  case USBPD_CORE_PDO_TYPE_APDO:
  358. //    {
  359. //      DPM_Ports[PortNum].DPM_RequestedCurrent    = ma;
  360. //      rdo.ProgRDO.ObjectPosition                 = IndexSrcPDO + 1;
  361. //      rdo.ProgRDO.OperatingCurrentIn50mAunits    = ma / 50;
  362. //      rdo.ProgRDO.OutputVoltageIn20mV            = mv / 20;
  363. //    }
  364. //    break;
  365.   default:
  366.     break;
  367.   }
  368.   pdhandle->DPM_RequestDOMsg = rdo.d32;
  369.   pdhandle->DPM_RDOPosition  = rdo.GenericRDO.ObjectPosition;
  370.   Rdo->d32 = pdhandle->DPM_RequestDOMsg;
  371.   /* Get the requested voltage */
  372.   pdhandle->DPM_RequestedVoltage = mv;
  373. }
  374.  
  375. /* USER CODE END USBPD_USER_PRIVATE_FUNCTIONS */
  376.  
  377. [...]
  378.  
  379. // user_usbpd.c
  380.  
  381.  
  382. struct {
  383.     enum {
  384.         SOURCE,
  385.         SINK
  386.     } role;
  387.     USBPD_PWR_VBUSDetectCallbackFunc* vbus_detect_callback;
  388. } drp = {
  389.     .role = SOURCE,
  390.     .vbus_detect_callback = NULL
  391. };
  392.  
  393. /**
  394.   * @brief  Get actual voltage level measured on the VBUS line.
  395.   * @param  Instance Type-C port identifier
  396.   *         This parameter can be take one of the following values:
  397.   *         @arg @ref USBPD_PWR_TYPE_C_PORT_1
  398.   *         @arg @ref USBPD_PWR_TYPE_C_PORT_2
  399.   * @param  pVoltage Pointer on measured voltage level (in mV)
  400.   * @retval BSP status
  401.   */
  402. int32_t BSP_USBPD_PWR_VBUSGetVoltage(uint32_t Instance, uint32_t *pVoltage) {
  403.     switch (Instance) {
  404.     case USBPD_PWR_TYPE_C_PORT_1:  // UFP: port 0, UCPD1
  405.         *pVoltage = 1000 * (uint32_t)(V_VBUS_UFP() + 0.5f);
  406.         return BSP_ERROR_NONE;
  407.     case USBPD_PWR_TYPE_C_PORT_2:  // DRP: port 1, UCPD2
  408.         *pVoltage = 1000 * (uint32_t)(V_VBUS_DRP() + 0.5f);
  409.         return BSP_ERROR_NONE;
  410.     default:
  411.         return BSP_ERROR_WRONG_PARAM;
  412.     }
  413. }
  414.  
  415.  
  416. /**
  417.   * @brief  Get actual current level measured on the VBUS line.
  418.   * @param  Instance Type-C port identifier
  419.   *         This parameter can be take one of the following values:
  420.   *         @arg @ref USBPD_PWR_TYPE_C_PORT_1
  421.   *         @arg @ref USBPD_PWR_TYPE_C_PORT_2
  422.   * @param  pCurrent Pointer on measured current level (in mA)
  423.   * @retval BSP status
  424.   */
  425. int32_t BSP_USBPD_PWR_VBUSGetCurrent(uint32_t Instance, int32_t *pCurrent) {
  426.     switch (Instance) {
  427.     case USBPD_PWR_TYPE_C_PORT_1:  // UFP: port 0, UCPD1
  428.         *pCurrent = 0;
  429.         return BSP_ERROR_NONE;
  430.     case USBPD_PWR_TYPE_C_PORT_2:  // DRP: port 1, UCPD2
  431.         *pCurrent = 1000 * (uint32_t)(I_DRP() + 0.5f);
  432.         return BSP_ERROR_NONE;
  433.     default:
  434.         return BSP_ERROR_WRONG_PARAM;
  435.     }
  436. }
  437.  
  438.  
  439. /**
  440.  * Called by remapped trace macros in user_usbpd_trace.h. These macros are called by
  441.  * various USBPD files, and print USBPD debug info.
  442.  */
  443. void user_usbpd_trace(UserTraceUSBPD trace_type, uint8_t port, char* message) {
  444.     const char type_pwr_user_dbg[] = "DPM pwr user debug";
  445.     const char type_pwr_if_dbg[] = "DPM pwr if debug";
  446.     const char type_dpm_user_dbg[] = "DPM user debug";
  447.     const char type_dpm_user_err[] = "DPM user error";
  448.     const char type_unknown[] = "UNKNOWN";
  449.     const char* type_ptr;
  450.  
  451.     switch (trace_type) {
  452.     case PD_TRACE_PWR_USER_DEBUG:
  453.         type_ptr = type_pwr_user_dbg;
  454.         break;
  455.     case PD_TRACE_PWR_IF_DEBUG:
  456.         type_ptr = type_pwr_if_dbg;
  457.         break;
  458.     case PD_TRACE_DPM_USER_DEBUG:
  459.         type_ptr = type_dpm_user_dbg;
  460.         break;
  461.     case PD_TRACE_DPM_USER_ERROR:
  462.         type_ptr = type_dpm_user_err;
  463.         break;
  464.     default:
  465.         type_ptr = type_unknown;
  466.     }
  467.  
  468.     uart_printf("%s [%u]: %s\r\n", type_ptr, port, message);
  469. }
  470.  
  471.  
  472. /**
  473.  * Overrides default error handler. assert() will tell you which error handler got called (the default solution is
  474.  * a simple `while(1);` ).
  475.  */
  476. void USBPD_DPM_ErrorHandler(void) {
  477.     assert(false);
  478. }
  479.  
  480.  
  481. /**
  482.  * Read V_UFP in blocking mode. For use only when the main ADC DMA loop is not active, ie. before the FreeRTOS
  483.  * scheduler is started.
  484.  */
  485. float adc_get_v_ufp_blocking(void) {
  486. //  HAL_ADCEx_Calibration_Start(&hadc1);
  487.     while (!LL_ADC_IsActiveFlag_CCRDY(ADC1));
  488.  
  489.     // Save current sequencer settings to restore later
  490.     uint32_t channels_initial = LL_ADC_REG_GetSequencerChannels(ADC1);
  491.  
  492.     // Enable only UFP channel
  493.     LL_ADC_REG_SetSequencerChannels(ADC1, 0x1);
  494.  
  495.     // Wait for changes to take effect
  496.     while (!LL_ADC_IsActiveFlag_CCRDY(ADC1));
  497.  
  498.     HAL_ADC_Start(&hadc1);
  499.     while (!LL_ADC_IsActiveFlag_EOC(ADC1));
  500.  
  501.     float v_ufp = VI_MONITOR_SCALE_FACTORS[0] * (float) (ADC1->DR);
  502.  
  503.     HAL_ADC_Stop(&hadc1);
  504.     LL_ADC_REG_SetSequencerChannels(ADC1, channels_initial);
  505.     while (!LL_ADC_IsActiveFlag_CCRDY(ADC1));
  506.     return v_ufp;
  507. }
  508.  
  509.  
  510. /**
  511.  * Init function for power delivery. Runs before the FreeRTOS scheduler starts.
  512.  */
  513. int32_t BSP_USBPD_PWR_Init(uint32_t Instance) {
  514.     if (Instance >= USBPD_PWR_INSTANCES_NBR) {
  515.         return BSP_ERROR_WRONG_PARAM;
  516.     }
  517.  
  518.     if (Instance == DRP_PORT_NUM) {
  519.         tcpp03_init();
  520.     } else {
  521.         // Disable dead battery in port protection IC. UCPD hardware will handle this from now on.
  522.         HAL_GPIO_WritePin(nDB_UFP_GPIO_Port, nDB_UFP_Pin, 1);
  523.     }
  524.  
  525.     return BSP_ERROR_NONE;
  526. }
  527.  
  528.  
  529. /**
  530.  * Called from USBPD_DPM_UserCableDetection ISR when a port partner (phone/computer) is attached or detached. Sets the USB
  531.  * redriver mux orientation based on the detected voltages on the CC1/CC2 pins. Also saves any changes to implicit
  532.  * contracts to g_ufp_implicit_contract / g_drp_implicit_contract.
  533.  *
  534.  * port: port number (0=UFP, 1=DRP)
  535.  * event: attach/detach/other event type (see enum definition)
  536.  */
  537. void user_usbpd_cable_detection_event(uint8_t port, USBPD_CAD_EVENT event) {
  538.     assert(port <= 1);
  539.  
  540.     update_implicit_contract(port);
  541.  
  542.     char contract_str[8];
  543.     user_usbpd_implicit_contract_enum_to_string(port, contract_str);
  544.     uart_printf("Cable detect event [%u]: %s\r\n", port, contract_str);
  545.     uart_printf("Cable detect event: USBPD contract type from DPM_Params: %u\r\n", DPM_Params[port].PE_Power);
  546.  
  547.  
  548.     if (port == UFP_PORT_NUM) {
  549.         switch (event) {
  550.         case USBPD_CAD_EVENT_ATTEMC:
  551.         case USBPD_CAD_EVENT_ATTACHED:
  552.             if (g_ufp_implicit_contract != IMPL_CONTRACT_NONE || V_VBUS_UFP() > 4.0f) {
  553.                 // UFP is supplying power, isolate DRP VBUS.
  554. //              tcpp03_set_isolated();
  555.             }
  556.             DPM_Ports[port].DPM_IsConnected = 1;
  557.             break;
  558.         }
  559.     }
  560.  
  561.     if (port == DRP_PORT_NUM) {
  562.         if (cable_flipped(port)) {  // If voltage is on CC2 pin
  563.             HAL_GPIO_WritePin(USB_MUX_SEL_GPIO_Port, USB_MUX_SEL_Pin, 0);  // Route TX/RX_AP <-> TX/RX_Con_2
  564.         } else {
  565.             HAL_GPIO_WritePin(USB_MUX_SEL_GPIO_Port, USB_MUX_SEL_Pin, 1);  // Route TX/RX_AP <-> TX/RX_Con_1
  566.         }
  567.  
  568.         switch (event) {
  569.         case USBPD_CAD_EVENT_ATTEMC:
  570.         case USBPD_CAD_EVENT_ATTACHED:
  571.             if (DPM_Params[port].PE_PowerRole == USBPD_PORTPOWERROLE_SRC) {
  572.                 USBPD_PWR_IF_VBUSEnable(port);
  573.             }
  574.             DPM_Ports[port].DPM_IsConnected = 1;
  575.             break;
  576.  
  577.         case USBPD_CAD_EVENT_DETACHED:
  578.         case USBPD_CAD_EVENT_EMC:
  579.         default:
  580.             if (DPM_Params[port].PE_PowerRole == USBPD_PORTPOWERROLE_SRC) {
  581.                 USBPD_PWR_IF_VBUSDisable(port);
  582.             }
  583.             memset(&DPM_Ports[port], 0, sizeof(DPM_Ports[port]));
  584.             break;
  585.         }
  586.     }
  587. }
  588.  
  589.  
  590. bool cable_flipped(uint8_t port) {
  591.     UCPD_TypeDef* ucpd;
  592.     if (port == 0) {
  593.         ucpd = UCPD1;
  594.     } else {
  595.         ucpd = UCPD2;
  596.     }
  597.     return LL_UCPD_GetTypeCVstateCC2(ucpd) != LL_UCPD_SNK_CC2_VOPEN;
  598. }
  599.  
  600.  
  601. /**
  602.  * Updates the global implicit contract variable for a specific port.
  603.  *
  604.  * Note that this doesn't check for VBUS voltage -- a noncompliant cable could
  605.  * still apply voltage to VBUS without signalling an implicit contract via the CC pins.
  606.  */
  607. void update_implicit_contract(uint8_t port) {
  608.     UCPD_TypeDef* ucpd;
  609.     uint8_t* g_new_implicit_contract;
  610.     if (port == 0) {
  611.         ucpd = UCPD1;
  612.         g_new_implicit_contract = &g_ufp_implicit_contract;
  613.     } else {
  614.         ucpd = UCPD2;
  615.         g_new_implicit_contract = &g_drp_implicit_contract;
  616.     }
  617.  
  618.     // Work out the implicit contract from the CC pins
  619.     switch (LL_UCPD_GetTypeCVstateCC1(ucpd)) {
  620.     case LL_UCPD_SNK_CC1_VRP30A:
  621.         *g_new_implicit_contract = IMPL_CONTRACT_3A;
  622.         break;
  623.     case LL_UCPD_SNK_CC1_VRP15A:
  624.         *g_new_implicit_contract = IMPL_CONTRACT_1_5A;
  625.         break;
  626.     case LL_UCPD_SNK_CC1_VRP:
  627.         *g_new_implicit_contract = IMPL_CONTRACT_DEFAULT;
  628.         break;
  629.     case LL_UCPD_SNK_CC1_VOPEN:
  630.         switch (LL_UCPD_GetTypeCVstateCC2(ucpd)) {
  631.         case LL_UCPD_SNK_CC2_VRP30A:
  632.             *g_new_implicit_contract = IMPL_CONTRACT_3A;
  633.             break;
  634.         case LL_UCPD_SNK_CC2_VRP15A:
  635.             *g_new_implicit_contract = IMPL_CONTRACT_1_5A;
  636.             break;
  637.         case LL_UCPD_SNK_CC2_VRP:
  638.             *g_new_implicit_contract = IMPL_CONTRACT_DEFAULT;
  639.             break;
  640.         case LL_UCPD_SNK_CC2_VOPEN:
  641.             *g_new_implicit_contract = IMPL_CONTRACT_NONE;
  642.             break;
  643.         }
  644.         break;
  645.     }
  646. }
  647.  
  648.  
  649. void user_usbpd_implicit_contract_enum_to_string(ImplicitContract in_enum, char out_string[8]) {
  650.     switch (in_enum) {
  651.     case IMPL_CONTRACT_NONE:
  652.         strcpy(out_string, "none");
  653.         break;
  654.     case IMPL_CONTRACT_DEFAULT:
  655.         strcpy(out_string, "default");
  656.         break;
  657.     case IMPL_CONTRACT_1_5A:
  658.         strcpy(out_string, "1.5A");
  659.         break;
  660.     case IMPL_CONTRACT_3A:
  661.         strcpy(out_string, "3A");
  662.         break;
  663.     }
  664. }
  665.  
  666.  
  667. /**
  668.   * @brief  Check if a given source PDO matches sink requirements. Returns USBPD_TRUE if src_v == sink_v && src_i >= sink_i.
  669.   * Customised from the original, largely by removing lots of code for variable / battery PDOs.
  670.   *
  671.   * @param  PortNum             Port number
  672.   * @param  SrcPDO              Selected SRC PDO (32 bits)
  673.   * @param  PtrRequestedVoltage Pointer to voltage value that could be provided if SrcPDO is requested (only valid if USBPD_TRUE is returned) in mV
  674.   * @param  PtrRequestedPower   Pointer to power value that could be provided if SrcPDO is requested (only valid if USBPD_TRUE is returned) in mW
  675.   * @retval USBPD_FALSE or USBPD_TRUE (USBPD_TRUE returned if SrcPDO is matches SNK profile)
  676.   */
  677. uint32_t USBPD_DPM_SNK_EvaluateMatchWithSRCPDO(uint8_t PortNum, uint32_t SrcPDO, uint32_t* PtrRequestedVoltage, uint32_t* PtrRequestedPower) {
  678.     USBPD_PDO_TypeDef  srcpdo, snkpdo;
  679.     uint32_t match = USBPD_FALSE;
  680.     uint32_t nbsnkpdo;
  681.     uint32_t snkpdo_array[USBPD_MAX_NB_PDO];
  682.  
  683.     /* Retrieve SNK PDO list from PWR_IF storage : PDO values + nb of u32 written by PWR_IF (nb of PDOs) */
  684.     USBPD_PWR_IF_GetPortPDOs(PortNum, USBPD_CORE_DATATYPE_SNK_PDO, (uint8_t*)snkpdo_array, &nbsnkpdo);
  685.     if (nbsnkpdo == 0) {
  686.         return USBPD_FALSE;
  687.     }
  688.  
  689.     uint32_t max_req_pwr_mW = 0;
  690.     uint32_t max_req_v_mV = 0;
  691.     srcpdo.d32 = SrcPDO;
  692.  
  693.     if (srcpdo.GenericPDO.PowerObject == USBPD_CORE_PDO_TYPE_FIXED) {
  694.         uint16_t v_src_mV = 50 * srcpdo.SRCFixedPDO.VoltageIn50mVunits;
  695.         uint16_t i_src_mA = 10 * srcpdo.SRCFixedPDO.MaxCurrentIn10mAunits;
  696.         /* Loop through SNK PDO list */
  697.         for (size_t i = 0; i < nbsnkpdo; i++) {
  698.             uint32_t req_pwr_mW = 0;
  699.             uint32_t req_v_mV = 0;
  700.  
  701.             /* Retrieve SNK PDO value according to its type */
  702.             snkpdo.d32 = snkpdo_array[i];
  703.             if (snkpdo.GenericPDO.PowerObject == USBPD_CORE_PDO_TYPE_FIXED) {
  704.                 uint16_t v_snk_mV = 50 * snkpdo.SNKFixedPDO.VoltageIn50mVunits;
  705.                 uint16_t i_snk_mA = 10 * snkpdo.SNKFixedPDO.OperationalCurrentIn10mAunits;
  706.                 /* Match if :
  707.                  SNK Voltage == SRC Voltage
  708.                  &&
  709.                  SNK Op Current <= SRC Max Current
  710.                  Requested Voltage : SNK Voltage
  711.                  Requested Op Current : SNK Op Current
  712.                  Requested Max Current : SNK Op Current
  713.                  */
  714.                 if ((v_snk_mV == v_src_mV) && (i_snk_mA <= i_src_mA)) {
  715.                     req_pwr_mW = (uint32_t) v_snk_mV * (uint32_t) i_snk_mA / 1000;
  716.                     req_v_mV = v_snk_mV;
  717.                 }
  718.             }
  719.  
  720.             if (req_pwr_mW > max_req_pwr_mW) {
  721.                 match = USBPD_TRUE;
  722.                 max_req_pwr_mW = req_pwr_mW;
  723.                 max_req_v_mV = req_v_mV;
  724.             }
  725.         }
  726.     } else {  // Non-fixed PDOs are not supported
  727.         return USBPD_FALSE;
  728.     }
  729.     if (max_req_pwr_mW > 0) {
  730.         *PtrRequestedPower = max_req_pwr_mW;
  731.         *PtrRequestedVoltage = max_req_v_mV;
  732.     }
  733. //  if (match) {
  734. //      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);
  735. //  } else {
  736. //      uart_printf("Failed to match source PDO %08lx\r\n", SrcPDO);
  737. //  }
  738.     return match;
  739. }
  740.  
  741.  
  742. void user_usbpd_event_notification(uint8_t port, USBPD_NotifyEventValue_TypeDef event) {
  743.     assert(port <= 1);
  744.     switch(event) {
  745.     case USBPD_NOTIFY_POWER_EXPLICIT_CONTRACT:  // Explicit contract ready, power available
  746.         // Load the PDO that the device policy manager selected
  747.         USBPD_PDO_TypeDef pdo;
  748.         uint32_t dpo_pos = DPM_Ports[port].DPM_RDOPosition - 1;
  749.         pdo.d32 = DPM_Ports[port].DPM_ListOfRcvSRCPDO[dpo_pos];
  750.  
  751.         uint16_t v_mV = 50 * pdo.SRCFixedPDO.VoltageIn50mVunits;
  752.         uint16_t i_mA = 10 * pdo.SRCFixedPDO.MaxCurrentIn10mAunits;
  753.  
  754.         if (port == DRP_PORT_NUM) {
  755.             g_drp_explicit_contract.v_mV = v_mV;
  756.             g_drp_explicit_contract.i_mA = i_mA;
  757.         } else {
  758.             g_ufp_explicit_contract.v_mV = v_mV;
  759.             g_ufp_explicit_contract.i_mA = i_mA;
  760.         }
  761.  
  762.         g_power_update = true;
  763.  
  764.         uart_printf("DPM user debug [%u]: Explicit contract established (V=%umV I=%umA)\r\n", port, v_mV, i_mA);
  765.         break;
  766.     case USBPD_NOTIFY_REQUEST_ACCEPTED:
  767.         break;
  768.     case USBPD_NOTIFY_REQUEST_REJECTED:
  769.     case USBPD_NOTIFY_REQUEST_WAIT:
  770.         break;
  771.     case USBPD_NOTIFY_POWER_SNK_READY:
  772.         DPM_USER_DEBUG_TRACE(port, "Power sink ready");
  773.         break;
  774.     case USBPD_NOTIFY_POWER_SNK_STOP:
  775.         DPM_USER_DEBUG_TRACE(port, "Power sink stopped");
  776.         break;
  777.     case USBPD_NOTIFY_POWER_SWAP_TO_SNK_DONE:
  778.         DPM_USER_DEBUG_TRACE(port, "Sink ready");
  779.         break;
  780.     case USBPD_NOTIFY_STATE_SNK_READY:
  781.         DPM_USER_DEBUG_TRACE(port, "Sink ready");
  782.         break;
  783.     case USBPD_NOTIFY_HARDRESET_RX:
  784.         DPM_USER_DEBUG_TRACE(port, "Hard reset RX");
  785.         break;
  786.     case USBPD_NOTIFY_HARDRESET_TX:
  787.         DPM_USER_DEBUG_TRACE(port, "Hard reset TX");
  788.         break;
  789.     case USBPD_NOTIFY_STATE_SRC_DISABLED:
  790.         uart_puts("[33] Source/cable not capable of USB Type-C PD, fall back to legacy 5V VBUS.");
  791.         break;
  792.     case USBPD_NOTIFY_ALERT_RECEIVED :
  793.         DPM_USER_DEBUG_TRACE(port, "Alert received");
  794.         break;
  795.     case USBPD_NOTIFY_CABLERESET_REQUESTED :
  796.         DPM_USER_DEBUG_TRACE(port, "Cable reset requested");
  797.         break;
  798.     case USBPD_NOTIFY_MSG_NOT_SUPPORTED :
  799.         DPM_USER_DEBUG_TRACE(port, "Message not supported");
  800.         break;
  801.     case USBPD_NOTIFY_PE_DISABLED :
  802.         DPM_USER_DEBUG_TRACE(port, "Protocol engine disabled");
  803.         break;
  804.     case USBPD_NOTIFY_USBSTACK_START:
  805.         DPM_USER_DEBUG_TRACE(port, "USB stack started");
  806.         break;
  807.     case USBPD_NOTIFY_USBSTACK_STOP:
  808.         DPM_USER_DEBUG_TRACE(port, "USB stack stopped");
  809.         break;
  810.     case USBPD_NOTIFY_DATAROLESWAP_DFP :
  811.         DPM_USER_DEBUG_TRACE(port, "Data role swapped to DFP");
  812.         break;
  813.     case USBPD_NOTIFY_DATAROLESWAP_UFP :
  814.         DPM_USER_DEBUG_TRACE(port, "Data role swapped to UFP");
  815.         break;
  816.     case USBPD_NOTIFY_POWER_STATE_CHANGE:
  817.         DPM_USER_DEBUG_TRACE(port, "Power state changed");
  818.         break;
  819.     default:
  820.         uart_printf("DPM user debug: [%u] unhandled DPM notification: %u\r\n", port, event);
  821.         break;
  822.     }
  823. }
  824.  
  825.  
  826. int32_t BSP_USBPD_PWR_RegisterVBUSDetectCallback(uint32_t  Instance,
  827.                                                  USBPD_PWR_VBUSDetectCallbackFunc *pfnVBUSDetectCallback) {
  828.   int32_t ret = BSP_ERROR_NONE;
  829.  
  830.   /* Check if instance is valid */
  831.   if ((Instance >= USBPD_PWR_INSTANCES_NBR) || (NULL == pfnVBUSDetectCallback))
  832.   {
  833.     ret = BSP_ERROR_WRONG_PARAM;
  834.   }
  835.   else
  836.   {
  837.     /* Set port callback for VBUS detection event */
  838.     drp.vbus_detect_callback = pfnVBUSDetectCallback;
  839.   }
  840.   return ret;
  841. }
  842.  
  843.  
  844. /**
  845.  * Set the power mode for a TCPP03-protected port (ie. a dual role port).
  846.  */
  847. int32_t BSP_USBPD_PWR_SetPowerMode(uint32_t Instance, USBPD_PWR_PowerModeTypeDef PwrMode) {
  848.     (void) PwrMode;
  849.  
  850.     if (Instance >= USBPD_PWR_INSTANCES_NBR) {
  851.         return BSP_ERROR_WRONG_PARAM;
  852.     } else if (Instance == DRP_PORT_NUM) {
  853.         uint8_t flags = tcpp03_get_flags();
  854.         if (flags & TCPP03_FLAG_VBUS_OK) {
  855.             if (drp.vbus_detect_callback != NULL) {
  856.                 drp.vbus_detect_callback(Instance, VBUS_CONNECTED);
  857.             }
  858.         }
  859.     } else {
  860.         return BSP_ERROR_FEATURE_NOT_SUPPORTED;
  861.     }
  862.  
  863.     return BSP_ERROR_NONE;
  864. }
  865.  
  866.  
  867. /**
  868.  * Keeps track of which power role the DRP port is in. This is called by the USBPD stack when it changes the power role.
  869.  *
  870.  * VBUS (the TCPP03 FET gate drivers) is controlled by BSP_USBPD_PWR_VBUSOn() and BSP_USBPD_PWR_VBUSOff().
  871.  */
  872. int32_t BSP_USBPD_PWR_SetRole(uint32_t PortNum, USBPD_PWR_PowerRoleTypeDef Role) {
  873.     if (PortNum >= USBPD_PWR_INSTANCES_NBR) {
  874.         return BSP_ERROR_WRONG_PARAM;
  875.     } else {
  876.         switch (Role) {
  877.         case POWER_ROLE_SOURCE:
  878.             drp.role = SOURCE;
  879.             break;
  880.  
  881.         case POWER_ROLE_SINK:
  882.             drp.role = SINK;
  883.             break;
  884.  
  885.         case POWER_ROLE_DUAL:
  886.             assert(false);
  887.             break;
  888.         }
  889.     }
  890.  
  891.     return BSP_ERROR_NONE;
  892. }
  893.  
  894.  
  895. /**
  896.  * Enable VBUS supply to a port (source/DRP only -- will fail if called on a sink port).
  897.  */
  898. int32_t BSP_USBPD_PWR_VBUSOn(uint32_t PortNum) {
  899.     if (PortNum >= USBPD_PWR_INSTANCES_NBR) {
  900.         return BSP_ERROR_WRONG_PARAM;
  901.     } else {
  902.         if (PortNum == DRP_PORT_NUM && drp.role == SOURCE) {
  903.             tcpp03_set_provider();
  904.         } else {
  905.             return BSP_ERROR_COMPONENT_FAILURE;  // Only DRP port can be powered on
  906.         }
  907.     }
  908.  
  909.     return BSP_ERROR_NONE;
  910. }
  911.  
  912.  
  913. /**
  914.  * Disable VBUS supply to a port (source only -- will fail if called on a sink port).
  915.  */
  916. int32_t BSP_USBPD_PWR_VBUSOff(uint32_t PortNum) {
  917.     if (PortNum >= USBPD_PWR_INSTANCES_NBR) {
  918.         return BSP_ERROR_WRONG_PARAM;
  919.     } else {
  920.         if (PortNum == DRP_PORT_NUM && drp.role == SOURCE) {
  921.             tcpp03_set_isolated();
  922.         } else {
  923.             return BSP_ERROR_COMPONENT_FAILURE;  // Only DRP port can be powered on
  924.         }
  925.     }
  926.  
  927.     return BSP_ERROR_NONE;
  928. }
  929.  
  930.  
  931. /**
  932.  * Check if VBUS supply is on for a given port. Note that this only check whether the VBUS FET is enabled,
  933.  * not the voltage on the port (use BSP_USBPD_PWR_VBUSGetVoltage() for that).
  934.  *
  935.  * *pState: pointer to a uint8_t that will be set to 1 if VBUS is on, 0 if it is off.
  936.  */
  937. int32_t BSP_USBPD_PWR_VBUSIsOn(uint32_t Instance, uint8_t *pState) {
  938.     if (Instance >= USBPD_PWR_INSTANCES_NBR) {
  939.         return BSP_ERROR_WRONG_PARAM;
  940.     }
  941.  
  942.     if (pState == NULL) {
  943.         return BSP_ERROR_WRONG_PARAM;
  944.     }
  945.  
  946.     // Check if VBUS is on for the given port
  947.     switch (Instance) {
  948.     case USBPD_PWR_TYPE_C_PORT_1:  // UFP: port 0, UCPD1
  949.         *pState = 0;
  950.         break;
  951.     case USBPD_PWR_TYPE_C_PORT_2:  // DRP: port 1, UCPD2
  952.         uint8_t acks = tcpp03_get_acks();
  953.         *pState = (acks & TCPP03_PROVIDER_GATE) ? 1 : 0;
  954.         break;
  955.     default:
  956.         return BSP_ERROR_WRONG_PARAM;
  957.     }
  958.  
  959.     return BSP_ERROR_NONE;
  960. }
  961.  
  962.  
  963. /**
  964.  * No action is needed to 'set' VBUS to 5V, as it's connected to 5V_IN when the provider FET is enabled. This
  965.  * function just checks that the requested voltage is 5V and the current is within limits.
  966.  */
  967. int32_t BSP_USBPD_PWR_VBUSSetVoltage_Fixed(uint32_t PortNum,
  968.                                            uint32_t VbusTargetInmv,
  969.                                            uint32_t OperatingCurrent,
  970.                                            uint32_t MaxOperatingCurrent) {
  971.     switch (PortNum) {
  972.     case USBPD_PWR_TYPE_C_PORT_1:  // UFP: port 0, UCPD1
  973.         return BSP_ERROR_FEATURE_NOT_SUPPORTED;
  974.         break;
  975.     case USBPD_PWR_TYPE_C_PORT_2:  // DRP: port 1, UCPD2
  976.         if (VbusTargetInmv == 5000 && OperatingCurrent <= 3000) {
  977.             return BSP_ERROR_NONE;
  978.         }
  979.         break;
  980.     }
  981.  
  982.     return BSP_ERROR_FEATURE_NOT_SUPPORTED;
  983. }
  984.  
  985.  
  986. /**
  987.  * Empty function. Warnings are generated if not implemented.
  988.  */
  989. int32_t BSP_USBPD_PWR_VBUSInit(uint32_t Instance) {
  990.     if (Instance >= USBPD_PWR_INSTANCES_NBR) {
  991.         return BSP_ERROR_WRONG_PARAM;
  992.     }
  993.  
  994.     return BSP_ERROR_NONE;
  995. }
  996.  
  997.  
  998. /**
  999.  * Return the port to the default state, as if the stack were not running.
  1000.  */
  1001. int32_t BSP_USBPD_PWR_VBUSDeInit(uint32_t Instance) {
  1002.     if (Instance >= USBPD_PWR_INSTANCES_NBR) {
  1003.         return BSP_ERROR_WRONG_PARAM;
  1004.     }
  1005.  
  1006.     if (Instance == USBPD_PWR_TYPE_C_PORT_2) {  // DRP port
  1007.         if (g_ufp_implicit_contract == IMPL_CONTRACT_NONE) {
  1008.             tcpp03_set_consumer();
  1009.         } else {
  1010.             tcpp03_set_isolated();
  1011.         }
  1012.     }
  1013.  
  1014.     return BSP_ERROR_NONE;
  1015. }
  1016.  
Advertisement
Add Comment
Please, Sign In to add comment