Skip to content

Commit

Permalink
【USB】更完善的休眠唤醒支持
Browse files Browse the repository at this point in the history
  • Loading branch information
genokolar committed Nov 7, 2024
1 parent e7d1814 commit c706f43
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 73 deletions.
12 changes: 5 additions & 7 deletions usb/endpoints.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "endpoints.h"

#define THIS_ENDP0_SIZE DEFAULT_ENDP0_SIZE
#define REMOTE_WAKE true

/**
* @brief 端点0/4缓冲区。
Expand Down Expand Up @@ -96,15 +95,15 @@ void EP0_OUT()
break;
case SETUP_STATE_OUT:
// 重置端点状态,等待下次传输
UEP0_CTRL ^= bUEP_R_TOG; //同步标志位翻转
UEP0_CTRL ^= bUEP_R_TOG; //同步标志位翻转
usb_state.setup_state = SETUP_IDLE;
break;
case SETUP_DATA_OUT:
// 似乎没有下传的数据
break;
default:
// ERROR
UEP0_CTRL ^= bUEP_R_TOG; //同步标志位翻转
UEP0_CTRL ^= bUEP_R_TOG; //同步标志位翻转
usb_state.setup_state = SETUP_IDLE;
break;
}
Expand Down Expand Up @@ -181,6 +180,9 @@ void EP0_SETUP()
// USB枚举完毕
usb_state.is_ready = UsbConfig > 0;
usb_state.setup_state = SETUP_STATE_IN;
//枚举完成代表接入了正确的主机,将RESET_KEEP寄存器写入1,在重新断电上电RESET_KEEP清零之前
//可认为CH552一直正确接入主机上
RESET_KEEP = 1;
break;

case USB_GET_INTERFACE:
Expand Down Expand Up @@ -225,7 +227,6 @@ void EP0_SETUP()
}
break;
}
#if REMOTE_WAKE
case USB_REQ_TO_DEVICE:
if (UsbSetupBuf->wValue != 0x01) {
// 操作失败
Expand All @@ -235,7 +236,6 @@ void EP0_SETUP()
// 设置唤醒使能标志
usb_state.remote_wake = false;
break;
#endif
default: //unsupport
SETUP_STALL();
return;
Expand Down Expand Up @@ -276,7 +276,6 @@ void EP0_SETUP()
}
break;
}
#if REMOTE_WAKE
case USB_REQ_TO_DEVICE: {
if (UsbSetupBuf->wValue != 0x01) {
SETUP_STALL();
Expand All @@ -286,7 +285,6 @@ void EP0_SETUP()
usb_state.remote_wake = true;
break;
}
#endif
default:
SETUP_STALL();
return;
Expand Down
36 changes: 14 additions & 22 deletions usb/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,29 +84,21 @@ static void UsbTransfurEventHandler()
*/
static void UsbBusResetEventHandler()
{
//部分特殊的电脑休眠唤醒后,无法正确的接入电脑
//此处添加对休眠唤醒过程的判断,如遇到休眠唤醒时复位总线的,进行一次软复位
if (usb_state.remote_wake) {
//软复位
SAFE_MOD = 0x55;
SAFE_MOD = 0xAA;
GLOBAL_CFG |= bSW_RESET;
} else {
//总线复位
UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
UEP1_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;
UEP2_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;
UEP3_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;
UEP4_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;
USB_DEV_AD = 0x00;
UIF_SUSPEND = 0;
UIF_TRANSFER = 0;
UIF_BUS_RST = 0; //清中断标志
// 总线复位
UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
UEP1_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;
UEP2_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;
UEP3_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;
UEP4_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;
USB_DEV_AD = 0x00;
UIF_SUSPEND = 0;
UIF_TRANSFER = 0;
UIF_BUS_RST = 0; // 清中断标志

// 重置状态
usb_state.is_ready = false;
usb_state.protocol = true;
usb_state.setup_state = SETUP_IDLE;
// 重置状态
usb_state.is_ready = false;
usb_state.protocol = true;
usb_state.setup_state = SETUP_IDLE;
}

/** \brief USB 总线挂起或唤醒事件处理
Expand Down
39 changes: 17 additions & 22 deletions usb/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,14 @@ static void CH554SoftReset()
/** \brief CH554设备模式唤醒主机,发送K信号
*
*/
static void CH554USBDevWakeup()
void CH554USBDevWakeup()
{
UDEV_CTRL |= bUD_LOW_SPEED;
DelayMs(2);
UDEV_CTRL &= ~bUD_LOW_SPEED;
if (usb_state.is_sleep && usb_state.remote_wake) {
usb_state.is_sleep = false;
UDEV_CTRL |= bUD_LOW_SPEED;
DelayMs(2);
UDEV_CTRL &= ~bUD_LOW_SPEED;
}
}

/** \brief CH559USB中断处理函数
Expand All @@ -69,32 +72,24 @@ void KeyboardGenericUpload(uint8_t* packet, uint8_t len)
{
if (len != 8)
return;
if ((USB_MIS_ST & bUMS_SUSPEND) && usb_state.remote_wake) {
CH554USBDevWakeup();
} else {
usb_state.is_busy = true;
memcpy(&Ep1Buffer[64], packet, len);
UEP1_T_LEN = len;
UEP1_CTRL = UEP1_CTRL & ~MASK_UEP_T_RES | UEP_T_RES_ACK;
}
usb_state.is_busy = true;
memcpy(&Ep1Buffer[64], packet, len);
UEP1_T_LEN = len;
UEP1_CTRL = UEP1_CTRL & ~MASK_UEP_T_RES | UEP_T_RES_ACK;
}

/**
* @brief 上传键盘特殊按键数据包
*
* @param packet 数据包,第一个byte为ID
* @param packet 数据包,第一个byte为ID 对应HID ReportID 1: mouse, 2: system, 3: consumer, 0x80: nkro
* @param len 长度
*/
void KeyboardExtraUpload(uint8_t* packet, uint8_t len)
{
if ((USB_MIS_ST & bUMS_SUSPEND) && usb_state.remote_wake) {
CH554USBDevWakeup();
} else {
usb_state.is_busy = true;
memcpy(Ep2Buffer, packet, len);
UEP2_T_LEN = len;
UEP2_CTRL = UEP2_CTRL & ~MASK_UEP_T_RES | UEP_T_RES_ACK;
}
usb_state.is_busy = true;
memcpy(Ep2Buffer, packet, len);
UEP2_T_LEN = len;
UEP2_CTRL = UEP2_CTRL & ~MASK_UEP_T_RES | UEP_T_RES_ACK;
}

/**
Expand Down Expand Up @@ -225,11 +220,11 @@ static void main()
IE_TKEY = 1; // 运行Timer

USBDeviceInit(); //USB设备模式初始化
EA = 1; //允许单片机中断
EnableWatchDog();
#ifdef ONBOARD_CMSIS_DAP
Dap_Init();
#endif
EA = 1; //允许单片机中断
UEP1_T_LEN = 0; //预使用发送长度一定要清空
UEP2_T_LEN = 0; //预使用发送长度一定要清空
UEP3_T_LEN = 0;
Expand Down
50 changes: 28 additions & 22 deletions usb/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <stdbool.h>
#include <string.h>

#ifdef PIN_STANDBY
#define IS_CHARGING (PIN_CHARGING && !PIN_STANDBY)
#else
#define IS_CHARGING (PIN_CHARGING)
#endif

uart_state uart_rx_state;
static uint8_t recv_len, pos;
static uint8_t __XDATA volatile recv_buff[64];
Expand Down Expand Up @@ -110,14 +104,28 @@ static void uart_data_parser(void)
} else if (command >= 0x40) {
uint8_t index = recv_buff[1];
uint8_t kplen = (command & 0x3F);
if (index == 0) {
// 通常键盘数据包
KeyboardGenericUpload(&recv_buff[2], kplen);
if (index == 0) { // 类型Index。0: generic, 1: mouse, 2: system, 3: consumer, 0x80: nkro
// 连接中断,尝试唤醒
if (USB_MIS_ST & bUMS_SUSPEND) {
usb_state.is_busy = true;
CH554USBDevWakeup();
usb_state.is_busy = false;
} else if(usb_state.is_ready) {
// 通常键盘数据包
KeyboardGenericUpload(&recv_buff[2], kplen);
}
last_success = true;
} else {
// 附加数据包
// 发过来的包的id和reportID一致,不用处理
KeyboardExtraUpload(&recv_buff[1], kplen + 1);
} else { // 附加数据包
// 类型Index。0: generic, 1: mouse, 2: system, 3: consumer, 0x80: nkro
// 连接中断,尝试唤醒
if (USB_MIS_ST & bUMS_SUSPEND) {
usb_state.is_busy = true;
CH554USBDevWakeup();
usb_state.is_busy = false;
} else if(usb_state.is_ready) {
// 附加数据包
KeyboardExtraUpload(&recv_buff[1], kplen + 1);
}
last_success = true;
}
}
Expand All @@ -130,13 +138,11 @@ static void uart_data_parser(void)
static void uart_send_status()
{
uint8_t data = 0x10;
#ifdef PIN_CHARGING
if (!IS_CHARGING) // 是否充满
data |= 0x02;
#endif
if (usb_state.is_ready || usb_state.remote_wake) // 是否连接主机
if ((USB_MIS_ST & bUMS_SUSPEND) && RESET_KEEP) //曾经枚举成功,当前连接中断-->已连接但进入休眠
data |= 0x02;
if (RESET_KEEP) // 是否连接主机
data |= 0x04;
if (usb_state.protocol)
if (usb_state.protocol) //是否report protocol
data |= 0x08;
if (last_success) // 上次接收状态
data |= 0x01;
Expand Down Expand Up @@ -181,7 +187,7 @@ void uart_check()
}

/**
* @brief 接收数据
* @brief 接收到nRF52数据
*
*/
void uart_recv(void)
Expand Down Expand Up @@ -215,7 +221,7 @@ void uart_recv(void)
}

/**
* @brief 下发LED信号
* @brief 下发LED信号至nRF52
*
* @param val
*/
Expand All @@ -226,7 +232,7 @@ void uart_send_led(uint8_t val)
}

/**
* @brief 下发keymap数据
* @brief 下发keymap数据至nRF52
*
* @param data
* @param len
Expand Down
1 change: 1 addition & 0 deletions usb/usb_comm.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
void KeyboardGenericUpload(uint8_t * packet, uint8_t len);
void KeyboardExtraUpload(uint8_t * packet, uint8_t len);
void ResponseConfigurePacket(uint8_t * packet, uint8_t len);
void CH554USBDevWakeup();

0 comments on commit c706f43

Please sign in to comment.