222 lines
4.9 KiB
C
222 lines
4.9 KiB
C
/********************************** (C) COPYRIGHT *******************************
|
|
* File Name : usb_pwr.c
|
|
* Author : WCH
|
|
* Version : V1.0.0
|
|
* Date : 2021/08/08
|
|
* Description : Connection/disconnection & power management
|
|
*********************************************************************************
|
|
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
|
* Attention: This software (modified or not) and binary are used for
|
|
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
|
*******************************************************************************/
|
|
#include "usb_pwr.h"
|
|
|
|
#include "usb_lib.h"
|
|
|
|
#include "hw_config.h"
|
|
#include "usb_conf.h"
|
|
|
|
|
|
|
|
__IO uint32_t bDeviceState = UNCONNECTED;
|
|
__IO uint8_t fSuspendEnabled = TRUE;
|
|
__IO uint32_t EP[8];
|
|
|
|
struct
|
|
{
|
|
__IO RESUME_STATE eState;
|
|
__IO uint8_t bESOFcnt;
|
|
}
|
|
ResumeS;
|
|
|
|
|
|
|
|
__IO uint32_t remotewakeupon=0;
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
* @fn PowerOn
|
|
*
|
|
* @brief Enable power on.
|
|
*
|
|
* @return USB_SUCCESS.
|
|
*/
|
|
RESULT PowerOn(void)
|
|
{
|
|
uint16_t wRegVal;
|
|
|
|
wRegVal = CNTR_FRES;
|
|
_SetCNTR(wRegVal);
|
|
wInterrupt_Mask = 0;
|
|
_SetCNTR(wInterrupt_Mask);
|
|
_SetISTR(0);
|
|
wInterrupt_Mask = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM;
|
|
_SetCNTR(wInterrupt_Mask);
|
|
|
|
return USB_SUCCESS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* @fn PowerOff
|
|
*
|
|
* @brief handles switch-off conditions
|
|
*
|
|
* @return USB_SUCCESS.
|
|
*/
|
|
RESULT PowerOff(void)
|
|
{
|
|
_SetCNTR(CNTR_FRES);
|
|
_SetISTR(0);
|
|
_SetCNTR(CNTR_FRES + CNTR_PDWN);
|
|
|
|
return USB_SUCCESS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* @fn Suspend
|
|
*
|
|
* @brief sets suspend mode operating conditions
|
|
*
|
|
* @return USB_SUCCESS.
|
|
*/
|
|
void Suspend(void)
|
|
{
|
|
uint32_t i =0;
|
|
uint16_t wCNTR;
|
|
|
|
wCNTR = _GetCNTR();
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
EP[i] = _GetENDPOINT(i);
|
|
}
|
|
|
|
wCNTR|=CNTR_RESETM;
|
|
_SetCNTR(wCNTR);
|
|
|
|
wCNTR|=CNTR_FRES;
|
|
_SetCNTR(wCNTR);
|
|
|
|
wCNTR&=~CNTR_FRES;
|
|
_SetCNTR(wCNTR);
|
|
|
|
while((_GetISTR()&ISTR_RESET) == 0);
|
|
|
|
_SetISTR((uint16_t)CLR_RESET);
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
_SetENDPOINT(i, EP[i]);
|
|
}
|
|
|
|
wCNTR |= CNTR_FSUSP;
|
|
_SetCNTR(wCNTR);
|
|
|
|
wCNTR = _GetCNTR();
|
|
wCNTR |= CNTR_LPMODE;
|
|
_SetCNTR(wCNTR);
|
|
|
|
usb_enter_LowPowerMode();
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* @fn Resume_Init
|
|
*
|
|
* @brief Handles wake-up restoring normal operations
|
|
*
|
|
* @return USB_SUCCESS.
|
|
*/
|
|
void Resume_Init(void)
|
|
{
|
|
uint16_t wCNTR;
|
|
|
|
wCNTR = _GetCNTR();
|
|
wCNTR &= (~CNTR_LPMODE);
|
|
_SetCNTR(wCNTR);
|
|
usb_leave_LowPowerMode();
|
|
_SetCNTR(IMR_MSK);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* @fn Resume
|
|
*
|
|
* @brief This is the state machine handling resume operations and
|
|
* timing sequence. The control is based on the Resume structure
|
|
* variables and on the ESOF interrupt calling this subroutine
|
|
* without changing machine state.
|
|
*
|
|
* @param a state machine value (RESUME_STATE)
|
|
* RESUME_ESOF doesn't change ResumeS.eState allowing
|
|
* decrementing of the ESOF counter in different states.
|
|
*
|
|
* @return None.
|
|
*/
|
|
void Resume(RESUME_STATE eResumeSetVal)
|
|
{
|
|
uint16_t wCNTR;
|
|
|
|
if (eResumeSetVal != RESUME_ESOF) {
|
|
ResumeS.eState = eResumeSetVal;
|
|
}
|
|
|
|
switch (ResumeS.eState) {
|
|
case RESUME_EXTERNAL: {
|
|
if (remotewakeupon == 0) {
|
|
Resume_Init();
|
|
ResumeS.eState = RESUME_OFF;
|
|
} else {
|
|
ResumeS.eState = RESUME_ON;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case RESUME_INTERNAL: {
|
|
Resume_Init();
|
|
ResumeS.eState = RESUME_START;
|
|
remotewakeupon = 1;
|
|
break;
|
|
}
|
|
|
|
case RESUME_LATER: {
|
|
ResumeS.bESOFcnt = 2;
|
|
ResumeS.eState = RESUME_WAIT;
|
|
break;
|
|
}
|
|
|
|
case RESUME_WAIT: {
|
|
ResumeS.bESOFcnt--;
|
|
if (ResumeS.bESOFcnt == 0) {
|
|
ResumeS.eState = RESUME_START;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case RESUME_START: {
|
|
wCNTR = _GetCNTR();
|
|
wCNTR |= CNTR_RESUME;
|
|
_SetCNTR(wCNTR);
|
|
ResumeS.eState = RESUME_ON;
|
|
ResumeS.bESOFcnt = 10;
|
|
break;
|
|
}
|
|
|
|
case RESUME_ON: {
|
|
ResumeS.bESOFcnt--;
|
|
if (ResumeS.bESOFcnt == 0) {
|
|
wCNTR = _GetCNTR();
|
|
wCNTR &= (~CNTR_RESUME);
|
|
_SetCNTR(wCNTR);
|
|
ResumeS.eState = RESUME_OFF;
|
|
remotewakeupon = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case RESUME_OFF:
|
|
case RESUME_ESOF:
|
|
default: {
|
|
ResumeS.eState = RESUME_OFF;
|
|
}
|
|
}
|
|
}
|