Skip to content

Commit 76d2924

Browse files
button reader and button service added to demonstrate a freertos thread that reacts to a semaphore triggered from an ISR.
1 parent ebd9f3a commit 76d2924

File tree

16 files changed

+662
-3
lines changed

16 files changed

+662
-3
lines changed

example/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
set(MOCKS_TOP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test/mocks CACHE INTERNAL "")
33
set(DRIVERS_TOP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/drivers CACHE INTERNAL "")
44

5+
include_directories(services/include)
56
add_subdirectory(services)
67
add_subdirectory(drivers)
78
add_subdirectory(apps)

example/apps/demoPcApp/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ FetchContent_MakeAvailable(FreeRTOS-Kernel-DemoPcApp)
1616

1717
add_executable(demoPcApp main.cpp)
1818
include_directories(${FREERTOS_KERNEL_PATH}/include)
19-
target_link_libraries(demoPcApp hwLockCtrlService freertos_kernel freertos_config)
19+
target_link_libraries(demoPcApp hwLockCtrlService buttonService freertos_kernel freertos_config)

example/apps/demoPcApp/main.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "FreeRTOS.h"
66
#include "task.h"
77
#include "hwLockCtrlService.h"
8+
#include "buttonService.h"
89

910
static HLCS_LockStateT s_lastState = HLCS_LOCK_STATE_UNKNOWN;
1011

@@ -54,7 +55,8 @@ DesiredAction GetUserAction()
5455
std::cout << "0: Unlock the lock" << std::endl;
5556
std::cout << "1: Lock the lock" << std::endl;
5657
std::cout << "2: Self Test the lock" << std::endl;
57-
std::cout << "3: Exit" << std::endl
58+
std::cout << "3: Button ISR" << std::endl;
59+
std::cout << "9: Exit" << std::endl
5860
<< std::endl;
5961

6062
while (true) {
@@ -67,6 +69,9 @@ DesiredAction GetUserAction()
6769
case '2':
6870
return DesiredAction::SELF_TEST;
6971
case '3':
72+
ButtonService_SimulateIsr();
73+
continue;
74+
case '9':
7075
return DesiredAction::EXIT;
7176
default:
7277
vTaskDelay(10);
@@ -97,13 +102,24 @@ void UserInputTask(void*)
97102
}
98103
}
99104

