這是我打的第一次比賽,主打的pwn方向,紀念我的成長 需求:一定的linux系統的命令指令知識,基礎的彙編代碼,配置好了的虛擬機(打pwn建議是ubuntu),pwntools的使用,python的使用,ROPgadget的使用 每次把文件拖入IDA前記得用Exeinfope進行檢查一下,看是x86 ...
本模塊模仿MultiButton實現的。GitHub:https://github.com/0x1abin/MultiButton
Freertos學習項目來自B站up主:https://www.bilibili.com/video/BV13R4y177jU/?spm_id_from=333.999.0.0
分享測試文件:
鏈接:https://pan.baidu.com/s/1dqXc-_ycR-Tl-KQtsxJs4A
提取碼:1234
按鍵狀態主要實現了以下幾個: typedef enum { KeyEvent_Idle = 0, KeyEvent_PutDown,//按下 KeyEvent_RealeaseUp,//彈起 KeyEvent_Click,//單擊 KeyEvent_DoubleClick,//雙擊 KeyEvent_LongPressStart,//長按開始 KeyEvent_LongPressRepeat,//長按持續 KeyEvent_LongPressEnd,//長按結束 KeyEvent_Stuck,//按鍵卡死 KeyEvent_Free//按鍵恢復 } KeyEvent_Def; 然後為每一個按鍵都設置一個結構體,通過鏈表連接: typedef struct Key { struct Key *pNext; //指向下一個按鍵結構體 uint32_t dwPressedTicks;//按下的時長 uint32_t dwReleasedTicks;//彈起後的時長 uint32_t dwLongPressRepeat_Ticks;//長按下的時長,用於重發事件 uint8_t byDebounce_Count;//按鍵消抖計數 uint8_t byEvent;//觸發的事件 uint8_t byKey_Level;//按鍵的電平 uint8_t byKeyStatus;//按鍵的狀態 uint8_t byMultiplePressEnable;//雙擊開啟標誌 GetIOStatus pGetIOLevel_Func;//獲取GPIO電平的函數 KeyEventProcess pProcess_Func;//按鍵事件處理函數 } KeyInfo_Def; 整個模塊大致邏輯:獲取輸入,根據狀態輸出事件。 輸入:uint8_t byRead_IO_Level = pHandle->pGetIOLevel_Func(); 輸出:KeyEvent_Process(pHandle, KeyEvent_RealeaseUp); 通過把每一個按鍵結構體通過鏈表連接起來,再定時去輪詢按鍵的狀態,然後觸發事件。 加入按鍵:int Add_KeyToList(KeyInfo_Def *pCurNode) 輪詢按鍵: KeyInfo_Def *pTarget; for (pTarget = pHead_Node; pTarget; pTarget = pTarget->pNext) { if (pTarget == NULL) return; Key_handler(pTarget); } 使用時:先創建一個隊列句柄和幾個按鍵結構體以及我們需要傳遞的信息(通過隊列在任務之間通信) static QueueHandle_t xKeyInfoQueue; static KeyProcessInfo_Def KeyData; static KeyInfo_Def key1; static KeyInfo_Def key2; static KeyInfo_Def key3; static KeyInfo_Def key4; static KeyInfo_Def key5; static KeyInfo_Def key6; 初始化鏈表,再把按鍵掛到鏈表上,並創建一個隊列: void Key_Init(void) { List_Init();
// 註冊按鍵 Key_Attach(&key1, Read_Key1, Key1_Event_Process, DPress_Enable); Key_Attach(&key2, Read_Key2, Key2_Event_Process, DPress_Enable); Key_Attach(&key3, Read_Key3, Key3_Event_Process, DPress_Enable); Key_Attach(&key4, Read_Key4, Key4_Event_Process, DPress_Enable); Key_Attach(&key5, Read_Key5, Key5_Event_Process, DPress_Enable); Key_Attach(&key6, Read_Key6, Key6_Event_Process, DPress_Enable);
xKeyInfoQueue = xQueueCreate(2, sizeof(KeyProcessInfo_Def)); } 在按鍵檢測任務中每1ms輪詢一次,並檢測按鍵狀態,觸發事件,並把信息KeyData傳遞給隊列: void KEYDetect_task(void const *pvParameters) { Key_Init(); for(;;) { Key_Ticks_1ms(); //printf("key Task \n\r"); vTaskDelay(1); } } 在另外一個任務中獲取該信息放到keyInfo中: KeyProcessInfo_Def keyInfo; for(;;) { if(Get_KeyInfo(&keyInfo,1000) == 0) { memset(&keyInfo, 0, sizeof(KeyProcessInfo_Def)); //printf("QUEUE_EMPTY\n\r"); } if(keyInfo.byKey_Num ==3) { if(keyInfo.byKey_event==KeyEvent_Click) { printf("Key 3 Click\n\r"); } else if(keyInfo.byKey_event==KeyEvent_PutDown) { printf("Key 3 PutDown\n\r"); } else if(keyInfo.byKey_event==KeyEvent_RealeaseUp) { printf("Key 3 RealeaseUp\n\r"); } else if(keyInfo.byKey_event==KeyEvent_DoubleClick) { printf("Key 3 DoubleClick\n\r"); } else if(keyInfo.byKey_event==KeyEvent_LongPressStart) { printf("Key 3 LongPressStart\n\r"); } else if(keyInfo.byKey_event==KeyEvent_LongPressRepeat) { printf("Key 3 LongPressRepeat\n\r"); } else if(keyInfo.byKey_event==KeyEvent_LongPressEnd) { printf("Key 3 LongPressEnd\n\r"); } else if(keyInfo.byKey_event==KeyEvent_Free) { printf("Key 3 Free\n\r"); } else if(keyInfo.byKey_event==KeyEvent_Stuck) { printf("Key 3 Stuck\n\r"); } } SetGPIO_Toggle(LED1); //printf("Task 1 \n\r"); //vTaskDelay(1000);
當按鍵按下,就可以在另外一個任務中去列印當前的按鍵事件了。
整體代碼內容:
#include "bsp_includes.h" #include <string.h> static KeyInfo_Def *pHead_Node = NULL; /************************************************************************** * @brief 初始化鏈表頭結點 **************************************************************************/ void List_Init(void) { pHead_Node = NULL; } /************************************************************************** * @brief 獲取按鍵當前觸發的事件 **************************************************************************/ u8 Get_KeyCurEvent(KeyInfo_Def *pHandle) { return (u8)(pHandle->byEvent); } /************************************************************************** * @brief 把新增的按鍵加入鏈表 **************************************************************************/ int Add_KeyToList(KeyInfo_Def *pCurNode) { KeyInfo_Def *pTargetNode = pHead_Node; while (pTargetNode) { if (pTargetNode == pCurNode) { return -1; // already exist. } pTargetNode = pTargetNode->pNext; // find Null node } pCurNode->pNext = pHead_Node; pHead_Node = pCurNode; return 0; // add success } /************************************************************************** * @brief 註冊按鍵信息 **************************************************************************/ void Key_Attach(KeyInfo_Def *pHandle, GetIOStatus pFunc1, KeyEventProcess pFunc2, uint8_t byState) { memset(pHandle, 0, sizeof(KeyInfo_Def)); pHandle->dwPressedTicks = 0; pHandle->dwReleasedTicks = 0; pHandle->dwLongPressRepeat_Ticks = 0; pHandle->byEvent = KeyEvent_Idle; pHandle->byKeyStatus = Key_IDLE; pHandle->byDebounce_Count = 0; pHandle->byMultiplePressEnable = byState; pHandle->pGetIOLevel_Func = pFunc1; pHandle->pProcess_Func = pFunc2; pHandle->byKey_Level = pHandle->pGetIOLevel_Func(); Add_KeyToList(pHandle); } void KeyEvent_Process(KeyInfo_Def *handle, KeyEvent_Def keyEvent) { handle->byEvent = keyEvent; handle->pProcess_Func(handle, handle->byEvent); } /************************************************************************** * @brief 按鍵狀態機 **************************************************************************/ void Key_handler(KeyInfo_Def *pHandle) { uint8_t byRead_IO_Level = pHandle->pGetIOLevel_Func(); /*------------button debounce handle---------------*/ if (byRead_IO_Level != pHandle->byKey_Level) // not equal to prev one { // continue read 3 times same new level change if (++(pHandle->byDebounce_Count) >= DEBOUNCE_TICKS) { pHandle->byKey_Level = byRead_IO_Level; pHandle->byDebounce_Count = 0; if (pHandle->byKey_Level == Pressed) { KeyEvent_Process(pHandle, KeyEvent_PutDown); } else { KeyEvent_Process(pHandle, KeyEvent_RealeaseUp); } } } else { // leved not change ,counter reset. pHandle->byDebounce_Count = 0; } if (pHandle->dwReleasedTicks < 300000) // 300s pHandle->dwReleasedTicks++; if (pHandle->dwPressedTicks < 300000) pHandle->dwPressedTicks++; if (byRead_IO_Level != pHandle->byKey_Level) { if (byRead_IO_Level == Pressed) pHandle->dwPressedTicks = 0; else pHandle->dwReleasedTicks = 0; } switch (pHandle->byKeyStatus) { case Key_IDLE: if (pHandle->byKey_Level == Pressed) { if (pHandle->dwPressedTicks >= ShortPress_Ticks) { KeyEvent_Process(pHandle, KeyEvent_LongPressStart); pHandle->dwLongPressRepeat_Ticks = 0; pHandle->byKeyStatus = Key_LongPress; } else { pHandle->byKeyStatus = Key_ACK; } } else { pHandle->byKeyStatus = Key_IDLE; } break; case Key_ACK: if (pHandle->byKey_Level == Pressed) { if (pHandle->dwPressedTicks >= ShortPress_Ticks) { KeyEvent_Process(pHandle, KeyEvent_LongPressStart); pHandle->dwLongPressRepeat_Ticks = 0; pHandle->byKeyStatus = Key_LongPress; } } else { if (pHandle->byMultiplePressEnable == DPress_Disable) { KeyEvent_Process(pHandle, KeyEvent_Click); pHandle->byKeyStatus = Key_IDLE; } else { pHandle->byKeyStatus = Key_WaitDoublePress; } } break; case Key_WaitDoublePress: if (pHandle->byKey_Level == Pressed) { if (pHandle->dwReleasedTicks <= DoubleClickIdle_Ticks) { if (pHandle->byMultiplePressEnable == DPress_Enable) KeyEvent_Process(pHandle, KeyEvent_DoubleClick); else KeyEvent_Process(pHandle, KeyEvent_PutDown); pHandle->byKeyStatus = Key_WaitDoublePressIdle; } } else { if (pHandle->dwReleasedTicks > DoubleClickIdle_Ticks) { KeyEvent_Process(pHandle, KeyEvent_Click); pHandle->byKeyStatus = Key_IDLE; } } break; case Key_WaitDoublePressIdle: if (pHandle->byKey_Level == Released) { pHandle->byKeyStatus = Key_IDLE; } break; case Key_LongPress: if (pHandle->byKey_Level == Pressed) { if (pHandle->dwPressedTicks > Stuck_Ticks) { KeyEvent_Process(pHandle, KeyEvent_Stuck); pHandle->byKeyStatus = Key_STUCK; } else if (pHandle->dwLongPressRepeat_Ticks > LongPressRepeat_Ticks) { KeyEvent_Process(pHandle, KeyEvent_LongPressRepeat); pHandle->dwLongPressRepeat_Ticks = 0; } else { pHandle->dwLongPressRepeat_Ticks++; } } else { KeyEvent_Process(pHandle, KeyEvent_LongPressEnd); pHandle->byKeyStatus = Key_IDLE; } break; case Key_STUCK: if (pHandle->byKey_Level == Released) { KeyEvent_Process(pHandle, KeyEvent_Free); pHandle->byKeyStatus = Key_IDLE; } default: break; } } /************************************************************************** * @brief 移除按鍵節點 **************************************************************************/ void Remove_Key(KeyInfo_Def *pTarget) { KeyInfo_Def **ppCur; KeyInfo_Def *entry = *ppCur; for (ppCur = &pHead_Node; (*ppCur) != NULL;) { if (entry == pTarget) { *ppCur = entry->pNext; // free(entry); } else { ppCur = &entry->pNext; } } } /************************************************************************** * @brief 毫秒處理函數 **************************************************************************/ void Key_Ticks_1ms(void) { KeyInfo_Def *pTarget; for (pTarget = pHead_Node; pTarget; pTarget = pTarget->pNext) { if (pTarget == NULL) return; Key_handler(pTarget); } } /*-------------------------------------------------------------------------- * 按鍵註冊,可擴展 ----------------------------------------------------------------------------*/ static QueueHandle_t xKeyInfoQueue; static KeyProcessInfo_Def KeyData; static KeyInfo_Def key1; static KeyInfo_Def key2; static KeyInfo_Def key3; static KeyInfo_Def key4; static KeyInfo_Def key5; static KeyInfo_Def key6; /************************************************************************** * @brief 獲取按鍵IO狀態 **************************************************************************/ uint8_t Read_Key1(void) { return (ReadGPIO(KEY1)); } uint8_t Read_Key2(void) { return (ReadGPIO(KEY2)); } uint8_t Read_Key3(void) { return (ReadGPIO(KEY3)); } uint8_t Read_Key4(void) { return (ReadGPIO(KEY4)); } uint8_t Read_Key5(void) { return (ReadGPIO(KEY5)); } uint8_t Read_Key6(void) { return (ReadGPIO(KEY6)); } /************************************************************************** * @brief 事件過濾 **************************************************************************/ static void Keyx_ChoseEvent(uint8_t byEvent) { switch (byEvent) { case KeyEvent_PutDown: KeyData.byKey_event = KeyEvent_PutDown; break; case KeyEvent_RealeaseUp: KeyData.byKey_event = KeyEvent_RealeaseUp; break; case KeyEvent_Click: KeyData.byKey_event = KeyEvent_Click; break; case KeyEvent_DoubleClick: KeyData.byKey_event = KeyEvent_DoubleClick; break; case KeyEvent_LongPressStart: KeyData.byKey_event = KeyEvent_LongPressStart; break; case KeyEvent_LongPressRepeat: KeyData.byKey_event = KeyEvent_LongPressRepeat; break; case KeyEvent_LongPressEnd: KeyData.byKey_event = KeyEvent_LongPressEnd; break; case KeyEvent_Stuck: KeyData.byKey_event = KeyEvent_Stuck; break; case KeyEvent_Free: KeyData.byKey_event = KeyEvent_Free; break; default: break; } } /************************************************************************** * @brief 按鍵事件處理函數 **************************************************************************/ static void Key1_Event_Process(void *btn, uint8_t event) { Keyx_ChoseEvent(event); KeyData.byKey_Num = 1; xQueueSend(xKeyInfoQueue, (void *)&KeyData, (TickType_t)10); } static void Key2_Event_Process(void *btn, uint8_t event) { Keyx_ChoseEvent(event); KeyData.byKey_Num = 2; xQueueSend(xKeyInfoQueue, (void *)&KeyData, (TickType_t)10); } static void Key3_Event_Process(void *btn, uint8_t event) { Keyx_ChoseEvent(event); KeyData.byKey_Num = 3; xQueueSend(xKeyInfoQueue, (void *)&KeyData, (TickType_t)10); } static void Key4_Event_Process(void *btn, uint8_t event) { Keyx_ChoseEvent(event); KeyData.byKey_Num = 4; xQueueSend(xKeyInfoQueue, (void *)&KeyData, (TickType_t)10); } static void Key5_Event_Process(void *btn, uint8_t event) { Keyx_ChoseEvent(event); KeyData.byKey_Num = 5; xQueueSend(xKeyInfoQueue, (void *)&KeyData, (TickType_t)10); } static void Key6_Event_Process(void *btn, uint8_t event) { Keyx_ChoseEvent(event); KeyData.byKey_Num = 6; xQueueSend(xKeyInfoQueue, (void *)&KeyData, (TickType_t)10); } /************************************************************************** * @brief 按鍵模塊初始化 **************************************************************************/ void Key_Init(void) { List_Init(); // 註冊按鍵 Key_Attach(&key1, Read_Key1, Key1_Event_Process, DPress_Enable); Key_Attach(&key2, Read_Key2, Key2_Event_Process, DPress_Enable); Key_Attach(&key3, Read_Key3, Key3_Event_Process, DPress_Enable); Key_Attach(&key4, Read_Key4, Key4_Event_Process, DPress_Enable); Key_Attach(&key5, Read_Key5, Key5_Event_Process, DPress_Enable); Key_Attach(&key6, Read_Key6, Key6_Event_Process, DPress_Enable); xKeyInfoQueue = xQueueCreate(2, sizeof(KeyProcessInfo_Def)); } /************************************************************************** * @brief 隊列接收,用於傳遞按鍵觸發信息 **************************************************************************/ uint8_t Get_KeyInfo(KeyProcessInfo_Def *ucQueueMsgValue, uint32_t xMaxBlockTime) { long byStatus; byStatus = xQueueReceive(xKeyInfoQueue, (void *)ucQueueMsgValue, (TickType_t)xMaxBlockTime); return (uint8_t)byStatus; }
#ifndef __BSP_KEY_H__ #define __BSP_KEY_H__ #include "bsp_includes.h" #define DEBOUNCE_TICKS 10 #define ShortPress_Ticks 500 #define DoubleClickIdle_Ticks 300 #define Stuck_Ticks 20000 #define LongPressRepeat_Ticks 200 #define DPress_Enable 1 #define DPress_Disable 0 typedef uint8_t (*GetIOStatus)(void); typedef void (*KeyEventProcess)(void *, uint8_t); typedef enum { Released = 1, Pressed = 0 } IOStatus_Def; typedef enum { Key_IDLE = 0, Key_ACK, Key_WaitDoublePress, Key_WaitDoublePressIdle, Key_LongPress, Key_STUCK } KeyStatus_Def; typedef enum { KeyEvent_Idle = 0, KeyEvent_PutDown, KeyEvent_RealeaseUp, KeyEvent_Click, KeyEvent_DoubleClick, KeyEvent_LongPressStart, KeyEvent_LongPressRepeat, KeyEvent_LongPressEnd, KeyEvent_Stuck, KeyEvent_Free } KeyEvent_Def; typedef struct Key { struct Key *pNext; uint32_t dwPressedTicks; uint32_t dwReleasedTicks; uint32_t dwLongPressRepeat_Ticks; uint8_t byDebounce_Count; uint8_t byEvent; uint8_t byKey_Level; uint8_t byKeyStatus; uint8_t byMultiplePressEnable; GetIOStatus pGetIOLevel_Func; KeyEventProcess pProcess_Func; } KeyInfo_Def; /*----------------------------------------------------------------------*/ typedef struct { uint8_t byKey_Num; uint8_t byKey_event; } KeyProcessInfo_Def; void Key_Init(void); uint8_t Get_KeyInfo(KeyProcessInfo_Def *ucQueueMsgValue, uint32_t xMaxBlockTime); void Key_Ticks_1ms(void); #endif /* __BSP_KEY_H__ */
#include "bsp_includes.h" #define LED1_TASK_PRIO 1 #define LED2_TASK_PRIO 2 #define LED3_TASK_PRIO 2 #define KEYDetect_TASK_PRIO 3 #define LED1_STK_SIZE 128 #define LED2_STK_SIZE 128 #define LED3_STK_SIZE 128 #define KEYDetect_STK_SIZE 128 TaskHandle_t LED1Task_Handler; TaskHandle_t LED2Task_Handler; TaskHandle_t LED3Task_Handler; TaskHandle_t KEYDetectTask_Handler; /************************************************************************** * @brief led1_task **************************************************************************/ void led1_task(void const *pvParameters) { KeyProcessInfo_Def keyInfo; for(;;) { if(Get_KeyInfo(&keyInfo,1000) == 0) { memset(&keyInfo, 0, sizeof(KeyProcessInfo_Def)); //printf("QUEUE_EMPTY\n\r"); } if(keyInfo.byKey_Num ==3) { if(keyInfo.byKey_event==KeyEvent_Click) { printf("Key 3 Click\n\r"); } else if(keyInfo.byKey_event==KeyEvent_PutDown) { printf("Key 3 PutDown\n\r"); } else if(keyInfo.byKey_event==KeyEvent_RealeaseUp) { printf("Key 3 RealeaseUp\n\r"); } else if(keyInfo.byKey_event==KeyEvent_DoubleClick) { printf("Key 3 DoubleClick\n\r"); } else if(keyInfo.byKey_event==KeyEvent_LongPressStart) { printf("Key 3 LongPressStart\n\r"); } else if(keyInfo.byKey_event==KeyEvent_LongPressRepeat) { printf("Key 3 LongPressRepeat\n\r"); } else if(keyInfo.byKey_event==KeyEvent_LongPressEnd) { printf("Key 3 LongPressEnd\n\r"); } else if(keyInfo.byKey_event==KeyEvent_Free) { printf("Key 3 Free\n\r"); } else if(keyInfo.byKey_event==KeyEvent_Stuck) { printf("Key 3 Stuck\n\r"); } } SetGPIO_Toggle(LED1); //printf("Task 1 \n\r"); //vTaskDelay(1000); } } /************************************************************************** * @brief led2_task **************************************************************************/ void led2_task(void const *pvParameters) { for(;;) { SetGPIO_Toggle(LED2); //printf("Task 2 \n\r"); vTaskDelay(1000); } } /************************************************************************** * @brief **************************************************************************/ void led3_task(void const *pvParameters) { for(;;) { SetGPIO_Toggle(LED3); //printf("Task 3 \n\r"); vTaskDelay(1000); } } /************************************************************************** * @brief Set_PowerOn **************************************************************************/ void KEYDetect_task(void const *pvParameters) { Key_Init(); for(;;) { Key_Ticks_1ms(); //printf("key Task \n\r"); vTaskDelay(1); } } /************************************************************************** * @brief Set_PowerOn **************************************************************************/ void Set_PowerOn(void) { HAL_Delay(50); SetGPIO_High(POWER_ON); } /************************************************************************** * @brief AppTaskCreat_Init **************************************************************************/ void AppTaskCreat_Init(void) { Set_PowerOn(); taskENTER_CRITICAL(); xTaskCreate((TaskFunction_t) led1_task, (const char *) "led1_task", (uint16_t) LED1_STK_SIZE, (void *) NULL, (UBaseType_t) LED1_TASK_PRIO, (TaskHandle_t *) &LED1Task_Handler); xTaskCreate((TaskFunction_t) led2_task, (const char *) "led2_task", (uint16_t) LED2_STK_SIZE, (void *) NULL, (UBaseType_t) LED2_TASK_PRIO, (TaskHandle_t *) &LED2Task_Handler); xTaskCreate((TaskFunction_t) led3_task, (const char *) "led3_task", (uint16_t) LED3_STK_SIZE, (void *) NULL, (UBaseType_t) LED3_TASK_PRIO, (TaskHandle_t *) &LED3Task_Handler); xTaskCreate((TaskFunction_t) KEYDetect_task, (const char *) "KEYDetect_task", (uint16_t) KEYDetect_STK_SIZE, (void *) NULL, (UBaseType_t) KEYDetect_TASK_PRIO, (TaskHandle_t *) &KEYDetectTask_Handler); vTaskStartScheduler(); taskEXIT_CRITICAL(); }