diff --git a/os/hal/ports/AVR/XMEGA/LLD/CRCv1/hal_crc_lld.c b/os/hal/ports/AVR/XMEGA/LLD/CRCv1/hal_crc_lld.c new file mode 100644 index 000000000..7159d348e --- /dev/null +++ b/os/hal/ports/AVR/XMEGA/LLD/CRCv1/hal_crc_lld.c @@ -0,0 +1,332 @@ +/* + ChibiOS - Copyright (C) 2006..2022 Theodore Ateba + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file CRCv1/hal_crc_lld.c + * @brief XMEGA CRC subsystem low level driver source. + * + * @addtogroup CRC + * @{ + */ + +#include "hal.h" + +/* Include CRC low level driver header directly for XMEGA specific driver. */ +#include "hal_crc_lld.h" + +#if HAL_USE_CRC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief CRC1 driver identifier. */ +#if AVR_CRC_USE_CRC1 || defined(__DOXYGEN__) +CRCDriver CRCD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Enable the CRC module. + * + * @param[in] crcp pointer to the @p CRCDriver object. + */ +static void crc_enable(CRCDriver *crcp) { + + switch (crcp->config->source) { + case CRC_SOURCE_IO: + case CRC_SOURCE_FLASH: + case CRC_SOURCE_EDMACH0: + case CRC_SOURCE_EDMACH1: + case CRC_SOURCE_EDMACH2: + crcp->crc->CTRL.bit.SOURCE = crcp->config->source; + break; + default: + break; + } +} + +/** + * @brief Select CRC16 algorithm for crc computation. + * + * @param[in] crcp pointer to the @p CRCDriver object. + */ +static void crc_select_algo_crc16(CRCDriver *crcp) { + + /* Wait the CRC module to be ready. */ + while (crcp->crc->STATUS.bit.BUSY); + + /* Enable CRC16 algorithm. */ + crcp->crc->CTRL.bit.CRC32 = 0; +} + +/** + * @brief Select CRC32 algorithm for crc computation. + * + * @param[in] crcp pointer to the @p CRCDriver object. + */ +static void crc_select_algo_crc32(CRCDriver *crcp) { + + /* Wait the CRC module to be ready. */ + while (crcp->crc->STATUS.bit.BUSY); + + /* Enable the CRC32 algorithm. */ + crcp->crc->CTRL.bit.CRC32 = 1; +} + +/** + * @brief Reset CRC module. + * + * @param[in] crcp pointer to the @p CRCDriver object. + * @param[in] rt reset type that need to be used to reset the CRC module. + */ +static void crc_reset(CRCDriver *crcp, crcreset_t rt) { + + switch (rt) { + case CRC_RESET_RESET0: + /* Initialize the CRC with all Zeros. */ + crcp->crc->CTRL.bit.RESET = CRC_RESET_RESET0; + break; + + case CRC_RESET_RESET1: + /* Initialize the CRC with all Ones. */ + crcp->crc->CTRL.bit.RESET = CRC_RESET_RESET1; + break; + + case CRC_RESET_NO: + default: + break; + } +} + +/** + * @brief Disabble the CRC module. + * + * @param[in] crcp pointer to the @p CRCDriver object. + */ +static void crc_disable(CRCDriver *crcp) { + + crcp->crc->CTRL.bit.SOURCE = CRC_SOURCE_DISABLE; +} + +/** + * @brief Load the data into the CRC module to perform. + * + * @param[in] crcp pointer to the @p CRCDriver object. + * @param[in] srcp pointer to the data used to compute CRC. + * @parma[in] size lenght of the data used to compute CRC. + */ +static void crc_lld_load_data(CRCDriver *crcp, uint8_t *srcp, size_t size) { + + uint8_t index = 0; + + for (index = 0; index < size; index++) { + crcp->crc->DATAIN.reg = srcp[index]; + } +} + +/** + * @brief Get the checksum value computed with CRC16 algorithm + * + * @param crcp pointer to the @p CRCDriver object. + * @return retVal the value of the CRC16 computed . + */ +static uint16_t crc_get_crc16_checksum(CRCDriver *crcp) { + + crc16_t retVal; + retVal.crc16 = 0; + + retVal.crc8.byte0 = crcp->crc->CHECKSUM0.reg; + retVal.crc8.byte1 = crcp->crc->CHECKSUM1.reg; + + return retVal.crc16; +} + +/** + * @brief Get the checksum value computed with CRC32 algorithm + * + * @param crcp pointer to the @p CRCDriver object. + * @return retVal the value of the CRC32 computed. + */ +static uint32_t crc_get_crc32_checksum(CRCDriver *crcp) { + + crc32_t retVal; + + retVal.crc32 = 0; + + retVal.crc8.byte0 = crcp->crc->CHECKSUM0.reg; + retVal.crc8.byte1 = crcp->crc->CHECKSUM1.reg; + retVal.crc8.byte2 = crcp->crc->CHECKSUM2.reg; + retVal.crc8.byte3 = crcp->crc->CHECKSUM3.reg; + + return retVal.crc32; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the standard part of a @p CRCDriver structure. + * + * @param[out] crcp pointer to the @p CRCDriver object. + * + * @init + */ +void crc_lld_object_init(CRCDriver *crcp) { + + crcp->state = CRC_STOP; + crcp->config = NULL; +} + +/** + * @brief Low level CRC driver initialization. + * + * @notapi + */ +void crc_lld_init(void) { + +#if AVR_CRC_USE_CRC1 + crc_lld_object_init(&CRCD1); + CRCD1.crc = CRC; +#endif +} + +/** + * @brief Configures and activates the CRC peripheral. + * + * @param[in] crcp pointer to the @p CRCDriver object + * + * @notapi + */ +void crc_lld_start(CRCDriver *crcp, CRCConfig *config) { + + /* Copy the config to the CRC driver config. */ + crcp->config = config; + + /* CRC source I/O interface only support CRC16 algorithm. */ + if (crcp->config->source == CRC_SOURCE_IO) { + crc_select_algo_crc16(crcp); + } + + /* CRC source Flash Memory only support CRC32 algorithm. */ + else if (crcp->config->source == CRC_SOURCE_FLASH) { + crc_select_algo_crc32(crcp); + } + + /* CRC source DMA support both CRC16 and CRC32. */ + else { + if (crcp->config->algo == CRC_TYPE_CRC16) { + crc_select_algo_crc16(crcp); + } + else { + crc_select_algo_crc32(crcp); + } + } + + /* Enable the CRC module. */ + crc_enable(crcp); +} + +/** + * @brief Deactivates the CRC peripheral. + * + * @param[in] crcp pointer to the @p CRCDriver object + * + * @notapi + */ +void crc_lld_stop(CRCDriver *crcp) { + + crc_disable(crcp); +} + +/** + * @brief Reset the CRC module with all checksum byte to 0x00. + * + * @param[in] crcp pointer to the @p CRCDriver object. + * @param[in] rt reset type use to initialize the checksum all to zeros or ones. + * + * @notapi + */ +void crc_lld_reset(CRCDriver *crcp, crcreset_t rt) { + + crc_reset(crcp, rt); +} + +/** + * @brief Compute the CRC16 on data IO interface. + * + * @param[in] crcp pointer to the @p CRCDriver object. + * @param[in] srcp pointer of data used to compute CRC16. + * @param[in] size length of data used to compute CRC16. + * @return retVal result of CRC16 operation. + * + * @notapi + */ +uint16_t crc_lld_compute_crc16_on_data(CRCDriver *crcp, uint8_t *srcp, size_t size) { + + uint16_t retVal = 0; + + /* Load data to compute the CRC16. */ + crc_lld_load_data(crcp, srcp, size); + + /* Read the computed CRC result. */ + retVal = crc_get_crc16_checksum(crcp); + + return retVal; +} + +/** + * @brief Compute the CRC32 on data IO interface. + * + * @param[in] crcp pointer to the @p CRCDriver object. + * @param[in] srcp pointer of data used to compute CRC32. + * @param[in] size length of data used to compute CRC32. + * @return retVal result of CRC32 operation. + * + * @notapi + */ +uint32_t crc_lld_compute_crc32_on_data(CRCDriver *crcp, uint8_t *srcp, size_t size) { + + uint32_t retVal = 0; + + /* Load data to compute the CRC32. */ + crc_lld_load_data(crcp, srcp, size); + + /* Read the computed CRC result. */ + retVal = crc_get_crc32_checksum(crcp); + + return retVal; +} + +#endif /* HAL_USE_CRC */ + +/** @} */ diff --git a/os/hal/ports/AVR/XMEGA/LLD/CRCv1/hal_crc_lld.h b/os/hal/ports/AVR/XMEGA/LLD/CRCv1/hal_crc_lld.h new file mode 100644 index 000000000..045a499e4 --- /dev/null +++ b/os/hal/ports/AVR/XMEGA/LLD/CRCv1/hal_crc_lld.h @@ -0,0 +1,181 @@ +/* + ChibiOS - Copyright (C) 2006..2022 Theodore Ateba + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file CRCv1/hal_crc_lld.h + * @brief XMEGA CRC low level driver header. + * + * @addtogroup CRC + * @{ + */ + +#ifndef HAL_CRC_LLD_H +#define HAL_CRC_LLD_H + +#include "xmega_crc.h" + +#if HAL_USE_CRC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief CRC1 driver enable switch. + * @note The default is @p FALSE. + */ +#if !defined(AVR_CRC_USE_CRC1) || defined(__DOXYGEN__) +#define AVR_CRC_USE_CRC1 FALSE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ +/** + * @brief Driver state machine possible states. + */ +typedef enum { + CRC_UNINIT = 0, /**< Not initialized. */ + CRC_STOP, /**< Stopped. */ + CRC_READY /**< Ready. */ +} crcstate_t; + +/** + * @brief CRC available sources. + */ +typedef enum { + CRC_SOURCE_DISABLE = 0, /* CRC disable. */ + CRC_SOURCE_IO = 1, /* I/O interface. */ + CRC_SOURCE_FLASH = 2, /* Flash. */ + CRC_SOURCE_EDMACH0 = 4, /* EDMA controller channel 0. */ + CRC_SOURCE_EDMACH1 = 5, /* EDMA controller channel 1. */ + CRC_SOURCE_EDMACH2 = 6, /* EDMA controller channel 2. */ + CRC_SOURCE_EDMACH3 = 7 /* EDMA controller channel 3. */ +} crcsource_t; + +/** + * @brief Available CRC polynomial algorithme. + */ +typedef enum { + CRC_TYPE_CRC16 = 0, /* CRC 16 = CRC-CCITT. */ + CRC_TYPE_CRC32 /* CRC 32 = IEEE 802.3. */ +} crcalgo_t; + +/** + * @brief CRC available reset method. + */ +typedef enum { + CRC_RESET_NO = 0, /* No reset. */ + CRC_RESET_RESET0 = 2, /* Reset all CRC with checksum to all zeros. */ + CRC_RESET_RESET1 = 3 /* Reset all CRC with checksum to all ones. */ +} crcreset_t; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + crcsource_t source; + crcalgo_t algo; +} CRCConfig; + +/** + * @brief Structure representing an CRC driver. + */ +typedef struct { + /** + * @brief Driver state. + */ + crcstate_t state; + /** + * @brief Current configuration data. + */ + const CRCConfig *config; + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the CRC registers block. + */ + xmega_crc_t *crc; +} CRCDriver; + +/** + * @brief Type used while reading CRC16 result. + */ +typedef union { + uint16_t crc16; + struct { + uint16_t byte0 : 8; + uint16_t byte1 : 8; + } crc8; +} crc16_t; + +/** + * @brief Type used while reading CRC32 result. + */ +typedef union { + uint32_t crc32; + struct { + uint32_t byte0 : 8; + uint32_t byte1 : 8; + uint32_t byte2 : 8; + uint32_t byte3 : 8; + } crc8; +} crc32_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if AVR_CRC_USE_CRC1 && !defined(__DOXYGEN__) +extern CRCDriver CRCD1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void crc_lld_object_init(CRCDriver *crcp); + void crc_lld_init(void); + void crc_lld_start(CRCDriver *crcp, CRCConfig *config); + void crc_lld_stop(CRCDriver *crcp); + void crc_lld_reset(CRCDriver *crcp, crcreset_t rt); + uint16_t crc_lld_compute_crc16_on_data(CRCDriver *crcp, uint8_t *srcp, size_t size); + uint32_t crc_lld_compute_crc32_on_data(CRCDriver *crcp, uint8_t *srcp, size_t size); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_CRC */ + +#endif /* HAL_CRC_LLD_H */ + +/** @} */