105+
void ButtonChangeCallback(ButtonFlagT flags, ButtonStateT state, void* context)
106+
{
107+
(void)context;
108+
printf("%s(flags = 0x%x, state = %d)\n",
109+
__FUNCTION__ , flags, state);
110+
}
111+
100112
int main()
101113
{
102114
HLCS_Init();
103115
HLCS_RegisterChangeStateCallback(LockStateChangeCallback);
104116
HLCS_RegisterSelfTestResultCallback(SelfTestResultCallback);
105117
HLCS_Start(EXECUTION_OPTION_NORMAL);
106118

119+
ButtonService_Init();
120+
ButtonService_RegisterButtonChangeCallback(ButtonChangeCallback, nullptr);
121+
ButtonService_Start(EXECUTION_OPTION_NORMAL);
122+
107123
TaskHandle_t input_thread = nullptr;
108124
BaseType_t ok = xTaskCreate(UserInputTask, "Input", 2000,
109125
nullptr, tskIDLE_PRIORITY+2, &input_thread);

example/drivers/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
add_subdirectory(hwLockCtrl)
2+
add_subdirectory(buttonReader)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
include_directories(include)
2+
add_library(buttonReader include/buttonReader.h src/buttonReader.c)
3+
target_include_directories(buttonReader PUBLIC include)
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
MIT License
3+
4+
Copyright (c) <2024> <Matthew Eshleman - https://covemountainsoftware.com>
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
*/
24+
25+
/**
26+
* @brief public header for the Button Reader driver.
27+
* This driver provides methods to read
28+
* the status of up to 16 buttons.
29+
* Additionally, it provides an ISR callback.
30+
*
31+
*/
32+
#ifndef BUTTON_READER_H
33+
#define BUTTON_READER_H
34+
35+
#include <stdbool.h>
36+
#include <stdint.h>
37+
38+
#ifdef __cplusplus
39+
extern "C" {
40+
#endif
41+
42+
/**
43+
* @brief initializes the driver.
44+
* @return true - initialization completed successfully.
45+
* false - some error.
46+
*/
47+
bool ButtonReaderInit();
48+
49+
/**
50+
* Read the pressed/released status. Guaranteed atomic.
51+
* @param pressed: which buttons pressed since last read.
52+
* @param released: which buttons released since last read.
53+
* @return true: read ok. otherwise error.
54+
*/
55+
bool ButtonReaderRead(uint16_t* pressed, uint16_t* released);
56+
57+
/*
58+
* ISR Function Callback type.
59+
*/
60+
typedef void (*ButtonReaderIsrCallback)(void* context);
61+
62+
/**
63+
* Register a callback to be executed when the button change ISR is hit.
64+
* @param callback
65+
* @param context
66+
* @return
67+
*/
68+
bool ButtonReaderRegisterIsrCallback(ButtonReaderIsrCallback callback, void* context);
69+
70+
#ifdef __cplusplus
71+
}
72+
#endif
73+
74+
#endif //BUTTON_READER_H
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* This concrete implementation of the Button Reader "C" style interface
3+
* is for demo purposes only. The focus of this project
4+
* is how to test FreeRTOS threads, hence
5+
* this fake driver module.
6+
*/
7+
#include "buttonReader.h"
8+
#include <stdio.h>
9+
10+
static ButtonReaderIsrCallback s_isrCallback;
11+
static void* s_isrContext;
12+
13+
bool ButtonReaderInit()
14+
{
15+
printf("%s() executed\n", __FUNCTION__);
16+
s_isrCallback = NULL;
17+
s_isrContext = NULL;
18+
return true;
19+
}
20+
21+
bool ButtonReaderRead(uint16_t* pressed, uint16_t* released)
22+
{
23+
static bool toggle = false;
24+
printf("%s() executed\n", __FUNCTION__);
25+
26+
if ((pressed == NULL) || (released == NULL))
27+
{
28+
return false;
29+
}
30+
31+
if (toggle)
32+
{
33+
*pressed = 2;
34+
*released = 0;
35+
}
36+
else
37+
{
38+
*pressed = 0;
39+
*released = 2;
40+
}
41+
42+
toggle = !toggle;
43+
44+
return true;
45+
}
46+
47+
bool ButtonReaderRegisterIsrCallback(ButtonReaderIsrCallback callback, void* context)
48+
{
49+
printf("%s() executed\n", __FUNCTION__);
50+
51+
s_isrCallback = callback;
52+
s_isrContext = context;
53+
return true;
54+
}

example/services/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
include_directories(${FREERTOS_KERNEL_PATH}/include)
2-
add_subdirectory(hwLockCtrlService)
2+
add_subdirectory(hwLockCtrlService)
3+
add_subdirectory(buttonService)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
include_directories(include)
2+
add_subdirectory(test)
3+
add_library(buttonService include/buttonService.h src/buttonService.c)
4+
target_link_libraries(buttonService buttonReader freertos_kernel freertos_config)
5+
target_include_directories(buttonService PUBLIC include)
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
MIT License
3+
4+
Copyright (c) <2024> <Matthew Eshleman - https://covemountainsoftware.com>
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
*/
24+
25+
#ifndef BUTTON_SERVICE_H
26+
#define BUTTON_SERVICE_H
27+
28+
#include <stdbool.h>
29+
#include "cmsExecutionOption.h"
30+
31+
#ifdef __cplusplus
32+
extern "C" {
33+
#endif
34+
35+
/**
36+
* Buttons supported on this product
37+
*/
38+
typedef enum ButtonFlag {
39+
BUTTON_ON_OFF = 0x1,
40+
BUTTON_FUNC_A = 0x2,
41+
} ButtonFlagT;
42+
43+
typedef enum ButtonState {
44+
BUTTON_PRESSED,
45+
BUTTON_RELEASED,
46+
} ButtonStateT;
47+
48+
/**
49+
* Initialize the Button Service. Does not start the thread, just prepares.
50+
*/
51+
void ButtonService_Init();
52+
53+
/**
54+
* Destroy the ButtonService. Typically only called in unit testing environment.
55+
*/
56+
void ButtonService_Destroy();
57+
58+
/**
59+
* Start the button service/thread. Init() must have been called first.
60+
* @param option
61+
*/
62+
void ButtonService_Start(ExecutionOptionT option);
63+
64+
/**
65+
* typedef for the button service callback
66+
*/
67+
typedef void (*ButtonService_ButtonChangeCallback)(ButtonFlagT flags, ButtonStateT state, void *context);
68+
69+
/**
70+
* Register callback to be executed from the button service
71+
* thread context. Guaranteed to NOT be called from an ISR context.
72+
* @param callback
73+
* @param context
74+
*/
75+
void ButtonService_RegisterButtonChangeCallback(ButtonService_ButtonChangeCallback callback, void *context);
76+
77+
/****************************************************************************/
78+
/***** Backdoor functionality provided for unit testing access only ********/
79+
/****************************************************************************/
80+
81+
/**
82+
* provided for unit testing access only. For the button service,
83+
* will check if semaphore token is available or not (i.e.
84+
* the button ISR has occurred).
85+
*
86+
* @param option EXECUTION_OPTION_NORMAL - internal, normal thread use
87+
* EXECUTION_OPTION_UNIT_TEST - for unit testing
88+
*
89+
* @return true: an event was processed
90+
* false: no events, nothing processed.
91+
*/
92+
bool ButtonService_ProcessOneEvent(ExecutionOptionT option);
93+
94+
/**
95+
* Fake/simulate the ISR that the button service relies upon
96+
*/
97+
void ButtonService_SimulateIsr();
98+
99+
#ifdef __cplusplus
100+
}
101+
#endif
102+
103+
#endif //BUTTON_SERVICE_H

0 commit comments

Comments
 (0)