diff --git a/.copilot/unit_test_agent.md b/.copilot/unit_test_agent.md new file mode 100644 index 00000000..271798c7 --- /dev/null +++ b/.copilot/unit_test_agent.md @@ -0,0 +1,127 @@ +# Unit Test Generation Agent +This agent scans C/C++ header and source files, extracts the public API, analyzes implementation behavior, and generates high‑quality unit tests using Catch2 and fff (Fake Function Framework). + +## Goals +- Identify all public API functions exposed in header files. +- Understand expected behavior by scanning corresponding source files. +- Generate Catch2-based unit tests for each API. +- Using BDD (behavior driven development) method from Catch2 to develop test cases +- Clear documentation (code comment) to explain what the test cases and asserts do. +- Use fff to mock external dependencies. +- Cover input/output validation, happy path, and fail path for each API. + +## Scope +Allowed: +- Read and analyze all header (.h/.hpp) and source (.c/.cpp) files. +- Create new test files or update existing ones. +- Introduce fff (Fake Function Framework) mocks and stubs. +- Add helper test utilities if needed. + +Not allowed: +- Modify production code unless explicitly instructed. +- Change API signatures. +- Introduce new external dependencies beyond Catch2 + fff. + +## Required Inputs +- Path to the module or folder to test. +- Optional: specific API names to focus on. + +## Test File Location Requirements +- All generated test files **must be placed inside**: + + `workspace/tests//` + +- The agent must: + - `` must reflects the folder structure in `inc` folder + - Create the folder if it does not exist. + - Mirror the module structure when appropriate. + - Follow project naming conventions: + - test file: `unittest_.cpp` + - mock file: `mocks_.cpp` + +## Tools +- File search and reading. +- File creation and editing. +- Test runner (e.g., `ctest`, `make test`, or project-specific command). +- Static analysis of function signatures and call graphs. + +## Workflow + +1. **Scan Headers** + - Parse all header files in the target module. + - Extract all public API functions: + - function name + - parameters (types, names) + - return type + - documentation comments (if present) + +2. **Analyze Source Files** + - Locate each API’s implementation. + - Identify: + - control flow + - error conditions + - boundary checks + - dependencies (functions, modules, globals) + - Build a behavioral summary for each API. + +3. **Prepare Test Structure** + - Create a test file per module or per API group. + - Include Catch2 headers. + - Include fff and define mocks for all external dependencies. + +4. **Generate Test Cases** + For each API, generate: + - **Input validation tests** + - null pointers + - invalid ranges + - boundary values + - **Happy path tests** + - typical valid inputs + - expected outputs + - expected side effects + - **Fail path tests** + - forced dependency failures (via fff) + - error return codes + - exceptional conditions + +5. **Mocking Setup** + - Identify all external calls inside the API. + - Create fff (Fake Function Framework) fakes for each dependency. + - Reset fakes before each test. + +6. **Verification** + - Run the test suite. + - If tests fail: + - Fix test logic first. + - Only modify production code if failure indicates a real bug. + +7. **Completion** + - Re-run tests until all pass. + - Output: + - list of created/updated test files + - summary of coverage gaps + - suggestions for additional tests + - short summary of the test cases: what have been tested. + +## Rules +- Use Catch2 `TEST_CASE` and `SECTION` for structure. +- Use fff for all external dependencies. +- Keep tests deterministic and isolated. +- Prefer table-driven tests when multiple input/output pairs exist. +- Do not mock the API under test — only its dependencies. +- Follow project naming conventions: + - test file: `unittest_.cpp` + - mock file: `mocks_.cpp` + +## Output Format +At the end, output: + +- "Summary:" +- List of created/updated test files +- Any warnings or TODOs +- Coverage notes + +## Failure Handling +- If API behavior is unclear, ask the user for clarification. +- If dependencies cannot be mocked, request guidance. +- If the module lacks testable entry points, stop and report. diff --git a/.github/workflows/document_build.yaml b/.github/workflows/document_build.yaml index 4076ba47..bef77457 100644 --- a/.github/workflows/document_build.yaml +++ b/.github/workflows/document_build.yaml @@ -1,6 +1,10 @@ name: Deploy Sphinx documentation to Pages -on: [push, workflow_dispatch] +on: + pull_request: + branches: [ "**" ] + push: + branches: [ "main" ] permissions: contents: write diff --git a/inc/hal/ez_driver_def.h b/inc/hal/ez_driver_def.h index 43454e8c..6d454395 100644 --- a/inc/hal/ez_driver_def.h +++ b/inc/hal/ez_driver_def.h @@ -73,28 +73,31 @@ typedef enum typedef void (*ezDrvCallback)(uint8_t event_code, void *param1, void *param2); +typedef void (*ezDrvOnReceiveEventCallback)( + void *driver_h, + uint8_t event_code, + void *param1, + void *param2); + + /** @brief Define a driver instance. */ -struct ezDrvInstance +typedef struct ezDrvInstance { - ezDrvCallback calback; /**< Callback funtion to handle the event from the HW driver */ + ezDrvCallback callback; /**< Callback funtion to handle the event from the HW driver */ void *driver; /**< Pointer to the HAL driver, depending on the implmentation */ -}; - - -/** @brief Define a driver instance type. - */ -typedef struct ezDrvInstance ezDrvInstance_t; +}ezDrvInstance_t; /** @brief Define structure holding common data of a driver */ -struct ezDriverCommon +typedef struct ezDriverCommon { - const char* name; /* Name of the driver instance */ - uint8_t version[3]; /* Version number including major, minor, patch */ - ezDrvInstance_t *curr_inst; /* Point to the current instance using the driver. NULL means the driver is available. */ -}; + const char* name; /* Name of the driver instance */ + uint8_t version[3]; /* Version number including major, minor, patch */ + ezDrvInstance_t *curr_inst; /* Point to the current instance using the driver. NULL means the driver is available. */ + ezDrvOnReceiveEventCallback callback; /* Callback funtion to handle the event from the HW driver, point to the callback of the instance which is using the driver */ +}ezDriver_t; /***************************************************************************** @@ -140,41 +143,6 @@ static inline void *ezDriver_GetDriverFromInstance(ezDrvInstance_t *inst) } -/***************************************************************************** -* Function: ezDriver_IsDriverAvailable -*//** -* @brief Check if the driver is availabe and ready to be used -* -* @details Helper function used by other components. THe user are not -* supposed to used this function -* -* @param[in] inst: Driver instance -* @param[in] drv_common: Pointer to the common structure of the driver. -* @see ezDriverCommon -* @return true is the driver is available, else false -* -* @pre None -* @post None -* -* \b Example -* @code -* @endcode -* -* @see -* -*****************************************************************************/ -static inline bool ezDriver_IsDriverAvailable(ezDrvInstance_t *inst, - struct ezDriverCommon *drv_common) -{ - bool ret = false; - if(inst != NULL && drv_common != NULL) - { - ret = ((drv_common->curr_inst == NULL) || (drv_common->curr_inst == inst)); - } - return ret; -} - - /***************************************************************************** * Function: ezDriver_LockDriver *//** @@ -194,13 +162,26 @@ static inline bool ezDriver_IsDriverAvailable(ezDrvInstance_t *inst, * @see * *****************************************************************************/ -static inline void ezDriver_LockDriver(ezDrvInstance_t *inst, +static inline bool ezDriver_LockDriver(ezDrvInstance_t *inst, struct ezDriverCommon *drv_common) { - if(inst != NULL && drv_common != NULL) + if(inst == NULL || drv_common == NULL) + { + return false; + } + + if(drv_common->curr_inst == inst) + { + return true; + } + + if(drv_common->curr_inst == NULL) { drv_common->curr_inst = inst; + return true; } + + return false; } diff --git a/inc/hal/gpio/ez_gpio.h b/inc/hal/gpio/ez_gpio.h index 0458855d..ccfd5eaf 100644 --- a/inc/hal/gpio/ez_gpio.h +++ b/inc/hal/gpio/ez_gpio.h @@ -49,6 +49,11 @@ extern "C" { /***************************************************************************** * Component Typedefs *****************************************************************************/ +/** @brief Define Uart Driver Instance + */ +typedef struct ezDrvInstance ezGpioDrvInstance_t; + + /** @brief GPIO mode */ typedef enum { @@ -101,26 +106,26 @@ typedef struct ezHwGpioConfig * @param[in] config: configuration of the GPIO pin * @return EZ_DRV_STATUS */ -typedef EZ_DRV_STATUS (*ezHwGpio_Initialize)(uint16_t pin_index, ezHwGpioConfig_t *config); +typedef EZ_DRV_STATUS (*ezHwGpio_Initialize)(ezDriver_t *handle, uint16_t pin_index, ezHwGpioConfig_t *config); /** @brief Read state of a pin * @param[in] pin_index: index of the GPIO pin * @return EZ_GPIO_PIN_LOW or EZ_GPIO_PIN_HIGH */ -typedef EZ_GPIO_PIN_STATE(*ezHwGpio_ReadPin)(uint16_t pin_index); +typedef EZ_GPIO_PIN_STATE(*ezHwGpio_ReadPin)(ezDriver_t *handle, uint16_t pin_index); /** @brief Write state of a pin * @param[in] pin_index: index of the GPIO pin * @param[in] state: state of the pin * @return EZ_DRV_STATUS */ -typedef EZ_DRV_STATUS(*ezHwGpio_WritePin)(uint16_t pin_index, EZ_GPIO_PIN_STATE state); +typedef EZ_DRV_STATUS(*ezHwGpio_WritePin)(ezDriver_t *handle, uint16_t pin_index, EZ_GPIO_PIN_STATE state); /** @brief Toggle state of a pin * @param[in] pin_index: index of the GPIO pin * @return EZ_DRV_STATUS */ -typedef EZ_DRV_STATUS(*ezHwGpio_TogglePin)(uint16_t pin_index); +typedef EZ_DRV_STATUS(*ezHwGpio_TogglePin)(ezDriver_t *handle, uint16_t pin_index); /** @brief GPIO driver interface @@ -143,13 +148,6 @@ struct ezGpioDriver bool initialized; /* Flag to check if the driver is initialized */ }; -/** @brief Define Uart Driver Instance - */ -typedef struct{ - struct ezDrvInstance drv_instance; /**< Driver instance */ -} ezGpioDrvInstance_t; - - /***************************************************************************** * Component Variable Definitions *****************************************************************************/ diff --git a/inc/hal/i2c/ez_i2c.h b/inc/hal/i2c/ez_i2c.h index 66e7e5eb..670fd510 100644 --- a/inc/hal/i2c/ez_i2c.h +++ b/inc/hal/i2c/ez_i2c.h @@ -85,40 +85,39 @@ typedef struct } ezI2cConfig_t; -typedef EZ_DRV_STATUS (*ezHwI2c_Initialize)(void *driver_h, ezI2cConfig_t *config); -typedef EZ_DRV_STATUS (*ezHwI2c_TransmitSync)(void *driver_h, +typedef EZ_DRV_STATUS (*ezHwI2c_Initialize)(ezDriver_t *driver_h, ezI2cConfig_t *config); +typedef EZ_DRV_STATUS (*ezHwI2c_TransmitSync)(ezDriver_t *driver_h, uint16_t address, const uint8_t *data, size_t length, bool send_stop, uint32_t timeout_millis); -typedef EZ_DRV_STATUS (*ezHwI2c_TransmitAsync)(void *driver_h, +typedef EZ_DRV_STATUS (*ezHwI2c_TransmitAsync)(ezDriver_t *driver_h, uint16_t address, const uint8_t *data, size_t length, bool send_stop); -typedef EZ_DRV_STATUS (*ezHwI2c_ReceiveSync)(void *driver_h, +typedef EZ_DRV_STATUS (*ezHwI2c_ReceiveSync)(ezDriver_t *driver_h, uint16_t address, uint8_t *data, size_t length, bool send_stop, uint32_t timeout_millis); -typedef EZ_DRV_STATUS (*ezHwI2c_ReceiveAsync)(void *driver_h, +typedef EZ_DRV_STATUS (*ezHwI2c_ReceiveAsync)(ezDriver_t *driver_h, uint16_t address, uint8_t *data, size_t length, bool send_stop); -typedef EZ_DRV_STATUS (*ezHwI2c_Probe)(void *driver_h, +typedef EZ_DRV_STATUS (*ezHwI2c_Probe)(ezDriver_t *driver_h, uint16_t address, uint32_t timeout_millis); struct ezHwI2cInterface { - void *driver_h; /**< Pointer to the HW driver handle to identify which hw driver is used */ ezHwI2c_Initialize initialize; /**< Initialize I2C interface */ ezHwI2c_TransmitSync transmit_sync; /**< Transmit data synchronously */ ezHwI2c_TransmitAsync transmit_async; /**< Transmit data asynchronously */ @@ -136,9 +135,7 @@ struct ezI2cDriver }; -typedef struct{ - struct ezDrvInstance drv_instance; /**< Driver instance */ -} ezI2cDrvInstance_t; +typedef struct ezDrvInstance ezI2cDrvInstance_t; /***************************************************************************** * Component Variable Definitions diff --git a/inc/hal/uart/ez_uart.h b/inc/hal/uart/ez_uart.h index 9ec5f38e..ba6628e3 100644 --- a/inc/hal/uart/ez_uart.h +++ b/inc/hal/uart/ez_uart.h @@ -114,7 +114,7 @@ typedef struct ezDrvInstance ezUartDrvInstance_t; * @param[in] index: index of the HW Uart instance * @return STATUS_OK if success, otherwise STATUS_XXX. @see EZ_DRV_STATUS */ -typedef EZ_DRV_STATUS(*ezHwUart_Initialize)(uint8_t index); +typedef EZ_DRV_STATUS(*ezHwUart_Initialize)(ezDriver_t *handle); /** @brief Deinitialize the Hw Uart @@ -122,7 +122,7 @@ typedef EZ_DRV_STATUS(*ezHwUart_Initialize)(uint8_t index); * @param[in] index: index of the HW Uart instance * @return STATUS_OK if success, otherwise STATUS_XXX. @see EZ_DRV_STATUS */ -typedef EZ_DRV_STATUS(*ezHwUart_Deinitialize)(uint8_t index); +typedef EZ_DRV_STATUS(*ezHwUart_Deinitialize)(ezDriver_t *handle); /** @brief Transmit data asynchornously @@ -132,7 +132,7 @@ typedef EZ_DRV_STATUS(*ezHwUart_Deinitialize)(uint8_t index); * @param[in] buff_size: size of the buffer * @return STATUS_OK if success, otherwise STATUS_XXX. @see EZ_DRV_STATUS */ -typedef EZ_DRV_STATUS(*ezHwUart_AsyncTransmit)(uint8_t index, const uint8_t *tx_buff, uint16_t buff_size); +typedef EZ_DRV_STATUS(*ezHwUart_AsyncTransmit)(ezDriver_t *handle, const uint8_t *tx_buff, uint16_t buff_size); /** @brief Receive data asynchornously @@ -142,7 +142,7 @@ typedef EZ_DRV_STATUS(*ezHwUart_AsyncTransmit)(uint8_t index, const uint8_t *tx_ * @param[in] buff_size: size of the buffer * @return STATUS_OK if success, otherwise STATUS_XXX. @see EZ_DRV_STATUS */ -typedef EZ_DRV_STATUS(*ezHwUart_AsyncReceive)(uint8_t index, uint8_t *rx_buff, uint16_t buff_size); +typedef EZ_DRV_STATUS(*ezHwUart_AsyncReceive)(ezDriver_t *handle, uint8_t *rx_buff, uint16_t buff_size); /** @brief Transmit data synchronously @@ -153,7 +153,7 @@ typedef EZ_DRV_STATUS(*ezHwUart_AsyncReceive)(uint8_t index, uint8_t *rx_buff, u * @param[in] timeout_millis: timeout in millisecond * @return STATUS_OK if success, otherwise STATUS_XXX. @see EZ_DRV_STATUS */ -typedef EZ_DRV_STATUS(*ezHwUart_SyncTransmit)(uint8_t index, const uint8_t *tx_buff, uint16_t buff_size, uint32_t timeout_millis); +typedef EZ_DRV_STATUS(*ezHwUart_SyncTransmit)(ezDriver_t *handle, const uint8_t *tx_buff, uint16_t buff_size, uint32_t timeout_millis); /** @brief Receive data synchronously @@ -164,7 +164,7 @@ typedef EZ_DRV_STATUS(*ezHwUart_SyncTransmit)(uint8_t index, const uint8_t *tx_b * @param[in] timeout_millis: timeout in millisecond * @return STATUS_OK if success, otherwise STATUS_XXX. @see EZ_DRV_STATUS */ -typedef EZ_DRV_STATUS(*ezHwUart_SyncReceive)(uint8_t index, uint8_t *rx_buff, uint16_t buff_size, uint32_t timeout_millis); +typedef EZ_DRV_STATUS(*ezHwUart_SyncReceive)(ezDriver_t *handle, uint8_t *rx_buff, uint16_t buff_size, uint32_t timeout_millis); /** @brief Update the configuration @@ -172,14 +172,13 @@ typedef EZ_DRV_STATUS(*ezHwUart_SyncReceive)(uint8_t index, uint8_t *rx_buff, ui * @param[in] index: index of the HW Uart instance * @return STATUS_OK if success, otherwise STATUS_ERR_XXX. @see EZ_DRV_STATUS */ -typedef EZ_DRV_STATUS(*ezHwUart_UpdateConfig)(uint8_t index); +typedef EZ_DRV_STATUS(*ezHwUart_UpdateConfig)(ezDriver_t *handle); /** @brief List of API must be supported by the Hw implementation */ struct ezHwUartInterface { - uint8_t index; /**< Index of the driver instance */ ezHwUart_Initialize initialize; /**< Initialize function */ ezHwUart_Deinitialize deinitialize; /**< Deinitialize function */ ezHwUart_AsyncTransmit async_transmit; /**< Transmit data asynchorously. Events are reported via callback in ezDriverCommon -> ezDrvInstance_t -> calback*/ @@ -324,7 +323,7 @@ EZ_DRV_STATUS ezUart_UnregisterInstance(ezUartDrvInstance_t *inst); * @details Normall, user do not need to call this function. The HW uart * implementation take care of the initialization. * -* @param[in] iinst: Driver instance +* @param[in] inst: Driver instance * @return STATUS_OK: Success * STATUS_XXX: Error code defined in EZ_DRV_STATUS * diff --git a/src/hal/gpio/ez_gpio.c b/src/hal/gpio/ez_gpio.c index 1052e6e0..26ebef06 100644 --- a/src/hal/gpio/ez_gpio.c +++ b/src/hal/gpio/ez_gpio.c @@ -53,7 +53,13 @@ static struct Node hw_driver_list = EZ_LINKEDLIST_INIT_NODE(hw_driver_list); /***************************************************************************** * Function Definitions *****************************************************************************/ -/* None */ +static void ezGpio_OnReceiveEvent( + void *driver_h, + uint8_t event_code, + void *param1, + void *param2 +); + /***************************************************************************** * Public functions @@ -69,6 +75,7 @@ EZ_DRV_STATUS ezGpio_SystemRegisterHwDriver(struct ezGpioDriver *hw_gpio_driver) else { hw_gpio_driver->initialized = false; + hw_gpio_driver->common.callback = ezGpio_OnReceiveEvent; EZ_LINKEDLIST_ADD_TAIL(&hw_driver_list, &hw_gpio_driver->ll_node); EZDEBUG("Register OK"); return STATUS_OK; @@ -111,8 +118,8 @@ EZ_DRV_STATUS ezGpio_RegisterInstance(ezGpioDrvInstance_t *inst, if(strcmp(gpio_drv->common.name, driver_name) == 0) { EZDEBUG("Found driver!"); - inst->drv_instance.driver = (void*)gpio_drv; - inst->drv_instance.calback = callback; + inst->driver = (void*)gpio_drv; + inst->callback = callback; return STATUS_OK; } } @@ -133,16 +140,16 @@ EZ_DRV_STATUS ezGpio_Initialize(ezGpioDrvInstance_t *inst, uint16_t pin_index, e return STATUS_ERR_DRV_NOT_FOUND; } - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == false) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - EZTRACE("Driver = %s is not available", drv->common.name); - return STATUS_ERR_INF_NOT_EXIST; + EZDEBUG("Driver is busy"); + return STATUS_BUSY; } - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); + status = STATUS_ERR_INF_NOT_EXIST; if(drv->interface.init_pin != NULL) { - status = drv->interface.init_pin(pin_index, config); + status = drv->interface.init_pin(&drv->common, pin_index, config); } ezDriver_UnlockDriver(&drv->common); @@ -164,7 +171,7 @@ EZ_DRV_STATUS ezGpio_UnregisterInstance(ezGpioDrvInstance_t *inst) return STATUS_ERR_ARG; } - inst->drv_instance.driver = NULL; + inst->driver = NULL; EZDEBUG("unregister success"); return STATUS_OK; } @@ -180,16 +187,18 @@ EZ_GPIO_PIN_STATE ezGpio_ReadPin(ezGpioDrvInstance_t *inst, uint16_t pin_index) if(drv != NULL) { EZTRACE("Found driver"); - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - EZTRACE("Driver = %s is available", drv->common.name); - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.read_pin) - { - state = drv->interface.read_pin(pin_index); - } - ezDriver_UnlockDriver(&drv->common); + EZTRACE("Driver is busy"); + return EZ_GPIO_PIN_ERROR; } + + EZTRACE("Driver = %s is available", drv->common.name); + if(drv->interface.read_pin) + { + state = drv->interface.read_pin(&drv->common, pin_index); + } + ezDriver_UnlockDriver(&drv->common); } return state; } @@ -205,17 +214,19 @@ EZ_DRV_STATUS ezGpio_WritePin(ezGpioDrvInstance_t *inst, uint16_t pin_index, EZ_ { EZTRACE("Found driver"); status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - EZTRACE("Driver = %s is available", drv->common.name); - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.write_pin) - { - status = drv->interface.write_pin(pin_index, state); - } - ezDriver_UnlockDriver(&drv->common); + EZTRACE("Driver is busy"); + return status; + } + + EZTRACE("Driver = %s is available", drv->common.name); + status = STATUS_ERR_INF_NOT_EXIST; + if(drv->interface.write_pin) + { + status = drv->interface.write_pin(&drv->common, pin_index, state); } + ezDriver_UnlockDriver(&drv->common); } return status; } @@ -232,17 +243,19 @@ EZ_DRV_STATUS ezGpio_TogglePin(ezGpioDrvInstance_t *inst, uint16_t pin_index) { EZTRACE("Found driver"); status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - EZTRACE("Driver = %s is available", drv->common.name); - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.toggle_pin) - { - status = drv->interface.toggle_pin(pin_index); - } - ezDriver_UnlockDriver(&drv->common); + EZTRACE("Driver is busy"); + return status; + } + + EZTRACE("Driver = %s is available", drv->common.name); + status = STATUS_ERR_INF_NOT_EXIST; + if(drv->interface.toggle_pin) + { + status = drv->interface.toggle_pin(&drv->common, pin_index); } + ezDriver_UnlockDriver(&drv->common); } return status; } @@ -251,7 +264,30 @@ EZ_DRV_STATUS ezGpio_TogglePin(ezGpioDrvInstance_t *inst, uint16_t pin_index) /***************************************************************************** * Local functions *****************************************************************************/ - +static void ezGpio_OnReceiveEvent( + void *driver_h, + uint8_t event_code, + void *param1, + void *param2 +) +{ + struct Node* it_node = NULL; + struct ezGpioDriver *gpio_drv = NULL; + + EZ_LINKEDLIST_FOR_EACH(it_node, &hw_driver_list) + { + gpio_drv = EZ_LINKEDLIST_GET_PARENT_OF(it_node, ll_node, struct ezGpioDriver); + if(gpio_drv->common.curr_inst != NULL && gpio_drv->common.curr_inst->driver == driver_h) + { + if(gpio_drv->common.callback) + { + gpio_drv->common.curr_inst->callback(event_code, param1, param2); + } + ezDriver_UnlockDriver(&gpio_drv->common); + break; + } + } +} #endif /* EZ_GPIO == 1 */ /* End of file*/ diff --git a/src/hal/i2c/ez_i2c.c b/src/hal/i2c/ez_i2c.c index 5c5c8464..62d1ffcb 100644 --- a/src/hal/i2c/ez_i2c.c +++ b/src/hal/i2c/ez_i2c.c @@ -52,7 +52,12 @@ static struct Node hw_driver_list = EZ_LINKEDLIST_INIT_NODE(hw_driver_list); /***************************************************************************** * Function Definitions *****************************************************************************/ -/* None */ +static void ezI2c_OnReceiveEvent( + void *driver_h, + uint8_t event_code, + void *param1, + void *param2 +); /***************************************************************************** * Public functions @@ -67,6 +72,7 @@ EZ_DRV_STATUS ezI2c_SystemRegisterHwDriver(struct ezI2cDriver *hw_driver) } hw_driver->initialized = false; + hw_driver->common.callback = ezI2c_OnReceiveEvent; EZ_LINKEDLIST_ADD_TAIL(&hw_driver_list, &hw_driver->ll_node); EZDEBUG("Register OK"); return STATUS_OK; @@ -104,8 +110,8 @@ EZ_DRV_STATUS ezI2c_RegisterInstance(ezI2cDrvInstance_t *inst, if(strcmp(i2c_drv->common.name, driver_name) == 0) { EZDEBUG("Found driver!"); - inst->drv_instance.driver = (void*)i2c_drv; - inst->drv_instance.calback = callback; + inst->driver = (void*)i2c_drv; + inst->callback = callback; return STATUS_OK; } } @@ -120,7 +126,7 @@ EZ_DRV_STATUS ezI2c_UnregisterInstance(ezI2cDrvInstance_t *inst) { return STATUS_ERR_ARG; } - inst->drv_instance.driver = NULL; + inst->driver = NULL; EZDEBUG("unregister success"); return STATUS_OK; } @@ -137,16 +143,15 @@ EZ_DRV_STATUS ezI2c_Initialize(ezI2cDrvInstance_t *inst, ezI2cConfig_t *config) return STATUS_ERR_DRV_NOT_FOUND; } - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == false) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - EZTRACE("Driver = %s is not available", drv->common.name); - return STATUS_ERR_INF_NOT_EXIST; + EZERROR("Driver is busy"); + return STATUS_BUSY; } - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); if(drv->interface.initialize != NULL) { - status = drv->interface.initialize(drv->interface.driver_h, config); + status = drv->interface.initialize(&drv->common, config); } ezDriver_UnlockDriver(&drv->common); @@ -172,22 +177,22 @@ EZ_DRV_STATUS ezI2c_TransmitSync(ezI2cDrvInstance_t *inst, if(drv != NULL) { - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.transmit_sync) - { - status = drv->interface.transmit_sync(drv->interface.driver_h, - address, - data, - length, - send_stop, - timeout_millis); - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; + } + + if(drv->interface.transmit_sync) + { + status = drv->interface.transmit_sync(&drv->common, + address, + data, + length, + send_stop, + timeout_millis); } + ezDriver_UnlockDriver(&drv->common); } return status; } @@ -204,21 +209,21 @@ EZ_DRV_STATUS ezI2c_TransmitAsync(ezI2cDrvInstance_t *inst, if(drv != NULL) { - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.transmit_async) - { - status = drv->interface.transmit_async(drv->interface.driver_h, - address, - data, - length, - send_stop); - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; + } + + if(drv->interface.transmit_async) + { + status = drv->interface.transmit_async(&drv->common, + address, + data, + length, + send_stop); } + //Unlock will be done in the callbak when the async operation is done } return status; } @@ -236,22 +241,22 @@ EZ_DRV_STATUS ezI2c_ReceiveSync(ezI2cDrvInstance_t *inst, if(drv != NULL) { - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.receive_sync) - { - status = drv->interface.receive_sync(drv->interface.driver_h, - address, - data, - length, - send_stop, - timeout_millis); - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; + } + + if(drv->interface.receive_sync) + { + status = drv->interface.receive_sync(&drv->common, + address, + data, + length, + send_stop, + timeout_millis); } + ezDriver_UnlockDriver(&drv->common); } return status; } @@ -268,21 +273,21 @@ EZ_DRV_STATUS ezI2c_ReceiveAsync(ezI2cDrvInstance_t *inst, if(drv != NULL) { - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.receive_async) - { - status = drv->interface.receive_async(drv->interface.driver_h, - address, - data, - length, - send_stop); - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; + } + + if(drv->interface.receive_async) + { + status = drv->interface.receive_async(&drv->common, + address, + data, + length, + send_stop); } + //Unlock will be done in the callbachk when the async operation is done } return status; } @@ -298,24 +303,50 @@ EZ_DRV_STATUS ezI2c_Probe(ezI2cDrvInstance_t *inst, if(drv != NULL) { - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.probe) - { - status = drv->interface.probe(drv->interface.driver_h, - address, - timeout_millis); - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; + } + + if(drv->interface.probe) + { + status = drv->interface.probe(&drv->common, + address, + timeout_millis); } + ezDriver_UnlockDriver(&drv->common); } return status; } /***************************************************************************** * Local functions *****************************************************************************/ +static void ezI2c_OnReceiveEvent( + void *driver_h, + uint8_t event_code, + void *param1, + void *param2) +{ + struct Node* it_node = NULL; + struct ezI2cDriver *i2c_drv = NULL; + + EZ_LINKEDLIST_FOR_EACH(it_node, &hw_driver_list) + { + i2c_drv = EZ_LINKEDLIST_GET_PARENT_OF(it_node, ll_node, struct ezI2cDriver); + if(i2c_drv->common.curr_inst != NULL && i2c_drv->common.curr_inst->driver == driver_h) + { + if(i2c_drv->common.callback) + { + i2c_drv->common.curr_inst->callback(event_code, param1, param2); + } + ezDriver_UnlockDriver(&i2c_drv->common); + break; + } + } +} + + #endif /* EZ_I2C == 1 */ /* End of file*/ diff --git a/src/hal/spi/ez_spi.c b/src/hal/spi/ez_spi.c index 7998f687..fa80371a 100644 --- a/src/hal/spi/ez_spi.c +++ b/src/hal/spi/ez_spi.c @@ -107,7 +107,7 @@ EZ_DRV_STATUS ezSpi_RegisterInstance(ezSpiDrvInstance_t *inst, { EZDEBUG("Found driver!"); inst->drv_instance.driver = (void*)spi_drv; - inst->drv_instance.calback = callback; + inst->drv_instance.callback = callback; return STATUS_OK; } } @@ -139,13 +139,12 @@ EZ_DRV_STATUS ezSpi_Initialize(ezSpiDrvInstance_t *inst, ezSpiConfig_t *config) return STATUS_ERR_DRV_NOT_FOUND; } - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == false) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - EZTRACE("Driver = %s is not available", drv->common.name); - return STATUS_ERR_INF_NOT_EXIST; + EZERROR("Driver is busy"); + return STATUS_BUSY; } - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); if(drv->interface.initialize != NULL) { status = drv->interface.initialize(drv->interface.driver_h, config); @@ -174,22 +173,22 @@ EZ_DRV_STATUS ezSpi_TransferSync(ezSpiDrvInstance_t *inst, if(drv != NULL) { - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.transfer_sync) - { - status = drv->interface.transfer_sync(drv->interface.driver_h, - tx_data, - tx_length, - rx_data, - rx_length, - timeout_millis); - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; } + + if(drv->interface.transfer_sync) + { + status = drv->interface.transfer_sync(drv->interface.driver_h, + tx_data, + tx_length, + rx_data, + rx_length, + timeout_millis); + } + ezDriver_UnlockDriver(&drv->common); } return status; } @@ -206,21 +205,21 @@ EZ_DRV_STATUS ezSpi_TransferAsync(ezSpiDrvInstance_t *inst, if(drv != NULL) { - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) + { + EZERROR("Driver is busy"); + return STATUS_BUSY; + } + + if(drv->interface.transfer_async) { - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.transfer_async) - { - status = drv->interface.transfer_async(drv->interface.driver_h, - tx_data, - tx_length, - rx_data, - rx_length); - } - ezDriver_UnlockDriver(&drv->common); + status = drv->interface.transfer_async(drv->interface.driver_h, + tx_data, + tx_length, + rx_data, + rx_length); } + ezDriver_UnlockDriver(&drv->common); } return status; } @@ -236,20 +235,20 @@ EZ_DRV_STATUS ezSpi_TransmitSync(ezSpiDrvInstance_t *inst, if(drv != NULL) { - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.transmit_sync) - { - status = drv->interface.transmit_sync(drv->interface.driver_h, - tx_data, - length, - timeout_millis); - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; } + + if(drv->interface.transmit_sync) + { + status = drv->interface.transmit_sync(drv->interface.driver_h, + tx_data, + length, + timeout_millis); + } + ezDriver_UnlockDriver(&drv->common); } return status; } @@ -264,19 +263,19 @@ EZ_DRV_STATUS ezSpi_TransmitAsync(ezSpiDrvInstance_t *inst, if(drv != NULL) { - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) + { + EZERROR("Driver is busy"); + return STATUS_BUSY; + } + + if(drv->interface.transmit_async) { - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.transmit_async) - { - status = drv->interface.transmit_async(drv->interface.driver_h, - tx_data, - length); - } - ezDriver_UnlockDriver(&drv->common); + status = drv->interface.transmit_async(drv->interface.driver_h, + tx_data, + length); } + ezDriver_UnlockDriver(&drv->common); } return status; } @@ -292,20 +291,20 @@ EZ_DRV_STATUS ezSpi_ReceiveSync(ezSpiDrvInstance_t *inst, if(drv != NULL) { - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.receive_sync) - { - status = drv->interface.receive_sync(drv->interface.driver_h, - rx_data, - length, - timeout_millis); - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; } + + if(drv->interface.receive_sync) + { + status = drv->interface.receive_sync(drv->interface.driver_h, + rx_data, + length, + timeout_millis); + } + ezDriver_UnlockDriver(&drv->common); } return status; } @@ -320,19 +319,20 @@ EZ_DRV_STATUS ezSpi_ReceiveAsync(ezSpiDrvInstance_t *inst, if(drv != NULL) { - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) { - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.receive_async) - { - status = drv->interface.receive_async(drv->interface.driver_h, - rx_data, - length); - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; } + + if(drv->interface.receive_async) + { + status = drv->interface.receive_async(drv->interface.driver_h, + rx_data, + length); + } + ezDriver_UnlockDriver(&drv->common); } return status; } @@ -345,17 +345,17 @@ EZ_DRV_STATUS ezSpi_ChipSelect(ezSpiDrvInstance_t *inst, bool select) if(drv != NULL) { - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable((struct ezDrvInstance*)inst, &drv->common) == true) + if(ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common) == false) + { + EZERROR("Driver is busy"); + return STATUS_BUSY; + } + + if(drv->interface.chip_select) { - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver((struct ezDrvInstance*)inst, &drv->common); - if(drv->interface.chip_select) - { - status = drv->interface.chip_select(drv->interface.driver_h, select); - } - ezDriver_UnlockDriver(&drv->common); + status = drv->interface.chip_select(drv->interface.driver_h, select); } + ezDriver_UnlockDriver(&drv->common); } return status; } diff --git a/src/hal/uart/ez_uart.c b/src/hal/uart/ez_uart.c index 69b1aa75..77651261 100644 --- a/src/hal/uart/ez_uart.c +++ b/src/hal/uart/ez_uart.c @@ -59,11 +59,16 @@ static struct Node instance_list = EZ_LINKEDLIST_INIT_NODE(instance_list); * Function Definitions *****************************************************************************/ static void ezUart_PrintStatus(EZ_DRV_STATUS status); - +static void ezUart_OnReceiveEvent( + void *driver_h, + uint8_t event_code, + void *param1, + void *param2 +); /***************************************************************************** -* Public functions -*****************************************************************************/ + * Public functions + *****************************************************************************/ EZ_DRV_STATUS ezUart_SystemRegisterHwDriver(struct ezUartDriver *hw_uart_driver) { EZ_DRV_STATUS status = STATUS_ERR_GENERIC; @@ -77,6 +82,7 @@ EZ_DRV_STATUS ezUart_SystemRegisterHwDriver(struct ezUartDriver *hw_uart_driver) else { EZ_LINKEDLIST_ADD_TAIL(&hw_driver_list, &hw_uart_driver->ll_node); + hw_uart_driver->common.callback = ezUart_OnReceiveEvent; status = STATUS_OK; } @@ -125,7 +131,7 @@ EZ_DRV_STATUS ezUart_RegisterInstance(ezUartDrvInstance_t *inst, if(strcmp(uart_drv->common.name, driver_name) == 0) { inst->driver = (void*)uart_drv; - inst->calback = callback; + inst->callback = callback; status = STATUS_OK; EZDEBUG("Found driver!"); break; @@ -166,19 +172,18 @@ EZ_DRV_STATUS ezUart_Initialize(ezUartDrvInstance_t *inst) drv = (struct ezUartDriver*)ezDriver_GetDriverFromInstance(inst); if(drv != NULL) { - EZTRACE("Found driver"); - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable(inst, &drv->common) == true) + if(ezDriver_LockDriver(inst, &drv->common) == false) { - EZTRACE("Driver = %s is available", drv->common.name); - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver(inst, &drv->common); - if(drv->interface.initialize) - { - status = drv->interface.initialize(drv->interface.index); - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; + } + + status = STATUS_ERR_INF_NOT_EXIST; + if(drv->interface.initialize) + { + status = drv->interface.initialize(&drv->common); } + ezDriver_UnlockDriver(&drv->common); } ezUart_PrintStatus(status); return status; @@ -194,19 +199,18 @@ EZ_DRV_STATUS ezUart_Deinitialize(ezUartDrvInstance_t *inst) drv = (struct ezUartDriver*)ezDriver_GetDriverFromInstance(inst); if(drv != NULL) { - EZTRACE("Found driver"); - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable(inst, &drv->common) == true) + if(ezDriver_LockDriver(inst, &drv->common) == false) { - EZTRACE("Driver = %s is available", drv->common.name); - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver(inst, &drv->common); - if(drv->interface.deinitialize) - { - status = drv->interface.deinitialize(drv->interface.index); - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; } + + status = STATUS_ERR_INF_NOT_EXIST; + if(drv->interface.deinitialize) + { + status = drv->interface.deinitialize(&drv->common); + } + ezDriver_UnlockDriver(&drv->common); } ezUart_PrintStatus(status); return status; @@ -222,21 +226,21 @@ EZ_DRV_STATUS ezUart_AsyncTransmit(ezUartDrvInstance_t *inst, const uint8_t *tx_ drv = (struct ezUartDriver*)ezDriver_GetDriverFromInstance(inst); if(drv != NULL) { - EZTRACE("Found driver"); - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable(inst, &drv->common) == true) + if(ezDriver_LockDriver(inst, &drv->common) == false) { - EZTRACE("Driver = %s is available", drv->common.name); - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver(inst, &drv->common); - if(drv->interface.async_transmit) - { - status = drv->interface.async_transmit(drv->interface.index, - tx_buff, - buff_size); - } - /* Driver is unlocked by the HW implementation in the callback function */ + EZERROR("Driver is busy"); + return STATUS_BUSY; } + + status = STATUS_ERR_INF_NOT_EXIST; + if(drv->interface.async_transmit) + { + status = drv->interface.async_transmit( + &drv->common, + tx_buff, + buff_size); + } + /* Driver is unlocked by the HW implementation in the callback function */ } ezUart_PrintStatus(status); return status; @@ -252,21 +256,20 @@ EZ_DRV_STATUS ezUart_AsyncReceive(ezUartDrvInstance_t *inst, uint8_t *rx_buff, u drv = (struct ezUartDriver*)ezDriver_GetDriverFromInstance(inst); if(drv != NULL) { - EZTRACE("Found driver"); - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable(inst, &drv->common) == true) + if(ezDriver_LockDriver(inst, &drv->common) == false) { - EZTRACE("Driver = %s is available", drv->common.name); - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver(inst, &drv->common); - if(drv->interface.async_receive) - { - status = drv->interface.async_receive(drv->interface.index, - rx_buff, - buff_size); - } - /* Driver is unlocked by the HW implementation in the callback function */ + EZERROR("Driver is busy"); + return STATUS_BUSY; + } + + status = STATUS_ERR_INF_NOT_EXIST; + if(drv->interface.async_receive) + { + status = drv->interface.async_receive(&drv->common, + rx_buff, + buff_size); } + /* Driver is unlocked by the HW implementation in the callback function */ } ezUart_PrintStatus(status); return status; @@ -283,22 +286,21 @@ EZ_DRV_STATUS ezUart_SyncTransmit(ezUartDrvInstance_t *inst, const uint8_t *tx_b drv = (struct ezUartDriver*)ezDriver_GetDriverFromInstance(inst); if(drv != NULL) { - EZTRACE("Found driver"); - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable(inst, &drv->common) == true) + if(ezDriver_LockDriver(inst, &drv->common) == false) { - EZTRACE("Driver = %s is available", drv->common.name); - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver(inst, &drv->common); - if(drv->interface.sync_transmit) - { - status = drv->interface.sync_transmit(drv->interface.index, - tx_buff, - buff_size, - timeout_millis); - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; } + + status = STATUS_ERR_INF_NOT_EXIST; + if(drv->interface.sync_transmit) + { + status = drv->interface.sync_transmit(&drv->common, + tx_buff, + buff_size, + timeout_millis); + } + ezDriver_UnlockDriver(&drv->common); } ezUart_PrintStatus(status); return status; @@ -315,22 +317,21 @@ EZ_DRV_STATUS ezUart_SyncReceive(ezUartDrvInstance_t *inst, uint8_t *rx_buff, ui drv = (struct ezUartDriver*)ezDriver_GetDriverFromInstance(inst); if(drv != NULL) { - EZTRACE("Found driver"); - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable(inst, &drv->common) == true) + if(ezDriver_LockDriver(inst, &drv->common) == false) { - EZTRACE("Driver = %s is available", drv->common.name); - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver(inst, &drv->common); - if(drv->interface.sync_receive) - { - status = drv->interface.sync_receive(drv->interface.index, - rx_buff, - buff_size, - timeout_millis); - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; } + + status = STATUS_ERR_INF_NOT_EXIST; + if(drv->interface.sync_receive) + { + status = drv->interface.sync_receive(&drv->common, + rx_buff, + buff_size, + timeout_millis); + } + ezDriver_UnlockDriver(&drv->common); } ezUart_PrintStatus(status); return status; @@ -346,20 +347,19 @@ EZ_DRV_STATUS ezUart_GetConfig(ezUartDrvInstance_t *inst, struct ezUartConfigura drv = (struct ezUartDriver*)ezDriver_GetDriverFromInstance(inst); if(drv != NULL) { - EZTRACE("Found driver"); - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable(inst, &drv->common) == true) + if(ezDriver_LockDriver(inst, &drv->common) == false) { - EZTRACE("Driver = %s is available", drv->common.name); - status = STATUS_ERR_ARG; - ezDriver_LockDriver(inst, &drv->common); - if(config != NULL) - { - *config = &drv->config; - status = STATUS_OK; - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; + } + + status = STATUS_ERR_ARG; + if(config != NULL) + { + *config = &drv->config; + status = STATUS_OK; } + ezDriver_UnlockDriver(&drv->common); } ezUart_PrintStatus(status); return status; @@ -376,19 +376,17 @@ EZ_DRV_STATUS ezUart_UpdateConfig(ezUartDrvInstance_t *inst) drv = (struct ezUartDriver*)ezDriver_GetDriverFromInstance(inst); if(drv != NULL) { - EZTRACE("Found driver"); - status = STATUS_BUSY; - if(ezDriver_IsDriverAvailable(inst, &drv->common) == true) + if(ezDriver_LockDriver(inst, &drv->common) == false) { - EZTRACE("Driver = %s is available", drv->common.name); - status = STATUS_ERR_INF_NOT_EXIST; - ezDriver_LockDriver(inst, &drv->common); - if(drv->interface.update_conf) - { - status = drv->interface.update_conf(drv->interface.index); - } - ezDriver_UnlockDriver(&drv->common); + EZERROR("Driver is busy"); + return STATUS_BUSY; } + + if(drv->interface.update_conf) + { + status = drv->interface.update_conf(&drv->common); + } + ezDriver_UnlockDriver(&drv->common); } ezUart_PrintStatus(status); return status; @@ -398,7 +396,30 @@ EZ_DRV_STATUS ezUart_UpdateConfig(ezUartDrvInstance_t *inst) /***************************************************************************** * Local functions *****************************************************************************/ - +static void ezUart_OnReceiveEvent( + void *driver_h, + uint8_t event_code, + void *param1, + void *param2 +) +{ + struct Node* it_node = NULL; + struct ezUartDriver *uart_drv = NULL; + + EZ_LINKEDLIST_FOR_EACH(it_node, &hw_driver_list) + { + uart_drv = EZ_LINKEDLIST_GET_PARENT_OF(it_node, ll_node, struct ezUartDriver); + if(uart_drv->common.curr_inst != NULL && uart_drv->common.curr_inst->driver == driver_h) + { + if(uart_drv->common.callback) + { + uart_drv->common.curr_inst->callback(event_code, param1, param2); + } + ezDriver_UnlockDriver(&uart_drv->common); + break; + } + } +} /***************************************************************************** * Function: ezUart_PrintStatus diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e7c60ad2..6fe048b9 100755 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -34,14 +34,6 @@ if(ENABLE_EZ_KERNEL) add_subdirectory(service/kernel) endif() -if(ENABLE_EZ_HAL_ECHO) - add_subdirectory(service/driver/hal_echo) -endif() - -if(ENABLE_EZ_UART) - add_subdirectory(service/driver/uart) -endif() - if(ENABLE_EZ_QUEUE) add_subdirectory(utilities/queue) endif() @@ -58,10 +50,18 @@ if(ENABLE_EZ_RING_BUFFER) add_subdirectory(utilities/ring_buffer) endif() +if(ENABLE_EZ_UART) + add_subdirectory(hal/uart) +endif() + if(ENABLE_EZ_GPIO) add_subdirectory(hal/gpio) endif() +if(ENABLE_EZ_I2C) + add_subdirectory(hal/i2c) +endif() + if(ENABLE_EZ_RPC) add_subdirectory(service/rpc) endif() diff --git a/tests/hal/gpio/unittest_ez_gpio.cpp b/tests/hal/gpio/unittest_ez_gpio.cpp index 8de79e9a..675e6c44 100644 --- a/tests/hal/gpio/unittest_ez_gpio.cpp +++ b/tests/hal/gpio/unittest_ez_gpio.cpp @@ -1,7 +1,7 @@ /***************************************************************************** -* Filename: unittest_ez_osal.c +* Filename: unittest_ez_gpio.cpp * Author: Hai Nguyen -* Original Date: 15.03.2025 +* Original Date: 25.04.2026 * * ---------------------------------------------------------------------------- * Contact: Hai Nguyen @@ -12,23 +12,25 @@ * *****************************************************************************/ -/** @file unittest_ez_osal.c +/** @file unittest_ez_gpio.cpp * @author Hai Nguyen - * @date 15.03.2025 - * @brief One line description of the component + * @date 25.04.2026 + * @brief Unit tests for the GPIO HAL component * - * @details Detail description of the component - * + * @details - */ /****************************************************************************** * Includes *******************************************************************************/ -#include #include +#include +#include + +#include "ez_driver_def.h" #include "ez_gpio.h" -#include "ez_event_bus.h" #include "fff.h" + #include @@ -36,101 +38,524 @@ * Module Preprocessor Macros *******************************************************************************/ DEFINE_FFF_GLOBALS; -FAKE_VALUE_FUNC(EZ_DRV_STATUS, Init, uint16_t, ezHwGpioConfig_t*); -FAKE_VALUE_FUNC(EZ_GPIO_PIN_STATE, ReadPin, uint16_t); -FAKE_VALUE_FUNC(EZ_DRV_STATUS, WritePin, uint16_t, EZ_GPIO_PIN_STATE); -FAKE_VOID_FUNC(Callback, uint8_t, void *, void*); +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwInitPin, ezDriver_t *, uint16_t, ezHwGpioConfig_t *); +FAKE_VALUE_FUNC(EZ_GPIO_PIN_STATE, HwReadPin, ezDriver_t *, uint16_t); +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwWritePin, ezDriver_t *, uint16_t, EZ_GPIO_PIN_STATE); +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwTogglePin, ezDriver_t *, uint16_t); +FAKE_VOID_FUNC(InstanceCallback, uint8_t, void *, void *); + /****************************************************************************** * Module Typedefs *******************************************************************************/ -static ezGpioDriver gpio_driver; - -class GpioTestFixture { -private: -protected: -public: - GpioTestFixture(); - ~GpioTestFixture(){} -protected: -}; +typedef struct +{ + uint8_t event_code; + void *param1; + void *param2; +} ezGpioEvent_t; /****************************************************************************** * Module Variable Definitions *******************************************************************************/ +static struct ezGpioDriver g_mock_driver; +static ezGpioEvent_t g_event; /****************************************************************************** * Function Definitions *******************************************************************************/ +static void ResetEvent(void); + +class GpioTestFixture +{ +public: + GpioTestFixture(); + ~GpioTestFixture(); + +protected: + void RegisterDriver(void); + void RegisterFirstInstance(void); + void RegisterSecondInstance(void); + void RegisterBothInstances(void); + + ezGpioDrvInstance_t first_inst{}; + ezGpioDrvInstance_t second_inst{}; + ezHwGpioConfig_t config{}; + bool driver_registered; + bool first_registered; + bool second_registered; +}; /****************************************************************************** * External functions *******************************************************************************/ -TEST_CASE_METHOD(GpioTestFixture, "Test write pin", "[hal][gpio]") +TEST_CASE_METHOD(GpioTestFixture, "Test driver registration", "[hal][gpio]") +{ + WHEN("A NULL hardware driver is provided") + { + /* Verify registration entry points reject invalid arguments. */ + THEN("The APIs report an argument error") + { + CHECK(ezGpio_SystemRegisterHwDriver(NULL) == STATUS_ERR_ARG); + CHECK(ezGpio_SystemUnregisterHwDriver(NULL) == STATUS_ERR_ARG); + } + } + + WHEN("A valid GPIO driver is registered") + { + RegisterDriver(); + + THEN("The driver is reset and the receive callback is installed") + { + CHECK(g_mock_driver.initialized == false); + CHECK(g_mock_driver.common.callback != NULL); + } + + AND_WHEN("The same driver is unregistered") + { + g_mock_driver.initialized = true; + + THEN("The driver is removed cleanly") + { + CHECK(ezGpio_SystemUnregisterHwDriver(&g_mock_driver) == STATUS_OK); + driver_registered = false; + CHECK(g_mock_driver.initialized == false); + } + } + } +} + + +TEST_CASE_METHOD(GpioTestFixture, "Test instance registration lifecycle", "[hal][gpio]") { - ezGpioDrvInstance_t instance; - REQUIRE(ezGpio_SystemRegisterHwDriver(&gpio_driver) == STATUS_OK); - REQUIRE(ezGpio_RegisterInstance(&instance, "Mock GPIO Driver", Callback) == STATUS_OK); + WHEN("Invalid instance arguments are used") + { + /* Confirm register and unregister perform basic argument validation. */ + THEN("The APIs report argument errors") + { + CHECK(ezGpio_RegisterInstance(NULL, NULL, NULL) == STATUS_ERR_ARG); + CHECK(ezGpio_UnregisterInstance(NULL) == STATUS_ERR_ARG); + } + } - EZ_DRV_STATUS status = ezGpio_WritePin(&instance, 0x01, EZ_GPIO_PIN_HIGH); - CHECK(status == STATUS_OK); - CHECK(WritePin_fake.call_count == 1); - CHECK(WritePin_fake.arg0_val == 0x01); - CHECK(WritePin_fake.arg1_val == EZ_GPIO_PIN_HIGH); + WHEN("The target driver name is unknown") + { + RegisterDriver(); + + THEN("The instance registration fails with driver-not-found") + { + CHECK(ezGpio_RegisterInstance(&first_inst, "Unknown driver", InstanceCallback) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + WHEN("A valid instance is registered") + { + RegisterDriver(); + + THEN("The instance stores the selected driver and callback") + { + CHECK(ezGpio_RegisterInstance(&first_inst, g_mock_driver.common.name, InstanceCallback) == STATUS_OK); + first_registered = true; + CHECK(first_inst.driver == &g_mock_driver); + CHECK(first_inst.callback == InstanceCallback); + } + + AND_WHEN("The instance is unregistered") + { + REQUIRE(ezGpio_RegisterInstance(&first_inst, g_mock_driver.common.name, InstanceCallback) == STATUS_OK); + first_registered = true; + + THEN("The driver reference is cleared") + { + CHECK(ezGpio_UnregisterInstance(&first_inst) == STATUS_OK); + first_registered = false; + CHECK(first_inst.driver == NULL); + } + } + } +} + + +TEST_CASE_METHOD(GpioTestFixture, "Test initialization", "[hal][gpio]") +{ + const uint16_t pin_index = 0x01U; + + WHEN("The instance is NULL or not registered") + { + /* The API cannot resolve a backing driver in this state. */ + THEN("The API returns driver-not-found") + { + CHECK(ezGpio_Initialize(NULL, pin_index, &config) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezGpio_Initialize(&first_inst, pin_index, &config) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No GPIO init interface is implemented") + { + THEN("The API reports a missing interface and unlocks the driver") + { + CHECK(ezGpio_Initialize(&first_inst, pin_index, &config) == STATUS_ERR_INF_NOT_EXIST); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("Another instance already owns the driver") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports busy") + { + CHECK(ezGpio_Initialize(&second_inst, pin_index, &config) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware init fake reports a timeout") + { + g_mock_driver.interface.init_pin = HwInitPin; + HwInitPin_fake.return_val = STATUS_TIMEOUT; + + THEN("The failure is propagated") + { + CHECK(ezGpio_Initialize(&first_inst, pin_index, &config) == STATUS_TIMEOUT); + CHECK(HwInitPin_fake.call_count == 1); + CHECK(HwInitPin_fake.arg0_val == &g_mock_driver.common); + CHECK(HwInitPin_fake.arg1_val == pin_index); + CHECK(HwInitPin_fake.arg2_val == &config); + CHECK(g_mock_driver.common.curr_inst == NULL); + CHECK(g_mock_driver.initialized == false); + } + } + + WHEN("The hardware init fake succeeds") + { + g_mock_driver.interface.init_pin = HwInitPin; + HwInitPin_fake.return_val = STATUS_OK; + + THEN("The driver is marked initialized and arguments are forwarded") + { + CHECK(ezGpio_Initialize(&first_inst, pin_index, &config) == STATUS_OK); + CHECK(HwInitPin_fake.call_count == 1); + CHECK(HwInitPin_fake.arg0_val == &g_mock_driver.common); + CHECK(HwInitPin_fake.arg1_val == pin_index); + CHECK(HwInitPin_fake.arg2_val == &config); + CHECK(g_mock_driver.initialized == true); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } } TEST_CASE_METHOD(GpioTestFixture, "Test read pin", "[hal][gpio]") { - ezGpioDrvInstance_t instance; - REQUIRE(ezGpio_SystemRegisterHwDriver(&gpio_driver) == STATUS_OK); - REQUIRE(ezGpio_RegisterInstance(&instance, "Mock GPIO Driver", Callback) == STATUS_OK); + const uint16_t pin_index = 0x02U; + + WHEN("The instance is NULL or not registered") + { + THEN("The API reports a pin error") + { + CHECK(ezGpio_ReadPin(NULL, pin_index) == EZ_GPIO_PIN_ERROR); + CHECK(ezGpio_ReadPin(&first_inst, pin_index) == EZ_GPIO_PIN_ERROR); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No read interface is implemented") + { + THEN("The API reports a pin error and unlocks the driver") + { + CHECK(ezGpio_ReadPin(&first_inst, pin_index) == EZ_GPIO_PIN_ERROR); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("Another instance already owns the driver") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports a pin error") + { + CHECK(ezGpio_ReadPin(&second_inst, pin_index) == EZ_GPIO_PIN_ERROR); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware read fake returns HIGH") + { + g_mock_driver.interface.read_pin = HwReadPin; + HwReadPin_fake.return_val = EZ_GPIO_PIN_HIGH; + + THEN("The pin state is forwarded to the caller") + { + CHECK(ezGpio_ReadPin(&first_inst, pin_index) == EZ_GPIO_PIN_HIGH); + CHECK(HwReadPin_fake.call_count == 1); + CHECK(HwReadPin_fake.arg0_val == &g_mock_driver.common); + CHECK(HwReadPin_fake.arg1_val == pin_index); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +TEST_CASE_METHOD(GpioTestFixture, "Test write pin", "[hal][gpio]") +{ + const uint16_t pin_index = 0x03U; + + WHEN("The instance is NULL or not registered") + { + THEN("The API returns driver-not-found") + { + CHECK(ezGpio_WritePin(NULL, pin_index, EZ_GPIO_PIN_HIGH) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezGpio_WritePin(&first_inst, pin_index, EZ_GPIO_PIN_HIGH) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No write interface is implemented") + { + THEN("The API reports a missing interface") + { + CHECK(ezGpio_WritePin(&first_inst, pin_index, EZ_GPIO_PIN_HIGH) == STATUS_ERR_INF_NOT_EXIST); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("Another instance already owns the driver") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports busy") + { + CHECK(ezGpio_WritePin(&second_inst, pin_index, EZ_GPIO_PIN_HIGH) == STATUS_BUSY); + } + g_mock_driver.common.curr_inst = NULL; + } - ReadPin_fake.return_val = EZ_GPIO_PIN_HIGH; - EZ_GPIO_PIN_STATE state = ezGpio_ReadPin(&instance, 0x01); - CHECK(state == EZ_GPIO_PIN_HIGH); - CHECK(ReadPin_fake.call_count == 1); - CHECK(ReadPin_fake.arg0_val == 0x01); + WHEN("The hardware write fake reports a timeout") + { + g_mock_driver.interface.write_pin = HwWritePin; + HwWritePin_fake.return_val = STATUS_TIMEOUT; + THEN("The failure is propagated") + { + CHECK(ezGpio_WritePin(&first_inst, pin_index, EZ_GPIO_PIN_HIGH) == STATUS_TIMEOUT); + CHECK(HwWritePin_fake.call_count == 1); + CHECK(HwWritePin_fake.arg0_val == &g_mock_driver.common); + CHECK(HwWritePin_fake.arg1_val == pin_index); + CHECK(HwWritePin_fake.arg2_val == EZ_GPIO_PIN_HIGH); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("The hardware write fake succeeds") + { + g_mock_driver.interface.write_pin = HwWritePin; + HwWritePin_fake.return_val = STATUS_OK; + + THEN("The state and pin index are forwarded to the hardware layer") + { + CHECK(ezGpio_WritePin(&first_inst, pin_index, EZ_GPIO_PIN_HIGH) == STATUS_OK); + CHECK(HwWritePin_fake.call_count == 1); + CHECK(HwWritePin_fake.arg0_val == &g_mock_driver.common); + CHECK(HwWritePin_fake.arg1_val == pin_index); + CHECK(HwWritePin_fake.arg2_val == EZ_GPIO_PIN_HIGH); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } } -TEST_CASE_METHOD(GpioTestFixture, "Test callback triggered", "[hal][gpio]") + +TEST_CASE_METHOD(GpioTestFixture, "Test toggle pin", "[hal][gpio]") { - ezGpioDrvInstance_t instance; - REQUIRE(ezGpio_SystemRegisterHwDriver(&gpio_driver) == STATUS_OK); - REQUIRE(ezGpio_RegisterInstance(&instance, "Mock GPIO Driver", Callback) == STATUS_OK); + const uint16_t pin_index = 0x04U; + + WHEN("The instance is NULL or not registered") + { + THEN("The API returns driver-not-found") + { + CHECK(ezGpio_TogglePin(NULL, pin_index) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezGpio_TogglePin(&first_inst, pin_index) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No toggle interface is implemented") + { + THEN("The API reports a missing interface") + { + CHECK(ezGpio_TogglePin(&first_inst, pin_index) == STATUS_ERR_INF_NOT_EXIST); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("Another instance already owns the driver") + { + g_mock_driver.common.curr_inst = &first_inst; - instance.drv_instance.calback(0x10, (void*)0x1234, (void*)0x5678); - CHECK(Callback_fake.call_count == 1); - CHECK(Callback_fake.arg0_val == 0x10); - CHECK(Callback_fake.arg1_val == (void*)0x1234); - CHECK(Callback_fake.arg2_val == (void*)0x5678); + THEN("The API reports busy") + { + CHECK(ezGpio_TogglePin(&second_inst, pin_index) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware toggle fake reports a timeout") + { + g_mock_driver.interface.toggle_pin = HwTogglePin; + HwTogglePin_fake.return_val = STATUS_TIMEOUT; + + THEN("The failure is propagated") + { + CHECK(ezGpio_TogglePin(&first_inst, pin_index) == STATUS_TIMEOUT); + CHECK(HwTogglePin_fake.call_count == 1); + CHECK(HwTogglePin_fake.arg0_val == &g_mock_driver.common); + CHECK(HwTogglePin_fake.arg1_val == pin_index); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("The hardware toggle fake succeeds") + { + g_mock_driver.interface.toggle_pin = HwTogglePin; + HwTogglePin_fake.return_val = STATUS_OK; + + THEN("The pin index is forwarded to the hardware layer") + { + CHECK(ezGpio_TogglePin(&first_inst, pin_index) == STATUS_OK); + CHECK(HwTogglePin_fake.call_count == 1); + CHECK(HwTogglePin_fake.arg0_val == &g_mock_driver.common); + CHECK(HwTogglePin_fake.arg1_val == pin_index); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +TEST_CASE_METHOD(GpioTestFixture, "Test callback forwarding", "[hal][gpio]") +{ + WHEN("A GPIO driver receives an event while an instance owns the driver") + { + RegisterDriver(); + RegisterFirstInstance(); + + g_mock_driver.common.curr_inst = &first_inst; + g_event.event_code = 0x10U; + g_event.param1 = (void*)0x1234; + g_event.param2 = (void*)0x5678; + + THEN("The registered instance callback is invoked and the driver unlocks") + { + REQUIRE(g_mock_driver.common.callback != NULL); + + g_mock_driver.common.callback(&g_mock_driver, + g_event.event_code, + g_event.param1, + g_event.param2); + + CHECK(InstanceCallback_fake.call_count == 1); + CHECK(InstanceCallback_fake.arg0_val == g_event.event_code); + CHECK(InstanceCallback_fake.arg1_val == g_event.param1); + CHECK(InstanceCallback_fake.arg2_val == g_event.param2); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } } + /****************************************************************************** * Internal functions *******************************************************************************/ GpioTestFixture::GpioTestFixture() + : driver_registered(false), + first_registered(false), + second_registered(false) +{ + memset(&g_mock_driver, 0, sizeof(g_mock_driver)); + ResetEvent(); + + RESET_FAKE(HwInitPin); + RESET_FAKE(HwReadPin); + RESET_FAKE(HwWritePin); + RESET_FAKE(HwTogglePin); + RESET_FAKE(InstanceCallback); + + g_mock_driver.common.name = "Mock GPIO Driver"; + g_mock_driver.common.version[0] = 1; + g_mock_driver.common.version[1] = 0; + g_mock_driver.common.version[2] = 0; + + config.mode = EZ_GPIO_MODE_OUTPUT; + config.pull = EZ_GPIO_NO_PULL; + config.intr_mode = EZ_INTTERTUP_NONE; +} + + +GpioTestFixture::~GpioTestFixture() +{ + if(first_registered) + { + (void)ezGpio_UnregisterInstance(&first_inst); + } + + if(second_registered) + { + (void)ezGpio_UnregisterInstance(&second_inst); + } + + if(driver_registered) + { + (void)ezGpio_SystemUnregisterHwDriver(&g_mock_driver); + } +} + + +void GpioTestFixture::RegisterDriver(void) +{ + REQUIRE(ezGpio_SystemRegisterHwDriver(&g_mock_driver) == STATUS_OK); + driver_registered = true; +} + + +void GpioTestFixture::RegisterFirstInstance(void) +{ + REQUIRE(ezGpio_RegisterInstance(&first_inst, g_mock_driver.common.name, InstanceCallback) == STATUS_OK); + first_registered = true; +} + + +void GpioTestFixture::RegisterSecondInstance(void) +{ + REQUIRE(ezGpio_RegisterInstance(&second_inst, g_mock_driver.common.name, InstanceCallback) == STATUS_OK); + second_registered = true; +} + + +void GpioTestFixture::RegisterBothInstances(void) +{ + RegisterFirstInstance(); + RegisterSecondInstance(); +} + + +static void ResetEvent(void) { - RESET_FAKE(Init); - RESET_FAKE(ReadPin); - RESET_FAKE(WritePin); - RESET_FAKE(Callback); - - gpio_driver.common.name = "Mock GPIO Driver"; - gpio_driver.common.version[0] = 1; - gpio_driver.common.version[1] = 0; - gpio_driver.common.version[2] = 0; - - gpio_driver.initialized = false; - gpio_driver.interface.init_pin = Init; - gpio_driver.interface.read_pin = ReadPin; - gpio_driver.interface.write_pin = WritePin; - gpio_driver.interface.toggle_pin = NULL; + memset(&g_event, 0, sizeof(g_event)); } diff --git a/tests/hal/i2c/CMakeLists.txt b/tests/hal/i2c/CMakeLists.txt new file mode 100644 index 00000000..b6e9a56a --- /dev/null +++ b/tests/hal/i2c/CMakeLists.txt @@ -0,0 +1,57 @@ +# ---------------------------------------------------------------------------- +# Author: Hai Nguyen +# Name: ez_i2c_test +# License: This file is published under the license described in LICENSE.md +# Description: Unit tests for the I2C HAL component +# ---------------------------------------------------------------------------- + +add_executable(ez_i2c_test) + +message(STATUS "**********************************************************") +message(STATUS "* Generating ez_i2c_test build files") +message(STATUS "**********************************************************") + + +# Source files --------------------------------------------------------------- +target_sources(ez_i2c_test + PRIVATE + unittest_ez_i2c.cpp +) + + +# Definitions ---------------------------------------------------------------- +target_compile_definitions(ez_i2c_test + PUBLIC + # Please add definitions here +) + + +# Include directory ----------------------------------------------------------- +target_include_directories(ez_i2c_test + PUBLIC + ${CURRENT_DIR} + ${FFF_PATH} + PRIVATE + # Please add private folders here + INTERFACE + # Please add interface folders here +) + +# Link libraries ------------------------------------------------------------- +target_link_libraries(ez_i2c_test + PUBLIC + # Please add public libraries + PRIVATE + easy_embedded_lib + Catch2::Catch2WithMain + INTERFACE + # Please add interface libraries +) + +add_test(NAME ez_i2c_test + COMMAND ez_i2c_test +) + +catch_discover_tests(ez_i2c_test) + +# End of file \ No newline at end of file diff --git a/tests/hal/i2c/unittest_ez_i2c.cpp b/tests/hal/i2c/unittest_ez_i2c.cpp new file mode 100644 index 00000000..631cba87 --- /dev/null +++ b/tests/hal/i2c/unittest_ez_i2c.cpp @@ -0,0 +1,764 @@ +/***************************************************************************** +* Filename: unittest_ez_i2c.cpp +* Author: Hai Nguyen +* Original Date: 25.04.2026 +* +* ---------------------------------------------------------------------------- +* Contact: Hai Nguyen +* hainguyen.eeit@gmail.com +* +* ---------------------------------------------------------------------------- +* License: This file is published under the license described in LICENSE.md +* +*****************************************************************************/ + +/** @file unittest_ez_i2c.cpp + * @author Hai Nguyen + * @date 25.04.2026 + * @brief Unit tests for the I2C HAL component + * + * @details - + */ + +/****************************************************************************** +* Includes +*******************************************************************************/ +#include +#include +#include +#include + +#include "ez_driver_def.h" +#include "ez_i2c.h" +#include "fff.h" + +#include + + +/****************************************************************************** +* Module Preprocessor Macros +*******************************************************************************/ +DEFINE_FFF_GLOBALS; +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwInitialize, ezDriver_t *, ezI2cConfig_t *); +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwTransmitSync, ezDriver_t *, uint16_t, const uint8_t *, size_t, bool, uint32_t); +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwTransmitAsync, ezDriver_t *, uint16_t, const uint8_t *, size_t, bool); +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwReceiveSync, ezDriver_t *, uint16_t, uint8_t *, size_t, bool, uint32_t); +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwReceiveAsync, ezDriver_t *, uint16_t, uint8_t *, size_t, bool); +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwProbe, ezDriver_t *, uint16_t, uint32_t); +FAKE_VOID_FUNC(InstanceCallback, uint8_t, void *, void *); + + +/****************************************************************************** +* Module Typedefs +*******************************************************************************/ +typedef struct +{ + uint8_t event_code; + void *param1; + void *param2; + bool fire_async_callback; +} ezI2cAsyncEvent_t; + + +/****************************************************************************** +* Module Variable Definitions +*******************************************************************************/ +static struct ezI2cDriver g_mock_driver; +static ezI2cAsyncEvent_t g_async_event; + + +/****************************************************************************** +* Function Definitions +*******************************************************************************/ +static void ResetAsyncEvent(void); +static EZ_DRV_STATUS HwTransmitAsyncCustom(ezDriver_t *driver_h, + uint16_t address, + const uint8_t *data, + size_t length, + bool send_stop); +static EZ_DRV_STATUS HwReceiveAsyncCustom(ezDriver_t *driver_h, + uint16_t address, + uint8_t *data, + size_t length, + bool send_stop); + +class I2cTestFixture +{ +public: + I2cTestFixture(); + ~I2cTestFixture(); + +protected: + void RegisterDriver(void); + void RegisterFirstInstance(void); + void RegisterSecondInstance(void); + void RegisterBothInstances(void); + void ImplementAllInterfaces(void); + + ezI2cDrvInstance_t first_inst{}; + ezI2cDrvInstance_t second_inst{}; + ezI2cConfig_t config{}; + bool driver_registered; + bool first_registered; + bool second_registered; +}; + + +/****************************************************************************** +* External functions +*******************************************************************************/ +TEST_CASE_METHOD(I2cTestFixture, "Test driver registration", "[hal][i2c]") +{ + WHEN("A NULL hardware driver is provided") + { + /* Verify the API rejects invalid input before touching driver state. */ + THEN("The API reports an argument error") + { + CHECK(ezI2c_SystemRegisterHwDriver(NULL) == STATUS_ERR_ARG); + CHECK(ezI2c_SystemUnregisterHwDriver(NULL) == STATUS_ERR_ARG); + } + } + + WHEN("A valid hardware driver is registered") + { + RegisterDriver(); + + THEN("The driver is added in a known default state") + { + CHECK(g_mock_driver.initialized == false); + CHECK(g_mock_driver.common.callback != NULL); + } + + AND_WHEN("The same driver is unregistered") + { + g_mock_driver.initialized = true; + + THEN("The driver is reset and removed cleanly") + { + CHECK(ezI2c_SystemUnregisterHwDriver(&g_mock_driver) == STATUS_OK); + driver_registered = false; + CHECK(g_mock_driver.initialized == false); + } + } + } +} + + +TEST_CASE_METHOD(I2cTestFixture, "Test instance registration lifecycle", "[hal][i2c]") +{ + WHEN("Invalid instance registration arguments are used") + { + /* Validate direct argument guards for register and unregister APIs. */ + THEN("The APIs report argument errors") + { + CHECK(ezI2c_RegisterInstance(NULL, NULL, NULL) == STATUS_ERR_ARG); + CHECK(ezI2c_UnregisterInstance(NULL) == STATUS_ERR_ARG); + } + } + + WHEN("The target driver does not exist") + { + RegisterDriver(); + + THEN("The instance registration fails with driver-not-found") + { + CHECK(ezI2c_RegisterInstance(&first_inst, "Unknown driver", InstanceCallback) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + WHEN("A valid instance is registered to an existing driver") + { + RegisterDriver(); + + THEN("The instance stores the driver and callback pointers") + { + CHECK(ezI2c_RegisterInstance(&first_inst, g_mock_driver.common.name, InstanceCallback) == STATUS_OK); + first_registered = true; + CHECK(first_inst.driver == &g_mock_driver); + CHECK(first_inst.callback == InstanceCallback); + } + + AND_WHEN("The instance is later unregistered") + { + REQUIRE(ezI2c_RegisterInstance(&first_inst, g_mock_driver.common.name, InstanceCallback) == STATUS_OK); + first_registered = true; + + THEN("The driver reference is cleared") + { + CHECK(ezI2c_UnregisterInstance(&first_inst) == STATUS_OK); + first_registered = false; + CHECK(first_inst.driver == NULL); + } + } + } +} + + +TEST_CASE_METHOD(I2cTestFixture, "Test initialization", "[hal][i2c]") +{ + WHEN("The instance is NULL or not registered") + { + /* Confirm the API refuses initialization when no backing driver exists. */ + THEN("The API returns driver-not-found") + { + CHECK(ezI2c_Initialize(NULL, &config) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezI2c_Initialize(&first_inst, &config) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No hardware initialize function is implemented") + { + THEN("The default generic error is returned and the lock is released") + { + CHECK(ezI2c_Initialize(&first_inst, &config) == STATUS_ERR_GENERIC); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("The driver is already locked by another instance") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports a busy driver") + { + CHECK(ezI2c_Initialize(&second_inst, &config) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware initialize fake reports a failure") + { + g_mock_driver.interface.initialize = HwInitialize; + HwInitialize_fake.return_val = STATUS_TIMEOUT; + + THEN("The failure is propagated and the driver stays uninitialized") + { + CHECK(ezI2c_Initialize(&first_inst, &config) == STATUS_TIMEOUT); + CHECK(HwInitialize_fake.call_count == 1); + CHECK(g_mock_driver.initialized == false); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("The hardware initialize fake succeeds") + { + g_mock_driver.interface.initialize = HwInitialize; + HwInitialize_fake.return_val = STATUS_OK; + + THEN("The driver is initialized and the hardware call arguments are forwarded") + { + CHECK(ezI2c_Initialize(&first_inst, &config) == STATUS_OK); + CHECK(HwInitialize_fake.call_count == 1); + CHECK(HwInitialize_fake.arg0_val == &g_mock_driver.common); + CHECK(HwInitialize_fake.arg1_val == &config); + CHECK(g_mock_driver.initialized == true); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +TEST_CASE_METHOD(I2cTestFixture, "Test sync transmit", "[hal][i2c]") +{ + static const uint8_t tx_data[] = {0xDE, 0xAD, 0xBE, 0xEF}; + + WHEN("The instance is NULL or not registered") + { + THEN("The API returns driver-not-found") + { + CHECK(ezI2c_TransmitSync(NULL, 0x52, tx_data, sizeof(tx_data), true, 1000U) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezI2c_TransmitSync(&first_inst, 0x52, tx_data, sizeof(tx_data), true, 1000U) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No synchronous transmit interface is implemented") + { + THEN("The API returns driver-not-found and keeps the driver unlocked") + { + CHECK(ezI2c_TransmitSync(&first_inst, 0x52, tx_data, sizeof(tx_data), true, 1000U) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("The driver is locked by another instance") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports busy") + { + CHECK(ezI2c_TransmitSync(&second_inst, 0x52, tx_data, sizeof(tx_data), true, 1000U) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware synchronous transmit fake reports a timeout") + { + g_mock_driver.interface.transmit_sync = HwTransmitSync; + HwTransmitSync_fake.return_val = STATUS_TIMEOUT; + + THEN("The timeout is propagated and the driver lock is released") + { + CHECK(ezI2c_TransmitSync(&first_inst, 0x52, tx_data, sizeof(tx_data), true, 1000U) == STATUS_TIMEOUT); + CHECK(HwTransmitSync_fake.call_count == 1); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("The hardware synchronous transmit fake succeeds") + { + g_mock_driver.interface.transmit_sync = HwTransmitSync; + HwTransmitSync_fake.return_val = STATUS_OK; + + THEN("The transmit arguments are forwarded to the hardware layer") + { + CHECK(ezI2c_TransmitSync(&first_inst, 0x52, tx_data, sizeof(tx_data), true, 1000U) == STATUS_OK); + CHECK(HwTransmitSync_fake.call_count == 1); + CHECK(HwTransmitSync_fake.arg0_val == &g_mock_driver.common); + CHECK(HwTransmitSync_fake.arg1_val == 0x52); + CHECK(HwTransmitSync_fake.arg2_val == tx_data); + CHECK(HwTransmitSync_fake.arg3_val == sizeof(tx_data)); + CHECK(HwTransmitSync_fake.arg4_val == true); + CHECK(HwTransmitSync_fake.arg5_val == 1000U); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +TEST_CASE_METHOD(I2cTestFixture, "Test async transmit", "[hal][i2c]") +{ + static const uint8_t tx_data[] = {0x11, 0x22, 0x33}; + + WHEN("The instance is NULL or not registered") + { + THEN("The API returns driver-not-found") + { + CHECK(ezI2c_TransmitAsync(NULL, 0x62, tx_data, sizeof(tx_data), false) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezI2c_TransmitAsync(&first_inst, 0x62, tx_data, sizeof(tx_data), false) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No asynchronous transmit interface is implemented") + { + THEN("The API returns driver-not-found") + { + CHECK(ezI2c_TransmitAsync(&first_inst, 0x62, tx_data, sizeof(tx_data), false) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + WHEN("The driver is locked by another instance") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports busy") + { + CHECK(ezI2c_TransmitAsync(&second_inst, 0x62, tx_data, sizeof(tx_data), false) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware asynchronous transmit fake reports a failure") + { + g_mock_driver.interface.transmit_async = HwTransmitAsync; + HwTransmitAsync_fake.custom_fake = NULL; + HwTransmitAsync_fake.return_val = STATUS_TIMEOUT; + + THEN("The failure is returned to the caller") + { + CHECK(ezI2c_TransmitAsync(&first_inst, 0x62, tx_data, sizeof(tx_data), false) == STATUS_TIMEOUT); + CHECK(HwTransmitAsync_fake.call_count == 1); + } + } + + WHEN("The hardware asynchronous transmit fake succeeds and triggers a callback") + { + g_mock_driver.interface.transmit_async = HwTransmitAsync; + HwTransmitAsync_fake.custom_fake = HwTransmitAsyncCustom; + HwTransmitAsync_fake.return_val = STATUS_OK; + g_async_event.fire_async_callback = true; + g_async_event.event_code = 0xA1U; + g_async_event.param1 = (void*)0x1234; + g_async_event.param2 = (void*)0x5678; + + THEN("The callback is forwarded to the registered client and the driver unlocks") + { + CHECK(ezI2c_TransmitAsync(&first_inst, 0x62, tx_data, sizeof(tx_data), false) == STATUS_OK); + CHECK(HwTransmitAsync_fake.call_count == 1); + CHECK(HwTransmitAsync_fake.arg0_val == &g_mock_driver.common); + CHECK(HwTransmitAsync_fake.arg1_val == 0x62); + CHECK(HwTransmitAsync_fake.arg2_val == tx_data); + CHECK(HwTransmitAsync_fake.arg3_val == sizeof(tx_data)); + CHECK(HwTransmitAsync_fake.arg4_val == false); + CHECK(InstanceCallback_fake.call_count == 1); + CHECK(InstanceCallback_fake.arg0_val == g_async_event.event_code); + CHECK(InstanceCallback_fake.arg1_val == g_async_event.param1); + CHECK(InstanceCallback_fake.arg2_val == g_async_event.param2); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +TEST_CASE_METHOD(I2cTestFixture, "Test sync receive", "[hal][i2c]") +{ + uint8_t rx_data[4] = {0}; + + WHEN("The instance is NULL or not registered") + { + THEN("The API returns driver-not-found") + { + CHECK(ezI2c_ReceiveSync(NULL, 0x27, rx_data, sizeof(rx_data), true, 200U) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezI2c_ReceiveSync(&first_inst, 0x27, rx_data, sizeof(rx_data), true, 200U) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No synchronous receive interface is implemented") + { + THEN("The API returns driver-not-found") + { + CHECK(ezI2c_ReceiveSync(&first_inst, 0x27, rx_data, sizeof(rx_data), true, 200U) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + WHEN("The driver is locked by another instance") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports busy") + { + CHECK(ezI2c_ReceiveSync(&second_inst, 0x27, rx_data, sizeof(rx_data), true, 200U) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware synchronous receive fake reports a timeout") + { + g_mock_driver.interface.receive_sync = HwReceiveSync; + HwReceiveSync_fake.return_val = STATUS_TIMEOUT; + + THEN("The timeout is propagated and the driver unlocks") + { + CHECK(ezI2c_ReceiveSync(&first_inst, 0x27, rx_data, sizeof(rx_data), true, 200U) == STATUS_TIMEOUT); + CHECK(HwReceiveSync_fake.call_count == 1); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("The hardware synchronous receive fake succeeds") + { + g_mock_driver.interface.receive_sync = HwReceiveSync; + HwReceiveSync_fake.return_val = STATUS_OK; + + THEN("The receive arguments are forwarded to the hardware layer") + { + CHECK(ezI2c_ReceiveSync(&first_inst, 0x27, rx_data, sizeof(rx_data), true, 200U) == STATUS_OK); + CHECK(HwReceiveSync_fake.call_count == 1); + CHECK(HwReceiveSync_fake.arg0_val == &g_mock_driver.common); + CHECK(HwReceiveSync_fake.arg1_val == 0x27); + CHECK(HwReceiveSync_fake.arg2_val == rx_data); + CHECK(HwReceiveSync_fake.arg3_val == sizeof(rx_data)); + CHECK(HwReceiveSync_fake.arg4_val == true); + CHECK(HwReceiveSync_fake.arg5_val == 200U); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +TEST_CASE_METHOD(I2cTestFixture, "Test async receive", "[hal][i2c]") +{ + uint8_t rx_data[3] = {0}; + + WHEN("The instance is NULL or not registered") + { + THEN("The API returns driver-not-found") + { + CHECK(ezI2c_ReceiveAsync(NULL, 0x31, rx_data, sizeof(rx_data), true) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezI2c_ReceiveAsync(&first_inst, 0x31, rx_data, sizeof(rx_data), true) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No asynchronous receive interface is implemented") + { + THEN("The API returns driver-not-found") + { + CHECK(ezI2c_ReceiveAsync(&first_inst, 0x31, rx_data, sizeof(rx_data), true) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + WHEN("The driver is locked by another instance") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports busy") + { + CHECK(ezI2c_ReceiveAsync(&second_inst, 0x31, rx_data, sizeof(rx_data), true) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware asynchronous receive fake reports a failure") + { + g_mock_driver.interface.receive_async = HwReceiveAsync; + HwReceiveAsync_fake.custom_fake = NULL; + HwReceiveAsync_fake.return_val = STATUS_TIMEOUT; + + THEN("The failure is returned to the caller") + { + CHECK(ezI2c_ReceiveAsync(&first_inst, 0x31, rx_data, sizeof(rx_data), true) == STATUS_TIMEOUT); + CHECK(HwReceiveAsync_fake.call_count == 1); + } + } + + WHEN("The hardware asynchronous receive fake succeeds and triggers a callback") + { + g_mock_driver.interface.receive_async = HwReceiveAsync; + HwReceiveAsync_fake.custom_fake = HwReceiveAsyncCustom; + HwReceiveAsync_fake.return_val = STATUS_OK; + g_async_event.fire_async_callback = true; + g_async_event.event_code = 0xB2U; + g_async_event.param1 = (void*)0xAAAA; + g_async_event.param2 = (void*)0x5555; + + THEN("The callback is forwarded to the registered client and the driver unlocks") + { + CHECK(ezI2c_ReceiveAsync(&first_inst, 0x31, rx_data, sizeof(rx_data), true) == STATUS_OK); + CHECK(HwReceiveAsync_fake.call_count == 1); + CHECK(HwReceiveAsync_fake.arg0_val == &g_mock_driver.common); + CHECK(HwReceiveAsync_fake.arg1_val == 0x31); + CHECK(HwReceiveAsync_fake.arg2_val == rx_data); + CHECK(HwReceiveAsync_fake.arg3_val == sizeof(rx_data)); + CHECK(HwReceiveAsync_fake.arg4_val == true); + CHECK(InstanceCallback_fake.call_count == 1); + CHECK(InstanceCallback_fake.arg0_val == g_async_event.event_code); + CHECK(InstanceCallback_fake.arg1_val == g_async_event.param1); + CHECK(InstanceCallback_fake.arg2_val == g_async_event.param2); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +TEST_CASE_METHOD(I2cTestFixture, "Test probe", "[hal][i2c]") +{ + WHEN("The instance is NULL or not registered") + { + THEN("The API returns driver-not-found") + { + CHECK(ezI2c_Probe(NULL, 0x44, 50U) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezI2c_Probe(&first_inst, 0x44, 50U) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No probe interface is implemented") + { + THEN("The API returns driver-not-found") + { + CHECK(ezI2c_Probe(&first_inst, 0x44, 50U) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + WHEN("The driver is locked by another instance") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports busy") + { + CHECK(ezI2c_Probe(&second_inst, 0x44, 50U) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware probe fake reports a timeout") + { + g_mock_driver.interface.probe = HwProbe; + HwProbe_fake.return_val = STATUS_TIMEOUT; + + THEN("The timeout is propagated to the caller") + { + CHECK(ezI2c_Probe(&first_inst, 0x44, 50U) == STATUS_TIMEOUT); + CHECK(HwProbe_fake.call_count == 1); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("The hardware probe fake succeeds") + { + g_mock_driver.interface.probe = HwProbe; + HwProbe_fake.return_val = STATUS_OK; + + THEN("The probe arguments are forwarded to the hardware layer") + { + CHECK(ezI2c_Probe(&first_inst, 0x44, 50U) == STATUS_OK); + CHECK(HwProbe_fake.call_count == 1); + CHECK(HwProbe_fake.arg0_val == &g_mock_driver.common); + CHECK(HwProbe_fake.arg1_val == 0x44); + CHECK(HwProbe_fake.arg2_val == 50U); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +/****************************************************************************** +* Internal functions +*******************************************************************************/ +I2cTestFixture::I2cTestFixture() + : driver_registered(false), + first_registered(false), + second_registered(false) +{ + memset(&g_mock_driver, 0, sizeof(g_mock_driver)); + ResetAsyncEvent(); + RESET_FAKE(HwInitialize); + RESET_FAKE(HwTransmitSync); + RESET_FAKE(HwTransmitAsync); + RESET_FAKE(HwReceiveSync); + RESET_FAKE(HwReceiveAsync); + RESET_FAKE(HwProbe); + RESET_FAKE(InstanceCallback); + + g_mock_driver.common.name = "Mock I2C Driver"; + g_mock_driver.common.version[0] = 1; + g_mock_driver.common.version[1] = 0; + g_mock_driver.common.version[2] = 0; + + config.mode = EZ_I2C_MODE_MASTER; + config.speed = EZ_I2C_SPEED_FAST; + config.addressing_mode = EZ_I2C_ADDRESSING_MODE_7BIT; +} + + +I2cTestFixture::~I2cTestFixture() +{ + if(first_registered) + { + (void)ezI2c_UnregisterInstance(&first_inst); + } + + if(second_registered) + { + (void)ezI2c_UnregisterInstance(&second_inst); + } + + if(driver_registered) + { + (void)ezI2c_SystemUnregisterHwDriver(&g_mock_driver); + } +} + + +void I2cTestFixture::RegisterDriver(void) +{ + REQUIRE(ezI2c_SystemRegisterHwDriver(&g_mock_driver) == STATUS_OK); + driver_registered = true; +} + + +void I2cTestFixture::RegisterFirstInstance(void) +{ + REQUIRE(ezI2c_RegisterInstance(&first_inst, g_mock_driver.common.name, InstanceCallback) == STATUS_OK); + first_registered = true; +} + + +void I2cTestFixture::RegisterSecondInstance(void) +{ + REQUIRE(ezI2c_RegisterInstance(&second_inst, g_mock_driver.common.name, InstanceCallback) == STATUS_OK); + second_registered = true; +} + + +void I2cTestFixture::RegisterBothInstances(void) +{ + RegisterFirstInstance(); + RegisterSecondInstance(); +} + + +void I2cTestFixture::ImplementAllInterfaces(void) +{ + g_mock_driver.interface.initialize = HwInitialize; + g_mock_driver.interface.transmit_sync = HwTransmitSync; + g_mock_driver.interface.transmit_async = HwTransmitAsync; + g_mock_driver.interface.receive_sync = HwReceiveSync; + g_mock_driver.interface.receive_async = HwReceiveAsync; + g_mock_driver.interface.probe = HwProbe; + HwTransmitAsync_fake.custom_fake = HwTransmitAsyncCustom; + HwReceiveAsync_fake.custom_fake = HwReceiveAsyncCustom; +} + + +static void ResetAsyncEvent(void) +{ + memset(&g_async_event, 0, sizeof(g_async_event)); +} + + +static EZ_DRV_STATUS HwTransmitAsyncCustom(ezDriver_t *driver_h, + uint16_t address, + const uint8_t *data, + size_t length, + bool send_stop) +{ + (void)address; + (void)data; + (void)length; + (void)send_stop; + if((g_async_event.fire_async_callback == true) && (driver_h != NULL) && (driver_h->callback != NULL) && (driver_h->curr_inst != NULL)) + { + driver_h->callback(driver_h->curr_inst->driver, + g_async_event.event_code, + g_async_event.param1, + g_async_event.param2); + } + return HwTransmitAsync_fake.return_val; +} + + +static EZ_DRV_STATUS HwReceiveAsyncCustom(ezDriver_t *driver_h, + uint16_t address, + uint8_t *data, + size_t length, + bool send_stop) +{ + (void)address; + (void)data; + (void)length; + (void)send_stop; + if((g_async_event.fire_async_callback == true) && (driver_h != NULL) && (driver_h->callback != NULL) && (driver_h->curr_inst != NULL)) + { + driver_h->callback(driver_h->curr_inst->driver, + g_async_event.event_code, + g_async_event.param1, + g_async_event.param2); + } + return HwReceiveAsync_fake.return_val; +} + + +/* End of file */ \ No newline at end of file diff --git a/tests/service/driver/uart/CMakeLists.txt b/tests/hal/uart/CMakeLists.txt similarity index 87% rename from tests/service/driver/uart/CMakeLists.txt rename to tests/hal/uart/CMakeLists.txt index a197c131..c4e2db81 100644 --- a/tests/service/driver/uart/CMakeLists.txt +++ b/tests/hal/uart/CMakeLists.txt @@ -2,7 +2,7 @@ # Author: Hai Nguyen # Name: ez_uart_test # License: This file is published under the license described in LICENSE.md -# Description: PLEASE ADD TEXT HERE +# Description: Unit tests for the UART HAL component # ---------------------------------------------------------------------------- add_executable(ez_uart_test) @@ -15,7 +15,7 @@ message(STATUS "**********************************************************") # Source files --------------------------------------------------------------- target_sources(ez_uart_test PRIVATE - unittest_ez_uart.c + unittest_ez_uart.cpp ) @@ -29,7 +29,8 @@ target_compile_definitions(ez_uart_test # Include directory ----------------------------------------------------------- target_include_directories(ez_uart_test PUBLIC - # Please add private folders here + ${CURRENT_DIR} + ${FFF_PATH} PRIVATE # Please add private folders here INTERFACE @@ -42,8 +43,8 @@ target_link_libraries(ez_uart_test PUBLIC # Please add public libraries PRIVATE - unity easy_embedded_lib + Catch2::Catch2WithMain INTERFACE # Please add interface libraries ) @@ -52,4 +53,6 @@ add_test(NAME ez_uart_test COMMAND ez_uart_test ) -# End of file +catch_discover_tests(ez_uart_test) + +# End of file \ No newline at end of file diff --git a/tests/hal/uart/unittest_ez_uart.cpp b/tests/hal/uart/unittest_ez_uart.cpp new file mode 100644 index 00000000..4c153828 --- /dev/null +++ b/tests/hal/uart/unittest_ez_uart.cpp @@ -0,0 +1,852 @@ +/***************************************************************************** +* Filename: unittest_ez_uart.cpp +* Author: Hai Nguyen +* Original Date: 25.04.2026 +* +* ---------------------------------------------------------------------------- +* Contact: Hai Nguyen +* hainguyen.eeit@gmail.com +* +* ---------------------------------------------------------------------------- +* License: This file is published under the license described in LICENSE.md +* +*****************************************************************************/ + +/** @file unittest_ez_uart.cpp + * @author Hai Nguyen + * @date 25.04.2026 + * @brief Unit tests for the UART HAL component + * + * @details - + */ + +/****************************************************************************** +* Includes +*******************************************************************************/ +#include +#include +#include + +#include "ez_driver_def.h" +#include "ez_uart.h" +#include "fff.h" + +#include + + +/****************************************************************************** +* Module Preprocessor Macros +*******************************************************************************/ +DEFINE_FFF_GLOBALS; +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwInitialize, ezDriver_t *); +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwDeinitialize, ezDriver_t *); +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwAsyncTransmit, ezDriver_t *, const uint8_t *, uint16_t); +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwAsyncReceive, ezDriver_t *, uint8_t *, uint16_t); +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwSyncTransmit, ezDriver_t *, const uint8_t *, uint16_t, uint32_t); +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwSyncReceive, ezDriver_t *, uint8_t *, uint16_t, uint32_t); +FAKE_VALUE_FUNC(EZ_DRV_STATUS, HwUpdateConfig, ezDriver_t *); +FAKE_VOID_FUNC(InstanceCallback, uint8_t, void *, void *); + + +/****************************************************************************** +* Module Typedefs +*******************************************************************************/ +typedef struct +{ + uint8_t event_code; + void *param1; + void *param2; + bool fire_async_callback; +} ezUartAsyncEvent_t; + + +/****************************************************************************** +* Module Variable Definitions +*******************************************************************************/ +static struct ezUartDriver g_mock_driver; +static ezUartAsyncEvent_t g_async_event; + + +/****************************************************************************** +* Function Definitions +*******************************************************************************/ +static void ResetAsyncEvent(void); +static EZ_DRV_STATUS HwAsyncTransmitCustom(ezDriver_t *driver_h, const uint8_t *tx_buff, uint16_t buff_size); +static EZ_DRV_STATUS HwAsyncReceiveCustom(ezDriver_t *driver_h, uint8_t *rx_buff, uint16_t buff_size); + +class UartTestFixture +{ +public: + UartTestFixture(); + ~UartTestFixture(); + +protected: + void RegisterDriver(void); + void RegisterFirstInstance(void); + void RegisterSecondInstance(void); + void RegisterBothInstances(void); + + ezUartDrvInstance_t first_inst{}; + ezUartDrvInstance_t second_inst{}; + bool driver_registered; + bool first_registered; + bool second_registered; +}; + + +/****************************************************************************** +* External functions +*******************************************************************************/ +TEST_CASE_METHOD(UartTestFixture, "Test driver registration", "[hal][uart]") +{ + WHEN("A NULL hardware driver is provided") + { + /* Verify the registration entry points reject invalid arguments. */ + THEN("The APIs report an argument error") + { + CHECK(ezUart_SystemRegisterHwDriver(NULL) == STATUS_ERR_ARG); + CHECK(ezUart_SystemUnregisterHwDriver(NULL) == STATUS_ERR_ARG); + } + } + + WHEN("A valid UART driver is registered") + { + RegisterDriver(); + + THEN("The receive-event callback is installed for async completion handling") + { + CHECK(g_mock_driver.common.callback != NULL); + } + + AND_WHEN("The same driver is unregistered") + { + THEN("The driver is removed cleanly") + { + CHECK(ezUart_SystemUnregisterHwDriver(&g_mock_driver) == STATUS_OK); + driver_registered = false; + } + } + } +} + + +TEST_CASE_METHOD(UartTestFixture, "Test instance registration lifecycle", "[hal][uart]") +{ + WHEN("Invalid instance arguments are used") + { + /* Confirm basic argument validation for register and unregister APIs. */ + THEN("The APIs report argument errors") + { + CHECK(ezUart_RegisterInstance(NULL, NULL, NULL) == STATUS_ERR_ARG); + CHECK(ezUart_UnregisterInstance(NULL) == STATUS_ERR_ARG); + } + } + + WHEN("The target driver name is unknown") + { + RegisterDriver(); + + THEN("The instance registration fails with driver-not-found") + { + CHECK(ezUart_RegisterInstance(&first_inst, "Unknown driver", InstanceCallback) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + WHEN("A valid instance is registered") + { + RegisterDriver(); + + THEN("The instance stores the selected driver and callback") + { + CHECK(ezUart_RegisterInstance(&first_inst, g_mock_driver.common.name, InstanceCallback) == STATUS_OK); + first_registered = true; + CHECK(first_inst.driver == &g_mock_driver); + CHECK(first_inst.callback == InstanceCallback); + } + + AND_WHEN("The instance is unregistered") + { + REQUIRE(ezUart_RegisterInstance(&first_inst, g_mock_driver.common.name, InstanceCallback) == STATUS_OK); + first_registered = true; + + THEN("The driver reference is cleared") + { + CHECK(ezUart_UnregisterInstance(&first_inst) == STATUS_OK); + first_registered = false; + CHECK(first_inst.driver == NULL); + } + } + } +} + + +TEST_CASE_METHOD(UartTestFixture, "Test initialization", "[hal][uart]") +{ + WHEN("The instance is NULL or not registered") + { + /* The API cannot resolve a backing hardware driver in this state. */ + THEN("The API returns driver-not-found") + { + CHECK(ezUart_Initialize(NULL) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezUart_Initialize(&first_inst) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No hardware initialize function is implemented") + { + THEN("The API reports a missing interface and unlocks the driver") + { + CHECK(ezUart_Initialize(&first_inst) == STATUS_ERR_INF_NOT_EXIST); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("Another instance is already using the driver") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports a busy driver") + { + CHECK(ezUart_Initialize(&second_inst) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware initialize fake reports a timeout") + { + g_mock_driver.interface.initialize = HwInitialize; + HwInitialize_fake.return_val = STATUS_TIMEOUT; + + THEN("The failure is propagated to the caller") + { + CHECK(ezUart_Initialize(&first_inst) == STATUS_TIMEOUT); + CHECK(HwInitialize_fake.call_count == 1); + CHECK(HwInitialize_fake.arg0_val == &g_mock_driver.common); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("The hardware initialize fake succeeds") + { + g_mock_driver.interface.initialize = HwInitialize; + HwInitialize_fake.return_val = STATUS_OK; + + THEN("The driver forwards the handle and reports success") + { + CHECK(ezUart_Initialize(&first_inst) == STATUS_OK); + CHECK(HwInitialize_fake.call_count == 1); + CHECK(HwInitialize_fake.arg0_val == &g_mock_driver.common); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +TEST_CASE_METHOD(UartTestFixture, "Test deinitialization", "[hal][uart]") +{ + WHEN("The instance is NULL or not registered") + { + THEN("The API returns driver-not-found") + { + CHECK(ezUart_Deinitialize(NULL) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezUart_Deinitialize(&first_inst) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No hardware deinitialize function is implemented") + { + THEN("The API reports a missing interface") + { + CHECK(ezUart_Deinitialize(&first_inst) == STATUS_ERR_INF_NOT_EXIST); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("Another instance already owns the driver") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports busy") + { + CHECK(ezUart_Deinitialize(&second_inst) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware deinitialize fake reports a timeout") + { + g_mock_driver.interface.deinitialize = HwDeinitialize; + HwDeinitialize_fake.return_val = STATUS_TIMEOUT; + + THEN("The failure is propagated") + { + CHECK(ezUart_Deinitialize(&first_inst) == STATUS_TIMEOUT); + CHECK(HwDeinitialize_fake.call_count == 1); + CHECK(HwDeinitialize_fake.arg0_val == &g_mock_driver.common); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("The hardware deinitialize fake succeeds") + { + g_mock_driver.interface.deinitialize = HwDeinitialize; + HwDeinitialize_fake.return_val = STATUS_OK; + + THEN("The driver forwards the handle and reports success") + { + CHECK(ezUart_Deinitialize(&first_inst) == STATUS_OK); + CHECK(HwDeinitialize_fake.call_count == 1); + CHECK(HwDeinitialize_fake.arg0_val == &g_mock_driver.common); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +TEST_CASE_METHOD(UartTestFixture, "Test async transmit", "[hal][uart]") +{ + static const uint8_t tx_buff[] = {0x10, 0x20, 0x30}; + + WHEN("The instance is NULL or not registered") + { + THEN("The API returns driver-not-found") + { + CHECK(ezUart_AsyncTransmit(NULL, tx_buff, sizeof(tx_buff)) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezUart_AsyncTransmit(&first_inst, tx_buff, sizeof(tx_buff)) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No asynchronous transmit interface is implemented") + { + THEN("The API reports a missing interface") + { + CHECK(ezUart_AsyncTransmit(&first_inst, tx_buff, sizeof(tx_buff)) == STATUS_ERR_INF_NOT_EXIST); + } + } + + WHEN("Another instance already owns the driver") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports busy") + { + CHECK(ezUart_AsyncTransmit(&second_inst, tx_buff, sizeof(tx_buff)) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware async transmit fake reports a timeout") + { + g_mock_driver.interface.async_transmit = HwAsyncTransmit; + HwAsyncTransmit_fake.custom_fake = NULL; + HwAsyncTransmit_fake.return_val = STATUS_TIMEOUT; + + THEN("The timeout is propagated to the caller") + { + CHECK(ezUart_AsyncTransmit(&first_inst, tx_buff, sizeof(tx_buff)) == STATUS_TIMEOUT); + CHECK(HwAsyncTransmit_fake.call_count == 1); + CHECK(HwAsyncTransmit_fake.arg0_val == &g_mock_driver.common); + } + } + + WHEN("The hardware async transmit fake succeeds and raises a callback") + { + g_mock_driver.interface.async_transmit = HwAsyncTransmit; + HwAsyncTransmit_fake.custom_fake = HwAsyncTransmitCustom; + HwAsyncTransmit_fake.return_val = STATUS_OK; + g_async_event.fire_async_callback = true; + g_async_event.event_code = UART_EVENT_TX_CMPLT; + g_async_event.param1 = (void*)0x1111; + g_async_event.param2 = (void*)0x2222; + + THEN("The callback is forwarded and the driver is unlocked") + { + CHECK(ezUart_AsyncTransmit(&first_inst, tx_buff, sizeof(tx_buff)) == STATUS_OK); + CHECK(HwAsyncTransmit_fake.call_count == 1); + CHECK(HwAsyncTransmit_fake.arg0_val == &g_mock_driver.common); + CHECK(HwAsyncTransmit_fake.arg1_val == tx_buff); + CHECK(HwAsyncTransmit_fake.arg2_val == sizeof(tx_buff)); + CHECK(InstanceCallback_fake.call_count == 1); + CHECK(InstanceCallback_fake.arg0_val == g_async_event.event_code); + CHECK(InstanceCallback_fake.arg1_val == g_async_event.param1); + CHECK(InstanceCallback_fake.arg2_val == g_async_event.param2); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +TEST_CASE_METHOD(UartTestFixture, "Test async receive", "[hal][uart]") +{ + uint8_t rx_buff[4] = {0}; + + WHEN("The instance is NULL or not registered") + { + THEN("The API returns driver-not-found") + { + CHECK(ezUart_AsyncReceive(NULL, rx_buff, sizeof(rx_buff)) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezUart_AsyncReceive(&first_inst, rx_buff, sizeof(rx_buff)) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No asynchronous receive interface is implemented") + { + THEN("The API reports a missing interface") + { + CHECK(ezUart_AsyncReceive(&first_inst, rx_buff, sizeof(rx_buff)) == STATUS_ERR_INF_NOT_EXIST); + } + } + + WHEN("Another instance already owns the driver") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports busy") + { + CHECK(ezUart_AsyncReceive(&second_inst, rx_buff, sizeof(rx_buff)) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware async receive fake reports a timeout") + { + g_mock_driver.interface.async_receive = HwAsyncReceive; + HwAsyncReceive_fake.custom_fake = NULL; + HwAsyncReceive_fake.return_val = STATUS_TIMEOUT; + + THEN("The timeout is propagated to the caller") + { + CHECK(ezUart_AsyncReceive(&first_inst, rx_buff, sizeof(rx_buff)) == STATUS_TIMEOUT); + CHECK(HwAsyncReceive_fake.call_count == 1); + CHECK(HwAsyncReceive_fake.arg0_val == &g_mock_driver.common); + } + } + + WHEN("The hardware async receive fake succeeds and raises a callback") + { + g_mock_driver.interface.async_receive = HwAsyncReceive; + HwAsyncReceive_fake.custom_fake = HwAsyncReceiveCustom; + HwAsyncReceive_fake.return_val = STATUS_OK; + g_async_event.fire_async_callback = true; + g_async_event.event_code = UART_EVENT_RX_CMPLT; + g_async_event.param1 = (void*)0x3333; + g_async_event.param2 = (void*)0x4444; + + THEN("The callback is forwarded and the driver is unlocked") + { + CHECK(ezUart_AsyncReceive(&first_inst, rx_buff, sizeof(rx_buff)) == STATUS_OK); + CHECK(HwAsyncReceive_fake.call_count == 1); + CHECK(HwAsyncReceive_fake.arg0_val == &g_mock_driver.common); + CHECK(HwAsyncReceive_fake.arg1_val == rx_buff); + CHECK(HwAsyncReceive_fake.arg2_val == sizeof(rx_buff)); + CHECK(InstanceCallback_fake.call_count == 1); + CHECK(InstanceCallback_fake.arg0_val == g_async_event.event_code); + CHECK(InstanceCallback_fake.arg1_val == g_async_event.param1); + CHECK(InstanceCallback_fake.arg2_val == g_async_event.param2); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +TEST_CASE_METHOD(UartTestFixture, "Test sync transmit", "[hal][uart]") +{ + static const uint8_t tx_buff[] = {0xAB, 0xCD, 0xEF}; + + WHEN("The instance is NULL or not registered") + { + THEN("The API returns driver-not-found") + { + CHECK(ezUart_SyncTransmit(NULL, tx_buff, sizeof(tx_buff), 1000U) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezUart_SyncTransmit(&first_inst, tx_buff, sizeof(tx_buff), 1000U) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No synchronous transmit interface is implemented") + { + THEN("The API reports a missing interface") + { + CHECK(ezUart_SyncTransmit(&first_inst, tx_buff, sizeof(tx_buff), 1000U) == STATUS_ERR_INF_NOT_EXIST); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("Another instance already owns the driver") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports busy") + { + CHECK(ezUart_SyncTransmit(&second_inst, tx_buff, sizeof(tx_buff), 1000U) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware sync transmit fake reports a timeout") + { + g_mock_driver.interface.sync_transmit = HwSyncTransmit; + HwSyncTransmit_fake.return_val = STATUS_TIMEOUT; + + THEN("The timeout is propagated and the driver unlocks") + { + CHECK(ezUart_SyncTransmit(&first_inst, tx_buff, sizeof(tx_buff), 1000U) == STATUS_TIMEOUT); + CHECK(HwSyncTransmit_fake.call_count == 1); + CHECK(HwSyncTransmit_fake.arg0_val == &g_mock_driver.common); + CHECK(HwSyncTransmit_fake.arg1_val == tx_buff); + CHECK(HwSyncTransmit_fake.arg2_val == sizeof(tx_buff)); + CHECK(HwSyncTransmit_fake.arg3_val == 1000U); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("The hardware sync transmit fake succeeds") + { + g_mock_driver.interface.sync_transmit = HwSyncTransmit; + HwSyncTransmit_fake.return_val = STATUS_OK; + + THEN("The transmit arguments are forwarded to the hardware layer") + { + CHECK(ezUart_SyncTransmit(&first_inst, tx_buff, sizeof(tx_buff), 1000U) == STATUS_OK); + CHECK(HwSyncTransmit_fake.call_count == 1); + CHECK(HwSyncTransmit_fake.arg0_val == &g_mock_driver.common); + CHECK(HwSyncTransmit_fake.arg1_val == tx_buff); + CHECK(HwSyncTransmit_fake.arg2_val == sizeof(tx_buff)); + CHECK(HwSyncTransmit_fake.arg3_val == 1000U); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +TEST_CASE_METHOD(UartTestFixture, "Test sync receive", "[hal][uart]") +{ + uint8_t rx_buff[4] = {0}; + + WHEN("The instance is NULL or not registered") + { + THEN("The API returns driver-not-found") + { + CHECK(ezUart_SyncReceive(NULL, rx_buff, sizeof(rx_buff), 1000U) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezUart_SyncReceive(&first_inst, rx_buff, sizeof(rx_buff), 1000U) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No synchronous receive interface is implemented") + { + THEN("The API reports a missing interface") + { + CHECK(ezUart_SyncReceive(&first_inst, rx_buff, sizeof(rx_buff), 1000U) == STATUS_ERR_INF_NOT_EXIST); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("Another instance already owns the driver") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports busy") + { + CHECK(ezUart_SyncReceive(&second_inst, rx_buff, sizeof(rx_buff), 1000U) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware sync receive fake reports a timeout") + { + g_mock_driver.interface.sync_receive = HwSyncReceive; + HwSyncReceive_fake.return_val = STATUS_TIMEOUT; + + THEN("The timeout is propagated and the driver unlocks") + { + CHECK(ezUart_SyncReceive(&first_inst, rx_buff, sizeof(rx_buff), 1000U) == STATUS_TIMEOUT); + CHECK(HwSyncReceive_fake.call_count == 1); + CHECK(HwSyncReceive_fake.arg0_val == &g_mock_driver.common); + CHECK(HwSyncReceive_fake.arg1_val == rx_buff); + CHECK(HwSyncReceive_fake.arg2_val == sizeof(rx_buff)); + CHECK(HwSyncReceive_fake.arg3_val == 1000U); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("The hardware sync receive fake succeeds") + { + g_mock_driver.interface.sync_receive = HwSyncReceive; + HwSyncReceive_fake.return_val = STATUS_OK; + + THEN("The receive arguments are forwarded to the hardware layer") + { + CHECK(ezUart_SyncReceive(&first_inst, rx_buff, sizeof(rx_buff), 1000U) == STATUS_OK); + CHECK(HwSyncReceive_fake.call_count == 1); + CHECK(HwSyncReceive_fake.arg0_val == &g_mock_driver.common); + CHECK(HwSyncReceive_fake.arg1_val == rx_buff); + CHECK(HwSyncReceive_fake.arg2_val == sizeof(rx_buff)); + CHECK(HwSyncReceive_fake.arg3_val == 1000U); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +TEST_CASE_METHOD(UartTestFixture, "Test get configuration", "[hal][uart]") +{ + struct ezUartConfiguration *config = NULL; + + WHEN("The instance is NULL or not registered") + { + THEN("The API returns driver-not-found") + { + CHECK(ezUart_GetConfig(NULL, &config) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezUart_GetConfig(&first_inst, &config) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("The output configuration pointer is NULL") + { + THEN("The API reports an argument error") + { + CHECK(ezUart_GetConfig(&first_inst, NULL) == STATUS_ERR_ARG); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("Another instance already owns the driver") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports busy") + { + CHECK(ezUart_GetConfig(&second_inst, &config) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("A valid output pointer is provided") + { + THEN("The API exposes the driver's live configuration structure") + { + CHECK(ezUart_GetConfig(&first_inst, &config) == STATUS_OK); + REQUIRE(config != NULL); + CHECK(config == &g_mock_driver.config); + CHECK(config->baudrate == 115200U); + CHECK(config->port_name == g_mock_driver.config.port_name); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +TEST_CASE_METHOD(UartTestFixture, "Test update configuration", "[hal][uart]") +{ + WHEN("The instance is NULL or not registered") + { + THEN("The API returns driver-not-found") + { + CHECK(ezUart_UpdateConfig(NULL) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(ezUart_UpdateConfig(&first_inst) == STATUS_ERR_DRV_NOT_FOUND); + } + } + + RegisterDriver(); + RegisterBothInstances(); + + WHEN("No update-config interface is implemented") + { + /* The source leaves the default driver-not-found status unchanged here. */ + THEN("The API returns the current default status") + { + CHECK(ezUart_UpdateConfig(&first_inst) == STATUS_ERR_DRV_NOT_FOUND); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("Another instance already owns the driver") + { + g_mock_driver.common.curr_inst = &first_inst; + + THEN("The API reports busy") + { + CHECK(ezUart_UpdateConfig(&second_inst) == STATUS_BUSY); + } + + g_mock_driver.common.curr_inst = NULL; + } + + WHEN("The hardware update-config fake reports a timeout") + { + g_mock_driver.interface.update_conf = HwUpdateConfig; + HwUpdateConfig_fake.return_val = STATUS_TIMEOUT; + + THEN("The timeout is propagated to the caller") + { + CHECK(ezUart_UpdateConfig(&first_inst) == STATUS_TIMEOUT); + CHECK(HwUpdateConfig_fake.call_count == 1); + CHECK(HwUpdateConfig_fake.arg0_val == &g_mock_driver.common); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } + + WHEN("The hardware update-config fake succeeds") + { + g_mock_driver.interface.update_conf = HwUpdateConfig; + HwUpdateConfig_fake.return_val = STATUS_OK; + + THEN("The driver forwards the handle and reports success") + { + CHECK(ezUart_UpdateConfig(&first_inst) == STATUS_OK); + CHECK(HwUpdateConfig_fake.call_count == 1); + CHECK(HwUpdateConfig_fake.arg0_val == &g_mock_driver.common); + CHECK(g_mock_driver.common.curr_inst == NULL); + } + } +} + + +/****************************************************************************** +* Internal functions +*******************************************************************************/ +UartTestFixture::UartTestFixture() + : driver_registered(false), + first_registered(false), + second_registered(false) +{ + memset(&g_mock_driver, 0, sizeof(g_mock_driver)); + ResetAsyncEvent(); + + RESET_FAKE(HwInitialize); + RESET_FAKE(HwDeinitialize); + RESET_FAKE(HwAsyncTransmit); + RESET_FAKE(HwAsyncReceive); + RESET_FAKE(HwSyncTransmit); + RESET_FAKE(HwSyncReceive); + RESET_FAKE(HwUpdateConfig); + RESET_FAKE(InstanceCallback); + + g_mock_driver.common.name = "Mock UART Driver"; + g_mock_driver.common.version[0] = 1; + g_mock_driver.common.version[1] = 0; + g_mock_driver.common.version[2] = 0; + + g_mock_driver.config.port_name = "COM1"; + g_mock_driver.config.baudrate = 115200U; + g_mock_driver.config.parity = PARITY_ODD; + g_mock_driver.config.stop_bit = ONE_BIT; + g_mock_driver.config.byte_size = 8U; +} + + +UartTestFixture::~UartTestFixture() +{ + if(first_registered) + { + (void)ezUart_UnregisterInstance(&first_inst); + } + + if(second_registered) + { + (void)ezUart_UnregisterInstance(&second_inst); + } + + if(driver_registered) + { + (void)ezUart_SystemUnregisterHwDriver(&g_mock_driver); + } +} + + +void UartTestFixture::RegisterDriver(void) +{ + REQUIRE(ezUart_SystemRegisterHwDriver(&g_mock_driver) == STATUS_OK); + driver_registered = true; +} + + +void UartTestFixture::RegisterFirstInstance(void) +{ + REQUIRE(ezUart_RegisterInstance(&first_inst, g_mock_driver.common.name, InstanceCallback) == STATUS_OK); + first_registered = true; +} + + +void UartTestFixture::RegisterSecondInstance(void) +{ + REQUIRE(ezUart_RegisterInstance(&second_inst, g_mock_driver.common.name, InstanceCallback) == STATUS_OK); + second_registered = true; +} + + +void UartTestFixture::RegisterBothInstances(void) +{ + RegisterFirstInstance(); + RegisterSecondInstance(); +} + + +static void ResetAsyncEvent(void) +{ + memset(&g_async_event, 0, sizeof(g_async_event)); +} + + +static EZ_DRV_STATUS HwAsyncTransmitCustom(ezDriver_t *driver_h, const uint8_t *tx_buff, uint16_t buff_size) +{ + (void)tx_buff; + (void)buff_size; + + if((g_async_event.fire_async_callback == true) && (driver_h != NULL) && (driver_h->callback != NULL) && (driver_h->curr_inst != NULL)) + { + driver_h->callback(driver_h->curr_inst->driver, + g_async_event.event_code, + g_async_event.param1, + g_async_event.param2); + } + + return HwAsyncTransmit_fake.return_val; +} + + +static EZ_DRV_STATUS HwAsyncReceiveCustom(ezDriver_t *driver_h, uint8_t *rx_buff, uint16_t buff_size) +{ + (void)rx_buff; + (void)buff_size; + + if((g_async_event.fire_async_callback == true) && (driver_h != NULL) && (driver_h->callback != NULL) && (driver_h->curr_inst != NULL)) + { + driver_h->callback(driver_h->curr_inst->driver, + g_async_event.event_code, + g_async_event.param1, + g_async_event.param2); + } + + return HwAsyncReceive_fake.return_val; +} + + +/* End of file */ \ No newline at end of file diff --git a/tests/service/driver/hal_echo/CMakeLists.txt b/tests/service/driver/hal_echo/CMakeLists.txt deleted file mode 100755 index 09e0111b..00000000 --- a/tests/service/driver/hal_echo/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -#build the unit tests -add_library(ez_unit_test_hal_echo) - -set(CURRENT_DIR ${CMAKE_CURRENT_LIST_DIR}) -set(SDK_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}../../../../../) - -#include directory -target_include_directories(ez_unit_test_hal_echo PRIVATE - ${CURRENT_DIR} - ${SDK_ROOT_DIR}/ezmsdk -) - -target_link_libraries(ez_unit_test_hal_echo PRIVATE unity sdk) - -# Service module -target_sources(ez_unit_test_hal_echo PRIVATE - Test_EchoHal.c - Test_EchoHal_Runner.c -) diff --git a/tests/service/driver/hal_echo/Test_EchoHal.c b/tests/service/driver/hal_echo/Test_EchoHal.c deleted file mode 100755 index ccf8c04b..00000000 --- a/tests/service/driver/hal_echo/Test_EchoHal.c +++ /dev/null @@ -1,401 +0,0 @@ - -/******************************************************************************* -* Filename: EchoHal.c -* Author: Hai Nguyen -* Original Date: 18.06.2023 -* Last Update: 18.06.2023 -* -* ----------------------------------------------------------------------------- -* Company: Embedded Easy -* Address Line 1 -* Address Line 2 -* -* ----------------------------------------------------------------------------- -* Contact: Embedded Easy -* hainguyen.ezm@gmail.com -* -* ----------------------------------------------------------------------------- -* Copyright Hai Nguyen - All Rights Reserved -* Unauthorized copying of this file, via any medium is strictly prohibited -* Proprietary and confidential -* Written by Hai Nguyen 18.06.2023 -* -*******************************************************************************/ - -/** @file EchoHal.c - * @author Hai Nguyen - * @date 18.06.2023 - * @brief This is the source for a module - * - * @details - * - */ - -/****************************************************************************** -* Includes -*******************************************************************************/ -#include -#include -#include "string.h" - -#include "service/driver/ez_hal_driver_def.h" -#include "service/driver/hal/hal_echo/ez_hal_echo.h" - -#include "unity.h" -#include "unity_fixture.h" - - -TEST_GROUP(EchoHal); - - -/****************************************************************************** -* Module Preprocessor Macros -*******************************************************************************/ -/* None */ - -/****************************************************************************** -* Module Typedefs -*******************************************************************************/ -/* None */ - -/****************************************************************************** -* Module Variable Definitions -*******************************************************************************/ -static ezDriverHandle_t handle1; -static ezDriverHandle_t handle2; -static ezDriverHandle_t handle3; - -static ezDriverStatus_t status = EZ_DRIVER_OK; -static uint8_t buff_1[32] = { 0xca }; -static uint8_t buff_2[64] = { 0xfe }; -static uint8_t read_buff[128] = { 0 }; - -static uint32_t handle1_callback_count = 0; -static uint32_t handle2_callback_count = 0; -static uint32_t handle3_callback_count = 0; - - -/****************************************************************************** -* Function Definitions -*******************************************************************************/ -/* None */ - -/****************************************************************************** -* External functions -*******************************************************************************/ -/* None */ - - -/****************************************************************************** -* Internal functions -*******************************************************************************/ -static void Handle1Callback(uint8_t cb_code, void *param1, void *param2); -static void Handle2Callback(uint8_t cb_code, void *param1, void *param2); -static void Handle3Callback(uint8_t cb_code, void *param1, void *param2); - -static void Handle1Callback(uint8_t cb_code, void *param1, void *param2) -{ - handle1_callback_count++; -} - -static void Handle2Callback(uint8_t cb_code, void *param1, void *param2) -{ - handle2_callback_count++; -} - -static void Handle3Callback(uint8_t cb_code, void *param1, void *param2) -{ - handle3_callback_count++; -} - - -TEST_SETUP(EchoHal) -{ - memset(&handle1, 0, sizeof(handle1)); - memset(&handle2, 0, sizeof(handle2)); - memset(&handle3, 0, sizeof(handle3)); - memset(&buff_1, 0xca, sizeof(buff_1)); - memset(&buff_2, 0xfe, sizeof(buff_2)); - memset(&read_buff, 0, sizeof(read_buff)); - - handle1_callback_count = 0; - handle2_callback_count = 0; - handle3_callback_count = 0; - - ezHalEcho_Initialize(); -} - - -TEST_TEAR_DOWN(EchoHal) -{ -} - - -TEST(EchoHal, ezHalEcho_GetDriver_Correct) -{ - status = ezHalEcho_GetDriver(ECHO_INTERFACE_1_NAME, &handle1, Handle1Callback); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - status = ezHalEcho_GetDriver(ECHO_INTERFACE_2_NAME, &handle2, Handle2Callback); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - TEST_ASSERT_NOT_EQUAL(handle1.driver, NULL); - TEST_ASSERT_NOT_EQUAL(handle2.driver, NULL); - - TEST_ASSERT_NOT_EQUAL(handle1.callback, NULL); - TEST_ASSERT_NOT_EQUAL(handle2.callback, NULL); - - if (handle1.driver != NULL) - { - TEST_ASSERT_EQUAL_STRING(ECHO_INTERFACE_1_NAME, handle1.driver->name); - } - - if (handle2.driver != NULL) - { - TEST_ASSERT_EQUAL_STRING(ECHO_INTERFACE_2_NAME, handle2.driver->name); - } -} - - -TEST(EchoHal, ezHalEcho_GetDriver_Incorrect) -{ - status = ezHalEcho_GetDriver("Random name", &handle1, Handle1Callback); - TEST_ASSERT_EQUAL(EZ_DRIVER_ERR_NO_DRIVER, status); - TEST_ASSERT_EQUAL(NULL, handle1.driver); - TEST_ASSERT_EQUAL(NULL, handle1.callback); - - status = ezHalEcho_GetDriver("Shalala", &handle1, Handle1Callback); - TEST_ASSERT_EQUAL(EZ_DRIVER_ERR_NO_DRIVER, status); - TEST_ASSERT_EQUAL(NULL, handle1.driver); - TEST_ASSERT_EQUAL(NULL, handle1.callback); - - status = ezHalEcho_GetDriver("", &handle1, Handle1Callback); - TEST_ASSERT_EQUAL(EZ_DRIVER_ERR_NO_DRIVER, status); - TEST_ASSERT_EQUAL(NULL, handle1.driver); - TEST_ASSERT_EQUAL(NULL, handle1.callback); -} - - -TEST(EchoHal, ezHalEcho_ReleaseDriver) -{ - status = ezHalEcho_GetDriver(ECHO_INTERFACE_1_NAME, &handle1, Handle1Callback); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - status = ezHalEcho_ReleaseDriver(&handle1); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - TEST_ASSERT_EQUAL(NULL, handle1.driver); - TEST_ASSERT_EQUAL(NULL, handle1.callback); - TEST_ASSERT_EQUAL(&handle1.node, handle1.node.next); - TEST_ASSERT_EQUAL(&handle1.node, handle1.node.prev); -} - - -TEST(EchoHal, ezHalEcho_Write_Incorrect) -{ - uint32_t byte_written = 0xdeadcafe; - - byte_written = ezHalEcho_Write(&handle1, buff_1, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - status = ezHalEcho_GetDriver(ECHO_INTERFACE_1_NAME, &handle1, Handle1Callback); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - byte_written = ezHalEcho_Write(&handle1, NULL, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - byte_written = ezHalEcho_Write(&handle1, NULL, 0); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - byte_written = ezHalEcho_Write(&handle1, buff_1, 0); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - byte_written = ezHalEcho_Write(NULL, buff_1, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - byte_written = ezHalEcho_Write(NULL, NULL, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - byte_written = ezHalEcho_Write(NULL, NULL, sizeof(0)); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - /* interface 2 */ - byte_written = 0xdeadcafe; - - byte_written = ezHalEcho_Write(&handle2, buff_1, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(0, handle2_callback_count); - - status = ezHalEcho_GetDriver(ECHO_INTERFACE_2_NAME, &handle2, Handle2Callback); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - TEST_ASSERT_EQUAL(0, handle2_callback_count); - - byte_written = ezHalEcho_Write(&handle2, NULL, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(0, handle2_callback_count); - - byte_written = ezHalEcho_Write(&handle2, NULL, 0); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(0, handle2_callback_count); - - byte_written = ezHalEcho_Write(&handle2, buff_1, 0); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(0, handle2_callback_count); - - byte_written = ezHalEcho_Write(NULL, buff_1, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(0, handle2_callback_count); - - byte_written = ezHalEcho_Write(NULL, NULL, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(0, handle2_callback_count); - - byte_written = ezHalEcho_Write(NULL, NULL, sizeof(0)); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(0, handle2_callback_count); -} - - -TEST(EchoHal, ezHalEcho_Write_Correct) -{ - uint32_t byte_written = 0xdeadcafe; - - status = ezHalEcho_GetDriver(ECHO_INTERFACE_1_NAME, &handle1, Handle1Callback); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - status = ezHalEcho_GetDriver(ECHO_INTERFACE_1_NAME, &handle3, Handle3Callback); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - byte_written = ezHalEcho_Write(&handle1, buff_1, sizeof(buff_1)); - TEST_ASSERT_EQUAL(sizeof(buff_1), byte_written); - TEST_ASSERT_EQUAL(1, handle1_callback_count); - - byte_written = ezHalEcho_Write(&handle1, buff_2, sizeof(buff_2)); - TEST_ASSERT_EQUAL(sizeof(buff_2), byte_written); - TEST_ASSERT_EQUAL(2, handle1_callback_count); - - /* Write when buff is full */ - byte_written = ezHalEcho_Write(&handle1, buff_2, sizeof(buff_2)); - TEST_ASSERT_EQUAL(32, byte_written); - TEST_ASSERT_EQUAL(3, handle1_callback_count); - - byte_written = ezHalEcho_Write(&handle1, buff_1, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_written); - TEST_ASSERT_EQUAL(4, handle1_callback_count); -} - - -TEST(EchoHal, ezHalEcho_Read_Incorrect) -{ - uint32_t byte_read = 0xdeadcafe; - - byte_read = ezHalEcho_Write(&handle1, buff_1, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - status = ezHalEcho_GetDriver(ECHO_INTERFACE_1_NAME, &handle1, Handle1Callback); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - byte_read = ezHalEcho_Read(&handle1, NULL, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - byte_read = ezHalEcho_Read(&handle1, NULL, 0); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - byte_read = ezHalEcho_Read(&handle1, buff_1, 0); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - byte_read = ezHalEcho_Read(NULL, buff_1, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - byte_read = ezHalEcho_Read(NULL, NULL, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - byte_read = ezHalEcho_Read(NULL, NULL, sizeof(0)); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(0, handle1_callback_count); - - /* interface 2 */ - byte_read = 0xdeadcafe; - - byte_read = ezHalEcho_Read(&handle2, buff_1, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(0, handle2_callback_count); - - status = ezHalEcho_GetDriver(ECHO_INTERFACE_2_NAME, &handle2, Handle2Callback); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - TEST_ASSERT_EQUAL(0, handle2_callback_count); - - byte_read = ezHalEcho_Read(&handle2, NULL, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(0, handle2_callback_count); - - byte_read = ezHalEcho_Read(&handle2, NULL, 0); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(0, handle2_callback_count); - - byte_read = ezHalEcho_Read(&handle2, buff_1, 0); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(0, handle2_callback_count); - - byte_read = ezHalEcho_Read(NULL, buff_1, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(0, handle2_callback_count); - - byte_read = ezHalEcho_Read(NULL, NULL, sizeof(buff_1)); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(0, handle2_callback_count); - - byte_read = ezHalEcho_Read(NULL, NULL, sizeof(0)); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(0, handle2_callback_count); -} - -TEST(EchoHal, ezHalEcho_Read_Correct) -{ - uint32_t byte_read = 0xdeadcafe; - uint32_t byte_written = 0xdeadcafe; - - status = ezHalEcho_GetDriver(ECHO_INTERFACE_1_NAME, &handle1, Handle1Callback); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - status = ezHalEcho_GetDriver(ECHO_INTERFACE_1_NAME, &handle3, Handle3Callback); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - byte_written = ezHalEcho_Write(&handle1, buff_1, sizeof(buff_1)); - TEST_ASSERT_EQUAL(sizeof(buff_1), byte_written); - TEST_ASSERT_EQUAL(1, handle1_callback_count); - - byte_written = ezHalEcho_Write(&handle1, buff_2, sizeof(buff_2)); - TEST_ASSERT_EQUAL(sizeof(buff_2), byte_written); - TEST_ASSERT_EQUAL(2, handle1_callback_count); - - byte_read = ezHalEcho_Read(&handle1, read_buff, sizeof(buff_1)); - TEST_ASSERT_EQUAL(sizeof(buff_1), byte_read); - TEST_ASSERT_EQUAL(3, handle1_callback_count); - TEST_ASSERT_EQUAL_MEMORY(buff_1, read_buff, sizeof(buff_1)); - - byte_read = ezHalEcho_Read(&handle1, read_buff, sizeof(buff_2)); - TEST_ASSERT_EQUAL(sizeof(buff_2), byte_read); - TEST_ASSERT_EQUAL(4, handle1_callback_count); - TEST_ASSERT_EQUAL_MEMORY(buff_2, read_buff, sizeof(buff_2)); - - byte_read = ezHalEcho_Read(&handle1, read_buff, 32); - TEST_ASSERT_EQUAL(0, byte_read); - TEST_ASSERT_EQUAL(5, handle1_callback_count); -} -/* End of file */ - diff --git a/tests/service/driver/hal_echo/Test_EchoHal_Runner.c b/tests/service/driver/hal_echo/Test_EchoHal_Runner.c deleted file mode 100755 index 595f53b4..00000000 --- a/tests/service/driver/hal_echo/Test_EchoHal_Runner.c +++ /dev/null @@ -1,86 +0,0 @@ - -/******************************************************************************* -* Filename: EchoHal_runner.c -* Author: Hai Nguyen -* Original Date: 18.06.2023 -* Last Update: 18.06.2023 -* -* ----------------------------------------------------------------------------- -* Company: Embedded Easy -* Address Line 1 -* Address Line 2 -* -* ----------------------------------------------------------------------------- -* Contact: Embedded Easy -* hainguyen.ezm@gmail.com -* -* ----------------------------------------------------------------------------- -* Copyright Hai Nguyen - All Rights Reserved -* Unauthorized copying of this file, via any medium is strictly prohibited -* Proprietary and confidential -* Written by Hai Nguyen 18.06.2023 -* -*******************************************************************************/ - -/** @file EchoHal_runner.c - * @author Hai Nguyen - * @date 18.06.2023 - * @brief This is the source for a module - * - * @details - * - */ - -/****************************************************************************** -* Includes -*******************************************************************************/ -#include -#include - -#include "unity.h" -#include "unity_fixture.h" - - -/****************************************************************************** -* Module Preprocessor Macros -*******************************************************************************/ -/* None */ - -/****************************************************************************** -* Module Typedefs -*******************************************************************************/ -/* None */ - -/****************************************************************************** -* Module Variable Definitions -*******************************************************************************/ -/* None */ - -/****************************************************************************** -* Function Definitions -*******************************************************************************/ -/* None */ - -/****************************************************************************** -* External functions -*******************************************************************************/ -/* None */ - - -/****************************************************************************** -* Internal functions -*******************************************************************************/ -TEST_GROUP_RUNNER(EchoHal) -{ - RUN_TEST_CASE(EchoHal, ezHalEcho_GetDriver_Correct); - RUN_TEST_CASE(EchoHal, ezHalEcho_GetDriver_Incorrect); - RUN_TEST_CASE(EchoHal, ezHalEcho_ReleaseDriver); - RUN_TEST_CASE(EchoHal, ezHalEcho_Write_Incorrect); - RUN_TEST_CASE(EchoHal, ezHalEcho_Write_Correct); - RUN_TEST_CASE(EchoHal, ezHalEcho_Read_Incorrect); - RUN_TEST_CASE(EchoHal, ezHalEcho_Read_Correct); -} - - -/* End of file */ - diff --git a/tests/service/driver/hal_uart/CMakeLists.txt b/tests/service/driver/hal_uart/CMakeLists.txt deleted file mode 100755 index 213c1ec7..00000000 --- a/tests/service/driver/hal_uart/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -#build the unit tests -add_library(ez_unit_test_hal_uart) - -set(CURRENT_DIR ${CMAKE_CURRENT_LIST_DIR}) -set(SDK_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}../../../../../) - -#include directory -target_include_directories(ez_unit_test_hal_uart PRIVATE - ${CURRENT_DIR} - ${SDK_ROOT_DIR}/ezmsdk -) - -target_link_libraries(ez_unit_test_hal_uart PRIVATE unity sdk) - -# Service module -target_sources(ez_unit_test_hal_uart PRIVATE - Test_ez_hal_uart.c - Test_ez_hal_uart_Runner.c -) diff --git a/tests/service/driver/hal_uart/Test_ez_hal_uart.c b/tests/service/driver/hal_uart/Test_ez_hal_uart.c deleted file mode 100755 index 8d95ad0e..00000000 --- a/tests/service/driver/hal_uart/Test_ez_hal_uart.c +++ /dev/null @@ -1,281 +0,0 @@ - -/******************************************************************************* -* Filename: ez_hal_uart.c -* Author: Hai Nguyen -* Original Date: 25.06.2023 -* Last Update: 25.06.2023 -* -* ----------------------------------------------------------------------------- -* Company: Embedded Easy -* Address Line 1 -* Address Line 2 -* -* ----------------------------------------------------------------------------- -* Contact: Embedded Easy -* hainguyen.ezm@gmail.com -* -* ----------------------------------------------------------------------------- -* Copyright Hai Nguyen - All Rights Reserved -* Unauthorized copying of this file, via any medium is strictly prohibited -* Proprietary and confidential -* Written by Hai Nguyen 25.06.2023 -* -*******************************************************************************/ - -/** @file ez_hal_uart.c - * @author Hai Nguyen - * @date 25.06.2023 - * @brief This is the source for a module - * - * @details - * - */ - -/****************************************************************************** -* Includes -*******************************************************************************/ -#include -#include -#include "unity.h" -#include "unity_fixture.h" -#include "service/driver/hal/hal_uart/ez_hal_uart.h" -#include "service/driver/hal/hal_uart/ez_target_uart_def.h" - -TEST_GROUP(ez_hal_uart); - - -/****************************************************************************** -* Module Preprocessor Macros -*******************************************************************************/ -/* None */ - -/****************************************************************************** -* Module Typedefs -*******************************************************************************/ -/* None */ - -/****************************************************************************** -* Module Variable Definitions -*******************************************************************************/ -static ezDriverHandle_t driver1; -static ezDriverHandle_t driver2; - -/****************************************************************************** -* Function Definitions -*******************************************************************************/ -static void ezHalUart_TestCallback1(uint8_t cb_code, - void *param1, - void *param2) -{ -} - - -static void ezHalUart_TestCallback2(uint8_t cb_code, - void *param1, - void *param2) -{ -} - - -TEST_SETUP(ez_hal_uart) -{ - ezHalUart_Initialize(); -} - - -TEST_TEAR_DOWN(ez_hal_uart) -{ - ezHalUart_Deinitialize(); -} - - -TEST(ez_hal_uart, ezHalUart_GetDriver_Correct) -{ - ezDriverStatus_t status = EZ_DRIVER_ERR_NO_DRIVER; - status = ezHalUart_GetDriver(UART1_NAME, &driver1, ezHalUart_TestCallback1); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); -} - - -TEST(ez_hal_uart, ezHalUart_GetDriver_Incorrect) -{ - ezDriverStatus_t status = EZ_DRIVER_OK; - status = ezHalUart_GetDriver("", &driver1, ezHalUart_TestCallback1); - TEST_ASSERT_EQUAL(EZ_DRIVER_ERR_NO_DRIVER, status); - - status = EZ_DRIVER_OK; - status = ezHalUart_GetDriver("Test Wrong Name", &driver1, ezHalUart_TestCallback1); - TEST_ASSERT_EQUAL(EZ_DRIVER_ERR_NO_DRIVER, status); -} - - -TEST(ez_hal_uart, ezHalUart_Write_Without_Get_Driver) -{ - uint32_t num_byte_written = 0; - uint8_t test_written_buff[128] = { 0xca }; - - num_byte_written = ezHalUart_WriteBlocking(&driver1, test_written_buff, 128); - TEST_ASSERT_EQUAL(0, num_byte_written); -} - - -TEST(ez_hal_uart, ezHalUart_ReleaseDriver) -{ - ezDriverStatus_t status = EZ_DRIVER_ERR_GENERIC; - uint32_t num_byte_written = 0; - uint8_t test_written_buff[128] = { 0xca }; - - status = ezHalUart_GetDriver(UART1_NAME, &driver1, ezHalUart_TestCallback1); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - status = EZ_DRIVER_ERR_GENERIC; - status = ezHalUart_ReleaseDriver(&driver1); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - num_byte_written = ezHalUart_WriteBlocking(&driver1, test_written_buff, 128); - TEST_ASSERT_EQUAL(0, num_byte_written); -} - - -TEST(ez_hal_uart, UsingUnsupportedAPI) -{ - ezDriverStatus_t status = EZ_DRIVER_ERR_GENERIC; - uint32_t num_byte_written = 0; - uint32_t num_byte_read = 0; - - uint8_t test_written_buff[128] = { 0xca }; - uint8_t test_read_buff[128] = { 0xff }; - - memset(test_written_buff, 0xca, 128); - memset(test_read_buff, 0xff, 128); - - status = ezHalUart_GetDriver(UART1_NAME, &driver1, ezHalUart_TestCallback1); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - - num_byte_written = ezHalUart_Write(&driver1, test_written_buff, 128); - TEST_ASSERT_EQUAL(0, num_byte_written); - - num_byte_read = ezHalUart_Read(&driver1, test_read_buff, 128); - TEST_ASSERT_EQUAL(0, num_byte_read); -} - -TEST(ez_hal_uart, ezHalUart_Write) -{ - ezDriverStatus_t status = EZ_DRIVER_ERR_GENERIC; - uint32_t num_byte_written = 0; - uint32_t num_byte_read = 0; - - uint8_t test_written_buff[128] = { 0xca }; - uint8_t test_read_buff[128] = { 0xff }; - - memset(test_written_buff, 0xca, 128); - memset(test_read_buff, 0xff, 128); - - status = ezHalUart_GetDriver(UART0_NAME, &driver1, ezHalUart_TestCallback1); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - status = ezHalUart_GetDriver(UART1_NAME, &driver2, ezHalUart_TestCallback2); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - num_byte_written = ezHalUart_WriteBlocking(&driver1, test_written_buff, 128); - TEST_ASSERT_EQUAL(128, num_byte_written); - - num_byte_read = ezHalUart_ReadBlocking(&driver2, test_read_buff, 128); - TEST_ASSERT_EQUAL(128, num_byte_read); - TEST_ASSERT_EQUAL_HEX8_ARRAY(test_written_buff, test_read_buff, 128); -} - - -TEST(ez_hal_uart, ezHalUart_WriteReadSequencial) -{ - ezDriverStatus_t status = EZ_DRIVER_ERR_GENERIC; - uint32_t num_byte_written = 0; - uint32_t num_byte_read = 0; - - uint8_t test_written_buff1[128] = { 0xca }; - uint8_t test_written_buff2[128] = { 0xca }; - uint8_t test_written_buff3[128] = { 0xca }; - uint8_t test_read_buff[128] = { 0xff }; - - memset(test_written_buff1, 0xca, 128); - memset(test_written_buff2, 0xbe, 128); - memset(test_written_buff3, 0xde, 128); - - status = ezHalUart_GetDriver(UART0_NAME, &driver1, ezHalUart_TestCallback1); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - status = ezHalUart_GetDriver(UART1_NAME, &driver2, ezHalUart_TestCallback2); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - /* first sequence */ - num_byte_written = ezHalUart_WriteBlocking(&driver1, test_written_buff1, 128); - TEST_ASSERT_EQUAL(128, num_byte_written); - - memset(test_read_buff, 0xff, 128); - num_byte_read = ezHalUart_ReadBlocking(&driver2, test_read_buff, 128); - TEST_ASSERT_EQUAL(128, num_byte_read); - TEST_ASSERT_EQUAL_HEX8_ARRAY(test_written_buff1, test_read_buff, 128); - - /* second sequence */ - num_byte_written = ezHalUart_WriteBlocking(&driver1, test_written_buff2, 128); - TEST_ASSERT_EQUAL(128, num_byte_written); - - memset(test_read_buff, 0xff, 128); - num_byte_read = ezHalUart_ReadBlocking(&driver2, test_read_buff, 128); - TEST_ASSERT_EQUAL(128, num_byte_read); - TEST_ASSERT_EQUAL_HEX8_ARRAY(test_written_buff2, test_read_buff, 128); - - /* third sequence */ - num_byte_written = ezHalUart_WriteBlocking(&driver1, test_written_buff3, 128); - TEST_ASSERT_EQUAL(128, num_byte_written); - - memset(test_read_buff, 0xff, 128); - num_byte_read = ezHalUart_ReadBlocking(&driver2, test_read_buff, 128); - TEST_ASSERT_EQUAL(128, num_byte_read); - TEST_ASSERT_EQUAL_HEX8_ARRAY(test_written_buff3, test_read_buff, 128); -} - - -TEST(ez_hal_uart, ezHalUart_WriteReadBlock) -{ - ezDriverStatus_t status = EZ_DRIVER_ERR_GENERIC; - uint32_t num_byte_written = 0; - uint32_t num_byte_read = 0; - - uint8_t test_written_buff1[128] = { 0xca }; - uint8_t test_written_buff2[128] = { 0xca }; - uint8_t test_written_buff3[128] = { 0xca }; - uint8_t test_read_buff[128 * 3] = { 0xff }; - - memset(test_written_buff1, 0xca, 128); - memset(test_written_buff2, 0xbe, 128); - memset(test_written_buff3, 0xde, 128); - - status = ezHalUart_GetDriver(UART0_NAME, &driver1, ezHalUart_TestCallback1); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - status = ezHalUart_GetDriver(UART1_NAME, &driver2, ezHalUart_TestCallback2); - TEST_ASSERT_EQUAL(EZ_DRIVER_OK, status); - - /* first sequence */ - num_byte_written = ezHalUart_WriteBlocking(&driver1, test_written_buff1, 128); - TEST_ASSERT_EQUAL(128, num_byte_written); - - num_byte_written = ezHalUart_WriteBlocking(&driver1, test_written_buff2, 128); - TEST_ASSERT_EQUAL(128, num_byte_written); - - num_byte_written = ezHalUart_WriteBlocking(&driver1, test_written_buff3, 128); - TEST_ASSERT_EQUAL(128, num_byte_written); - - - memset(test_read_buff, 0xff, 128 * 3); - num_byte_read = ezHalUart_ReadBlocking(&driver2, test_read_buff, 128 * 3); - TEST_ASSERT_EQUAL(128 * 3, num_byte_read); - TEST_ASSERT_EQUAL_HEX8_ARRAY(test_written_buff1, test_read_buff, 128); - TEST_ASSERT_EQUAL_HEX8_ARRAY(test_written_buff2, &test_read_buff[128], 128); - TEST_ASSERT_EQUAL_HEX8_ARRAY(test_written_buff3, &test_read_buff[256], 128); -} - -/* End of file */ - diff --git a/tests/service/driver/hal_uart/Test_ez_hal_uart_Runner.c b/tests/service/driver/hal_uart/Test_ez_hal_uart_Runner.c deleted file mode 100755 index 04fe168e..00000000 --- a/tests/service/driver/hal_uart/Test_ez_hal_uart_Runner.c +++ /dev/null @@ -1,86 +0,0 @@ - -/******************************************************************************* -* Filename: ez_hal_uart_runner.c -* Author: Hai Nguyen -* Original Date: 25.06.2023 -* Last Update: 25.06.2023 -* -* ----------------------------------------------------------------------------- -* Company: Embedded Easy -* Address Line 1 -* Address Line 2 -* -* ----------------------------------------------------------------------------- -* Contact: Embedded Easy -* hainguyen.ezm@gmail.com -* -* ----------------------------------------------------------------------------- -* Copyright Hai Nguyen - All Rights Reserved -* Unauthorized copying of this file, via any medium is strictly prohibited -* Proprietary and confidential -* Written by Hai Nguyen 25.06.2023 -* -*******************************************************************************/ - -/** @file ez_hal_uart_runner.c - * @author Hai Nguyen - * @date 25.06.2023 - * @brief This is the source for a module - * - * @details - * - */ - -/****************************************************************************** -* Includes -*******************************************************************************/ -#include -#include - -#include "unity.h" -#include "unity_fixture.h" - -/****************************************************************************** -* Module Preprocessor Macros -*******************************************************************************/ -/* None */ - -/****************************************************************************** -* Module Typedefs -*******************************************************************************/ -/* None */ - -/****************************************************************************** -* Module Variable Definitions -*******************************************************************************/ -/* None */ - -/****************************************************************************** -* Function Definitions -*******************************************************************************/ -/* None */ - -/****************************************************************************** -* External functions -*******************************************************************************/ -/* None */ - - -/****************************************************************************** -* Internal functions -*******************************************************************************/ -TEST_GROUP_RUNNER(ez_hal_uart) -{ - RUN_TEST_CASE(ez_hal_uart, ezHalUart_GetDriver_Correct); - RUN_TEST_CASE(ez_hal_uart, ezHalUart_GetDriver_Incorrect); - RUN_TEST_CASE(ez_hal_uart, ezHalUart_Write_Without_Get_Driver); - RUN_TEST_CASE(ez_hal_uart, ezHalUart_ReleaseDriver); - RUN_TEST_CASE(ez_hal_uart, UsingUnsupportedAPI); - RUN_TEST_CASE(ez_hal_uart, ezHalUart_Write); - RUN_TEST_CASE(ez_hal_uart, ezHalUart_WriteReadSequencial); - RUN_TEST_CASE(ez_hal_uart, ezHalUart_WriteReadBlock); -} - - -/* End of file */ - diff --git a/tests/service/driver/uart/unittest_ez_uart.c b/tests/service/driver/uart/unittest_ez_uart.c deleted file mode 100644 index c88c7d7d..00000000 --- a/tests/service/driver/uart/unittest_ez_uart.c +++ /dev/null @@ -1,592 +0,0 @@ -/***************************************************************************** -* Filename: unittest_ez_uart.c -* Author: Hai Nguyen -* Original Date: 15.03.2024 -* -* ---------------------------------------------------------------------------- -* Contact: Hai Nguyen -* hainguyen.eeit@gmail.com -* -* ---------------------------------------------------------------------------- -* License: This file is published under the license described in LICENSE.md -* -*****************************************************************************/ - -/** @file unittest_ez_uart.c - * @author Hai Nguyen - * @date 15.03.2024 - * @brief One line description of the component - * - * @details Detail description of the component - * - */ - -/****************************************************************************** -* Includes -*******************************************************************************/ -#include -#include -#include -#include "unity.h" -#include "unity_fixture.h" -#include "ez_uart.h" -#include "ez_driver_def.h" - -TEST_GROUP(ez_uart); - -/****************************************************************************** -* Module Preprocessor Macros -*******************************************************************************/ -#define DRV_NAME "MOCK DRIVER" -#define PORT_NAME "COM1" - -/****************************************************************************** -* Module Typedefs -*******************************************************************************/ -/* None */ - -/****************************************************************************** -* Module Variable Definitions -*******************************************************************************/ -static struct ezUartDriver mock_hw; -static ezUartDrvInstance_t first_inst; -static ezUartDrvInstance_t second_inst; -static EZ_UART_EVENT uart_event = UART_NUM_EVENTS; - -/****************************************************************************** -* Function Definitions -*******************************************************************************/ -static void RunAllTests(void); -static EZ_DRV_STATUS ezMockUart_Initialize(uint8_t index); -static EZ_DRV_STATUS ezMockUart_Deinitialize(uint8_t index); -static EZ_DRV_STATUS ezMockUart_AsyncTransmit(uint8_t index, const uint8_t *tx_buff, uint16_t buff_size); -static EZ_DRV_STATUS ezMockUart_AsyncReceive(uint8_t index, uint8_t *rx_buff, uint16_t buff_size); -static EZ_DRV_STATUS ezMockUart_SyncTransmit(uint8_t index, const uint8_t *tx_buff, uint16_t buff_size, uint32_t timeout_millis); -static EZ_DRV_STATUS ezMockUart_SyncReceive(uint8_t index, uint8_t *rx_buff, uint16_t buff_size, uint32_t timeout_millis); -static EZ_DRV_STATUS ezMockUart_UpdateConfig(uint8_t index); -static void ezMockUart_SetImplementedInterface(struct ezHwUartInterface *interface); -static void ezMockUart_Callback(uint8_t event_code, void *param1, void *param2); - - -/****************************************************************************** -* External functions -*******************************************************************************/ -int main(int argc, const char *argv[]) -{ - return UnityMain(argc, argv, RunAllTests); -} - - -TEST_SETUP(ez_uart) -{ - EZ_DRV_STATUS status = STATUS_ERR_GENERIC; - uart_event = UART_NUM_EVENTS; - mock_hw.common.version[0] = 1; - mock_hw.common.version[1] = 2; - mock_hw.common.version[2] = 3; - mock_hw.common.name = DRV_NAME; - mock_hw.config.baudrate = 115200; - mock_hw.config.byte_size = 8; - mock_hw.config.parity = PARITY_ODD; - mock_hw.config.port_name = PORT_NAME; - mock_hw.config.stop_bit = ONE_BIT; - - status = ezUart_SystemRegisterHwDriver(&mock_hw); - TEST_ASSERT_EQUAL(STATUS_OK, status); -} - - -TEST_TEAR_DOWN(ez_uart) -{ - EZ_DRV_STATUS status = STATUS_ERR_GENERIC; - - status = ezUart_UnregisterInstance(&first_inst); - TEST_ASSERT_EQUAL(STATUS_OK, status); - - status = ezUart_UnregisterInstance(&second_inst); - TEST_ASSERT_EQUAL(STATUS_OK, status); - - status = ezUart_SystemUnregisterHwDriver(&mock_hw); - TEST_ASSERT_EQUAL(STATUS_OK, status); - - memset(&mock_hw, 0, sizeof(mock_hw)); -} - - -TEST_GROUP_RUNNER(ez_uart) -{ - RUN_TEST_CASE(ez_uart, ezUart_SystemRegisterHwDriver); - RUN_TEST_CASE(ez_uart, ezUart_SystemUnregisterHwDriver); - RUN_TEST_CASE(ez_uart, ezUart_RegisterInstance); - RUN_TEST_CASE(ez_uart, ezUart_UnregisterInstance); - RUN_TEST_CASE(ez_uart, ezUart_Initialize); - RUN_TEST_CASE(ez_uart, ezUart_Deinitialize); - RUN_TEST_CASE(ez_uart, ezUart_AsyncTransmit); - RUN_TEST_CASE(ez_uart, ezUart_AsyncReceive); - RUN_TEST_CASE(ez_uart, ezUart_SyncTransmit); - RUN_TEST_CASE(ez_uart, ezUart_SyncReceive); - RUN_TEST_CASE(ez_uart, ezUart_GetConfig); - RUN_TEST_CASE(ez_uart, ezUart_UpdateConfig); -} - - -TEST(ez_uart, ezUart_SystemRegisterHwDriver) -{ - EZ_DRV_STATUS status = STATUS_ERR_GENERIC; - - TEST_MESSAGE("Test NULL argument"); - status = ezUart_SystemRegisterHwDriver(NULL); - TEST_ASSERT_EQUAL(STATUS_ERR_ARG, status); -} - - -TEST(ez_uart, ezUart_SystemUnregisterHwDriver) -{ - EZ_DRV_STATUS status = STATUS_ERR_GENERIC; - - TEST_MESSAGE("Test NULL argument"); - status = ezUart_SystemUnregisterHwDriver(NULL); - TEST_ASSERT_EQUAL(STATUS_ERR_ARG, status); -} - - -TEST(ez_uart, ezUart_RegisterInstance) -{ - EZ_DRV_STATUS status = STATUS_ERR_GENERIC; - - TEST_MESSAGE("Test null pointer"); - status = ezUart_RegisterInstance(NULL, NULL, ezMockUart_Callback); - TEST_ASSERT_EQUAL(STATUS_ERR_ARG, status); - - TEST_MESSAGE("Test driver does not exist"); - status = ezUart_RegisterInstance(&first_inst, "Random driver name", ezMockUart_Callback); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - TEST_MESSAGE("Test happy path"); - status = ezUart_RegisterInstance(&first_inst, DRV_NAME, ezMockUart_Callback); - TEST_ASSERT_EQUAL(STATUS_OK, status); - TEST_ASSERT_NOT_EQUAL(NULL, first_inst.driver); -} - - -TEST(ez_uart, ezUart_UnregisterInstance) -{ - EZ_DRV_STATUS status = STATUS_ERR_GENERIC; - - TEST_MESSAGE("Test null pointer"); - status = ezUart_UnregisterInstance(NULL); - TEST_ASSERT_EQUAL(STATUS_ERR_ARG, status); - - TEST_MESSAGE("Test happy path"); - status = ezUart_UnregisterInstance(&first_inst); - TEST_ASSERT_EQUAL(STATUS_OK, status); - TEST_ASSERT_EQUAL(NULL, first_inst.driver); -} - - -TEST(ez_uart, ezUart_Initialize) -{ - EZ_DRV_STATUS status = STATUS_ERR_GENERIC; - - TEST_MESSAGE("Test null pointer"); - status = ezUart_Initialize(NULL); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - TEST_MESSAGE("Test unregistered instance"); - status = ezUart_Initialize(&second_inst); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - /* Now we register the instance */ - status = ezUart_RegisterInstance(&first_inst, DRV_NAME, ezMockUart_Callback); - status = ezUart_RegisterInstance(&second_inst, DRV_NAME, ezMockUart_Callback); - - TEST_MESSAGE("Test unimplmented interface "); - status = ezUart_Initialize(&first_inst); - TEST_ASSERT_EQUAL(STATUS_ERR_INF_NOT_EXIST, status); - - TEST_MESSAGE("Test interface is locked"); - /* manually set lock */ - mock_hw.common.curr_inst = &first_inst; - status = ezUart_Initialize(&second_inst); - TEST_ASSERT_EQUAL(STATUS_BUSY, status); - /* release the lock */ - mock_hw.common.curr_inst = NULL; - - TEST_MESSAGE("Test happy path"); - ezMockUart_SetImplementedInterface(&mock_hw.interface); - status = ezUart_Initialize(&first_inst); - TEST_ASSERT_EQUAL(STATUS_OK, status); -} - - -TEST(ez_uart, ezUart_Deinitialize) -{ - EZ_DRV_STATUS status = STATUS_ERR_GENERIC; - - TEST_MESSAGE("Test null pointer"); - status = ezUart_Deinitialize(NULL); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - TEST_MESSAGE("Test unregistered instance"); - status = ezUart_Deinitialize(&second_inst); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - /* Now we register the instance */ - status = ezUart_RegisterInstance(&first_inst, DRV_NAME, ezMockUart_Callback); - status = ezUart_RegisterInstance(&second_inst, DRV_NAME, ezMockUart_Callback); - - TEST_MESSAGE("Test unimplmented interface "); - status = ezUart_Deinitialize(&first_inst); - TEST_ASSERT_EQUAL(STATUS_ERR_INF_NOT_EXIST, status); - - TEST_MESSAGE("Test interface is locked"); - /* manually set lock */ - mock_hw.common.curr_inst = &first_inst; - status = ezUart_Deinitialize(&second_inst); - TEST_ASSERT_EQUAL(STATUS_BUSY, status); - /* release the lock */ - mock_hw.common.curr_inst = NULL; - - TEST_MESSAGE("Test happy path"); - ezMockUart_SetImplementedInterface(&mock_hw.interface); - status = ezUart_Deinitialize(&first_inst); - TEST_ASSERT_EQUAL(STATUS_OK, status); -} - - -TEST(ez_uart, ezUart_AsyncTransmit) -{ - EZ_DRV_STATUS status = STATUS_ERR_GENERIC; - uint8_t tx_buff[] = {0xde, 0xad, 0xca, 0xfe}; - - TEST_MESSAGE("Test null pointer"); - status = ezUart_AsyncTransmit(NULL, tx_buff, sizeof(tx_buff)); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - TEST_MESSAGE("Test unregistered instance"); - status = ezUart_AsyncTransmit(&second_inst, tx_buff, sizeof(tx_buff)); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - /* Now we register the instance */ - status = ezUart_RegisterInstance(&first_inst, DRV_NAME, ezMockUart_Callback); - status = ezUart_RegisterInstance(&second_inst, DRV_NAME, ezMockUart_Callback); - - TEST_MESSAGE("Test unimplmented interface "); - status = ezUart_AsyncTransmit(&first_inst, tx_buff, sizeof(tx_buff)); - TEST_ASSERT_EQUAL(STATUS_ERR_INF_NOT_EXIST, status); - - TEST_MESSAGE("Test interface is locked"); - /* manually set lock */ - mock_hw.common.curr_inst = &first_inst; - status = ezUart_AsyncTransmit(&second_inst, tx_buff, sizeof(tx_buff)); - TEST_ASSERT_EQUAL(STATUS_BUSY, status); - /* release the lock */ - mock_hw.common.curr_inst = NULL; - - TEST_MESSAGE("Test happy path"); - ezMockUart_SetImplementedInterface(&mock_hw.interface); - status = ezUart_AsyncTransmit(&first_inst, tx_buff, sizeof(tx_buff)); - TEST_ASSERT_EQUAL(STATUS_OK, status); - TEST_ASSERT_EQUAL(NULL, mock_hw.common.curr_inst); - TEST_ASSERT_EQUAL(UART_EVENT_TX_CMPLT, uart_event); -} - - -TEST(ez_uart, ezUart_AsyncReceive) -{ - EZ_DRV_STATUS status = STATUS_ERR_GENERIC; - uint8_t rx_buff[4]; - - TEST_MESSAGE("Test null pointer"); - status = ezUart_AsyncReceive(NULL, rx_buff, sizeof(rx_buff)); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - TEST_MESSAGE("Test unregistered instance"); - status = ezUart_AsyncReceive(&second_inst, rx_buff, sizeof(rx_buff)); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - /* Now we register the instance */ - status = ezUart_RegisterInstance(&first_inst, DRV_NAME, ezMockUart_Callback); - status = ezUart_RegisterInstance(&second_inst, DRV_NAME, ezMockUart_Callback); - - TEST_MESSAGE("Test unimplmented interface "); - status = ezUart_AsyncReceive(&first_inst, rx_buff, sizeof(rx_buff)); - TEST_ASSERT_EQUAL(STATUS_ERR_INF_NOT_EXIST, status); - - TEST_MESSAGE("Test interface is locked"); - /* manually set lock */ - mock_hw.common.curr_inst = &first_inst; - status = ezUart_AsyncReceive(&second_inst, rx_buff, sizeof(rx_buff)); - TEST_ASSERT_EQUAL(STATUS_BUSY, status); - /* release the lock */ - mock_hw.common.curr_inst = NULL; - - TEST_MESSAGE("Test happy path"); - ezMockUart_SetImplementedInterface(&mock_hw.interface); - status = ezUart_AsyncReceive(&first_inst, rx_buff, sizeof(rx_buff)); - TEST_ASSERT_EQUAL(STATUS_OK, status); - TEST_ASSERT_EQUAL(NULL, mock_hw.common.curr_inst); - TEST_ASSERT_EQUAL(UART_EVENT_RX_CMPLT, uart_event); -} - - -TEST(ez_uart, ezUart_SyncTransmit) -{ - EZ_DRV_STATUS status = STATUS_ERR_GENERIC; - uint8_t tx_buff[] = {0xde, 0xad, 0xca, 0xfe}; - - TEST_MESSAGE("Test null pointer"); - status = ezUart_SyncTransmit(NULL, tx_buff, sizeof(tx_buff), 1000); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - TEST_MESSAGE("Test unregistered instance"); - status = ezUart_SyncTransmit(&second_inst, tx_buff, sizeof(tx_buff), 1000); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - /* Now we register the instance */ - status = ezUart_RegisterInstance(&first_inst, DRV_NAME, ezMockUart_Callback); - status = ezUart_RegisterInstance(&second_inst, DRV_NAME, ezMockUart_Callback); - - TEST_MESSAGE("Test unimplmented interface "); - status = ezUart_SyncTransmit(&first_inst, tx_buff, sizeof(tx_buff), 1000); - TEST_ASSERT_EQUAL(STATUS_ERR_INF_NOT_EXIST, status); - - TEST_MESSAGE("Test interface is locked"); - /* manually set lock */ - mock_hw.common.curr_inst = &first_inst; - status = ezUart_SyncTransmit(&second_inst, tx_buff, sizeof(tx_buff), 1000); - TEST_ASSERT_EQUAL(STATUS_BUSY, status); - /* release the lock */ - mock_hw.common.curr_inst = NULL; - - TEST_MESSAGE("Test happy path"); - ezMockUart_SetImplementedInterface(&mock_hw.interface); - status = ezUart_SyncTransmit(&first_inst, tx_buff, sizeof(tx_buff), 1000); - TEST_ASSERT_EQUAL(STATUS_OK, status); - TEST_ASSERT_EQUAL(NULL, mock_hw.common.curr_inst); - TEST_ASSERT_EQUAL(UART_NUM_EVENTS, uart_event); -} - - -TEST(ez_uart, ezUart_SyncReceive) -{ - EZ_DRV_STATUS status = STATUS_ERR_GENERIC; - uint8_t rx_buff[4]; - - TEST_MESSAGE("Test null pointer"); - status = ezUart_SyncReceive(NULL, rx_buff, sizeof(rx_buff), 1000); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - TEST_MESSAGE("Test unregistered instance"); - status = ezUart_SyncReceive(&second_inst, rx_buff, sizeof(rx_buff), 1000); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - /* Now we register the instance */ - status = ezUart_RegisterInstance(&first_inst, DRV_NAME, ezMockUart_Callback); - status = ezUart_RegisterInstance(&second_inst, DRV_NAME, ezMockUart_Callback); - - TEST_MESSAGE("Test unimplmented interface "); - status = ezUart_SyncReceive(&first_inst, rx_buff, sizeof(rx_buff), 1000); - TEST_ASSERT_EQUAL(STATUS_ERR_INF_NOT_EXIST, status); - - TEST_MESSAGE("Test interface is locked"); - /* manually set lock */ - mock_hw.common.curr_inst = &first_inst; - status = ezUart_SyncReceive(&second_inst, rx_buff, sizeof(rx_buff), 1000); - TEST_ASSERT_EQUAL(STATUS_BUSY, status); - /* release the lock */ - mock_hw.common.curr_inst = NULL; - - TEST_MESSAGE("Test happy path"); - ezMockUart_SetImplementedInterface(&mock_hw.interface); - status = ezUart_SyncReceive(&first_inst, rx_buff, sizeof(rx_buff), 1000); - TEST_ASSERT_EQUAL(STATUS_OK, status); - TEST_ASSERT_EQUAL(NULL, mock_hw.common.curr_inst); - TEST_ASSERT_EQUAL(UART_NUM_EVENTS, uart_event); -} - - -TEST(ez_uart, ezUart_GetConfig) -{ - EZ_DRV_STATUS status = STATUS_ERR_GENERIC; - struct ezUartConfiguration *config = NULL; - - TEST_MESSAGE("Test null pointer"); - status = ezUart_GetConfig(NULL, &config); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - TEST_MESSAGE("Test unregistered instance"); - status = ezUart_GetConfig(&second_inst, &config); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - /* Now we register the instance */ - status = ezUart_RegisterInstance(&first_inst, DRV_NAME, ezMockUart_Callback); - status = ezUart_RegisterInstance(&second_inst, DRV_NAME, ezMockUart_Callback); - - TEST_MESSAGE("Test null pointer "); - status = ezUart_GetConfig(&first_inst, NULL); - TEST_ASSERT_EQUAL(STATUS_ERR_ARG, status); - - TEST_MESSAGE("Test interface is locked"); - /* manually set lock */ - mock_hw.common.curr_inst = &first_inst; - status = ezUart_GetConfig(&second_inst, &config); - TEST_ASSERT_EQUAL(STATUS_BUSY, status); - /* release the lock */ - mock_hw.common.curr_inst = NULL; - - TEST_MESSAGE("Test happy path"); - ezMockUart_SetImplementedInterface(&mock_hw.interface); - status = ezUart_GetConfig(&first_inst, &config); - TEST_ASSERT_EQUAL(STATUS_OK, status); - TEST_ASSERT_EQUAL(&mock_hw.config, config); -} - - -TEST(ez_uart, ezUart_UpdateConfig) -{ - EZ_DRV_STATUS status = STATUS_ERR_GENERIC; - struct ezUartConfiguration *config = NULL; - - TEST_MESSAGE("Test null pointer"); - status = ezUart_UpdateConfig(NULL); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - TEST_MESSAGE("Test unregistered instance"); - status = ezUart_UpdateConfig(&second_inst); - TEST_ASSERT_EQUAL(STATUS_ERR_DRV_NOT_FOUND, status); - - /* Now we register the instance */ - status = ezUart_RegisterInstance(&first_inst, DRV_NAME, ezMockUart_Callback); - status = ezUart_RegisterInstance(&second_inst, DRV_NAME, ezMockUart_Callback); - - TEST_MESSAGE("Test interface is locked"); - /* manually set lock */ - mock_hw.common.curr_inst = &first_inst; - status = ezUart_UpdateConfig(&second_inst); - TEST_ASSERT_EQUAL(STATUS_BUSY, status); - /* release the lock */ - mock_hw.common.curr_inst = NULL; - - TEST_MESSAGE("Test happy path"); - ezMockUart_SetImplementedInterface(&mock_hw.interface); - status = ezUart_GetConfig(&first_inst, &config); - TEST_ASSERT_EQUAL(STATUS_OK, status); - TEST_ASSERT_EQUAL(&mock_hw.config, config); - - config->baudrate = 9600; - config->stop_bit = TWO_BITS; - - status = ezUart_UpdateConfig(&first_inst); - TEST_ASSERT_EQUAL(STATUS_OK, status); - TEST_ASSERT_EQUAL_MEMORY(&mock_hw.config, config, sizeof(mock_hw.config)); -} - - - -/****************************************************************************** -* Internal functions -*******************************************************************************/ -static void RunAllTests(void) -{ - RUN_TEST_GROUP(ez_uart); -} - -static EZ_DRV_STATUS ezMockUart_Initialize(uint8_t index) -{ - (void)index; - return STATUS_OK; -} - - -static EZ_DRV_STATUS ezMockUart_Deinitialize(uint8_t index) -{ - (void)index; - return STATUS_OK; -} - - -static EZ_DRV_STATUS ezMockUart_AsyncTransmit(uint8_t index, const uint8_t *tx_buff, uint16_t buff_size) -{ - (void)index; - (void)tx_buff; - (void)buff_size; - if(mock_hw.common.curr_inst != NULL && mock_hw.common.curr_inst->calback != NULL) - { - mock_hw.common.curr_inst->calback(UART_EVENT_TX_CMPLT, NULL, NULL); - } - - /* Job done, unlock driver */ - mock_hw.common.curr_inst = NULL; - return STATUS_OK; -} - - -static EZ_DRV_STATUS ezMockUart_AsyncReceive(uint8_t index, uint8_t *rx_buff, uint16_t buff_size) -{ - (void)index; - (void)rx_buff; - (void)buff_size; - /* In reality, the HW driver declare the ezUartDriver, so it has access to this struct */ - if(mock_hw.common.curr_inst != NULL && mock_hw.common.curr_inst->calback != NULL) - { - mock_hw.common.curr_inst->calback(UART_EVENT_RX_CMPLT, NULL, NULL); - } - - /* Job done, unlock driver */ - mock_hw.common.curr_inst = NULL; - return STATUS_OK; -} - - -static EZ_DRV_STATUS ezMockUart_SyncTransmit(uint8_t index, const uint8_t *tx_buff, uint16_t buff_size, uint32_t timeout_millis) -{ - (void)index; - (void)tx_buff; - (void)buff_size; - (void)timeout_millis; - return STATUS_OK; -} - - -static EZ_DRV_STATUS ezMockUart_SyncReceive(uint8_t index, uint8_t *rx_buff, uint16_t buff_size, uint32_t timeout_millis) -{ - (void)index; - (void)rx_buff; - (void)buff_size; - (void)timeout_millis; - return STATUS_OK; -} - - -static EZ_DRV_STATUS ezMockUart_UpdateConfig(uint8_t index) -{ - (void)index; - return STATUS_OK; -} - - -static void ezMockUart_SetImplementedInterface(struct ezHwUartInterface *interface) -{ - if(interface != NULL) - { - interface->index = 0; - interface->async_receive = ezMockUart_AsyncReceive; - interface->async_transmit = ezMockUart_AsyncTransmit; - interface->deinitialize = ezMockUart_Deinitialize; - interface->initialize = ezMockUart_Initialize; - interface->sync_receive = ezMockUart_SyncReceive; - interface->sync_transmit = ezMockUart_SyncTransmit; - interface->update_conf = ezMockUart_UpdateConfig; - } -} - -static void ezMockUart_Callback(uint8_t event_code, void *param1, void *param2) -{ - (void)param1; - (void)param2; - uart_event = (EZ_UART_EVENT)event_code; -} - - -/* End of file */