Merge pull request #276 from KarlK90/gd32vf103-add-crc

[GD32VF103] Add CRC driver
This commit is contained in:
Fabien Poussin 2021-04-21 22:28:35 +02:00 committed by GitHub
commit d53c82a884
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 578 additions and 18 deletions

View File

@ -55,7 +55,7 @@
#define LINE_GREEN_LED PAL_LINE(GPIOA, PIN_GREEN_LED)
#define LINE_BLUE_LED PAL_LINE(GPIOA, PIN_BLUE_LED)
#define LINE_RED_LED PAL_LINE(GPIOA, PIN_RED_LED)
#define LINE_RED_LED PAL_LINE(GPIOC, PIN_RED_LED)
#define LINE_DISPLAY_MISO PAL_LINE(GPIOA, PIN_DISPLAY_MISO)
#define LINE_DISPLAY_MOSI PAL_LINE(GPIOA, PIN_DISPLAY_MOSI)
@ -113,9 +113,10 @@
/*
* Port C setup.
* Everything input with pull-up except:
* C13 - RED LED - Push Pull output 50MHz
*/
#define VAL_GPIOCCRL 0x88888888 /* PC7...PC0 */
#define VAL_GPIOCCRH 0x88888888 /* PC15...PC8 */
#define VAL_GPIOCCRH 0x88388888 /* PC15...PC8 */
#define VAL_GPIOCODR 0xFFFFFFFF
/*

View File

@ -0,0 +1,11 @@
ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_CRC TRUE,$(HALCONF)),)
PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/GD/GD32VF103/CRC/hal_crc_lld.c \
${CHIBIOS_CONTRIB}/os/various/crcsw.c
endif
else
PLATFORMSRC += ${CHIBIOS_CONTRIB}/os/hal/ports/GD/GD32VF103/CRC/hal_crc_lld.c \
${CHIBIOS_CONTRIB}/os/various/crcsw.c
endif
PLATFORMINC += ${CHIBIOS_CONTRIB}/os/hal/ports/GD/GD32VF103/CRC

View File

@ -0,0 +1,259 @@
/*
ChibiOS - Copyright (C) 2015 Michael D. Spradling
ChibiOS - Copyright (C) 2021 Stefan Kerkmann
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 GD32VF103/CRC/hal_crc_lld.c
* @brief GD32 CRC subsystem low level driver source.
*
* @addtogroup CRC
* @{
*/
#include "hal.h"
#if (HAL_USE_CRC == TRUE) || defined(__DOXYGEN__)
/**
* Allow CRC Software override for ST drivers. Some ST CRC implimentations
* have limited capabilities.
*/
#if CRCSW_USE_CRC1 != TRUE
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/**
* @brief CRC default configuration.
*/
static const CRCConfig default_config = {
.poly_size = 32,
.poly = 0x04C11DB7,
.initial_val = 0xFFFFFFFF,
.final_val = 0xFFFFFFFF,
.reflect_data = 1,
.reflect_remainder = 1
};
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/** @brief CRC1 driver identifier.*/
#if GD32_CRC_USE_CRC0 || defined(__DOXYGEN__)
CRCDriver CRCD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
void _crc_lld_calc_byte(CRCDriver *crcp, uint8_t data) {
__IO uint8_t *crc8 = (__IO uint8_t*)&(crcp->crc->DATA);
*crc8 = data;
}
/*
* @brief Returns calculated CRC from last reset
*
* @param[in] crcp pointer to the @p CRCDriver object
* @param[in] data data to be added to crc
*
* @notapi
*/
void _crc_lld_calc_halfword(CRCDriver *crcp, uint16_t data) {
__IO uint16_t *crc16 = (__IO uint16_t*)&(crcp->crc->DATA);
*crc16 = data;
}
/*
* @brief Returns calculated CRC from last reset
*
* @param[in] crcp pointer to the @p CRCDriver object
* @param[in] data data to be added to crc
*
* @notapi
*/
void _crc_lld_calc_word(CRCDriver *crcp, uint32_t data) {
crcp->crc->DATA = data;
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/**
* @brief Shared end-of-rx service routine.
*
* @param[in] crcp pointer to the @p CRCDriver object
* @param[in] flags pre-shifted content of the ISR register
*/
#if CRC_USE_DMA == TRUE
static void crc_lld_serve_interrupt(CRCDriver *crcp, uint32_t flags) {
/* DMA errors handling.*/
#if defined(GD32_CRC_DMA_ERROR_HOOK)
if ((flags & (GD32_DMA_INTF_ERRIF)) != 0) {
GD32_CRC_DMA_ERROR_HOOK(crcp);
}
#else
(void)flags;
#endif
/* Stop everything.*/
dmaStreamDisable(crcp->dmastp);
if (crcp->rem_data_size) {
/* Start DMA follow up transfer for next data chunk */
crc_lld_start_calc(crcp, crcp->rem_data_size,
(const void *)crcp->dmastp->channel->PADDR+0xffff);
} else {
/* Portable CRC ISR code defined in the high level driver, note, it is a macro.*/
_crc_isr_code(crcp, crcp->crc->DATA ^ crcp->config->final_val);
}
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level CRC driver initialization.
*
* @notapi
*/
void crc_lld_init(void) {
crcObjectInit(&CRCD1);
CRCD1.crc = CRC;
}
/**
* @brief Configures and activates the CRC peripheral.
*
* @param[in] crcp pointer to the @p CRCDriver object
*
* @notapi
*/
void crc_lld_start(CRCDriver *crcp) {
if (crcp->config == NULL)
crcp->config = &default_config;
rcuEnableCRC( FALSE );
osalDbgAssert(crcp->config->initial_val == default_config.initial_val,
"hardware doesn't support programmable initial value");
osalDbgAssert(crcp->config->poly_size == default_config.poly_size,
"hardware doesn't support programmable polynomial size");
osalDbgAssert(crcp->config->poly == default_config.poly,
"hardware doesn't support programmable polynomial");
osalDbgAssert(crcp->config->reflect_data == default_config.reflect_data,
"hardware doesn't support reflect of input data");
osalDbgAssert(crcp->config->reflect_remainder == default_config.reflect_remainder,
"hardware doesn't support reflect of output remainder");
#if CRC_USE_DMA == TRUE
crcp->dmamode = GD32_DMA_CTL_DIR_M2M | GD32_DMA_CTL_PNAGA |
GD32_DMA_CTL_MWIDTH_WORD | GD32_DMA_CTL_PWIDTH_WORD |
GD32_DMA_CTL_ERRIE | GD32_DMA_CTL_FTFIE |
GD32_DMA_CTL_PRIO(GD32_CRC_CRC0_DMA_PRIORITY);
{
crcp->dmastp = dmaStreamAlloc(GD32_CRC_CRC0_DMA_STREAM,
GD32_CRC_CRC0_DMA_IRQ_PRIORITY,
(gd32_dmaisr_t)crc_lld_serve_interrupt,
(void *)crcp);
osalDbgAssert(crcp->dmastp != NULL, "unable to allocate stream");
}
#endif
}
/**
* @brief Deactivates the CRC peripheral.
*
* @param[in] crcp pointer to the @p CRCDriver object
*
* @notapi
*/
void crc_lld_stop(CRCDriver *crcp) {
#if CRC_USE_DMA == TRUE
dmaStreamFree(crcp->dmastp);
#else
(void)crcp;
#endif
rcuDisableCRC();
}
/**
* @brief Resets current CRC calculation.
*
* @param[in] crcp pointer to the @p CRCDriver object
*
* @notapi
*/
void crc_lld_reset(CRCDriver *crcp) {
crcp->crc->CTL |= CRC_CTL_RST;
}
/**
* @brief Returns calculated CRC from last reset
*
* @param[in] crcp pointer to the @p CRCDriver object
* @param[in] n size of buf in bytes
* @param[in] buf @p buffer location
*
* @notapi
*/
uint32_t crc_lld_calc(CRCDriver *crcp, size_t n, const void *buf) {
#if CRC_USE_DMA == TRUE
crc_lld_start_calc(crcp, n, buf);
(void) osalThreadSuspendS(&crcp->thread);
#else
while(n > 3) {
_crc_lld_calc_word(crcp, *(uint32_t*)buf);
buf+=4;
n-=4;
}
osalDbgAssert(n == 0, "GD32 CRC Unit only supports WORD accesses");
#endif
return crcp->crc->DATA ^ crcp->config->final_val;
}
#if CRC_USE_DMA == TRUE
void crc_lld_start_calc(CRCDriver *crcp, size_t n, const void *buf) {
/* The GD32 DMA can only handle max 65535 bytes per transfer
* because it's data count register has only 16 bit. */
size_t sz = (n > 0xffff) ? 0xffff : n;
crcp->rem_data_size = n-sz;
dmaStreamSetPeripheral(crcp->dmastp, buf);
dmaStreamSetMemory0(crcp->dmastp, &crcp->crc->DATA);
dmaStreamSetTransactionSize(crcp->dmastp, (sz / 4));
dmaStreamSetMode(crcp->dmastp, crcp->dmamode);
dmaStreamEnable(crcp->dmastp);
}
#endif
#endif /* CRCSW_USE_CRC1 */
#endif /* HAL_USE_CRC */
/** @} */

View File

@ -0,0 +1,255 @@
/*
ChibiOS - Copyright (C) 2015 Michael D. Spradling
ChibiOS - Copyright (C) 2021 Stefan Kerkmann
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 GD32VF103/CRC/hal_crc_lld.h
* @brief GD CRC subsystem low level driver header.
*
* @addtogroup CRC
* @{
*/
#ifndef HAL_CRC_LLD_H_
#define HAL_CRC_LLD_H_
#if (HAL_USE_CRC == TRUE) || defined(__DOXYGEN__)
/*
* This error check must occur outsite of CRCSW_USE_CRC1 to check if
* two LLD drivers are enabled at the same time
*/
#if GD32_CRC_USE_CRC0 == TRUE && \
CRCSW_USE_CRC1 == TRUE
#error "Software CRC can't be enable with GD32_CRC_USE_CRC0"
#endif
/**
* Allow CRC Software override for ST drivers. Some ST CRC implimentations
* have limited capabilities.
*/
#if CRCSW_USE_CRC1 != TRUE
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief CRC0 driver enable switch.
* @details If set to @p TRUE the support for CRC1 is included.
* @note The default is @p FALSE.
*/
#if !defined(GD32_CRC_USE_CRC0) || defined(__DOXYGEN__)
#define GD32_CRC_USE_CRC0 FALSE
#endif
/**
* @brief CRC0 DMA priority (0..3|lowest..highest).
* @note The priority level is for CRC DMA stream.
*/
#if !defined(GD32_CRC_CRC0_DMA_PRIORITY) || defined(__DOXYGEN__)
#define GD32_CRC_CRC0_DMA_PRIORITY 2
#endif
/**
* @brief CRC0 DMA interrupt priority level setting.
*/
#if !defined(GD32_CRC_CRC0_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define GD32_CRC_CRC0_DMA_IRQ_PRIORITY 14
#endif
/**
* @brief CRC0 DMA STREAM to use when performing CRC calculation.
*/
#if !defined(GD32_CRC_CRC0_DMA_STREAM) || defined(__DOXYGEN__)
#define GD32_CRC_CRC0_DMA_STREAM GD32_DMA_STREAM_ID(0, 1)
#endif
/**
* @brief CRC DMA error hook.
*/
#if !defined(GD32_CRC_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define GD32_CRC_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if GD32_CRC_USE_CRC0 && !GD32_HAS_CRC
#error "Hardware CRC not present in the selected device"
#error "Use CRCSW_USE_CRC1 for software implementation"
#endif
#if CRC_USE_DMA
#if GD32_CRC_USE_CRC0 && \
!OSAL_IRQ_IS_VALID_PRIORITY(GD32_CRC_CRC0_DMA_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to CRC0"
#endif
#if GD32_CRC_USE_CRC0 && \
!GD32_DMA_IS_VALID_PRIORITY(GD32_CRC_CRC0_DMA_PRIORITY)
#error "Invalid DMA priority assigned to CRC0"
#endif
#if !defined(GD32_DMA_REQUIRED)
#define GD32_DMA_REQUIRED
#endif
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Type of a structure representing an CRC driver.
*/
typedef struct CRCDriver CRCDriver;
/**
* @brief CRC notification callback type
*
* @param[in] crcp pointer to the @ CRCDriver object triggering the
* callback
*/
typedef void (*crccallback_t)(CRCDriver *crcp, uint32_t crc);
/**
* @brief Driver configuration structure.
*/
typedef struct {
/**
* @brief The size of polynomial to be used for CRC.
*/
uint32_t poly_size;
/**
* @brief The coefficients of the polynomial to be used for CRC.
*/
uint32_t poly;
/**
* @brief The inital value
*/
uint32_t initial_val;
/**
* @brief The final XOR value
*/
uint32_t final_val;
/**
* @brief Reflect bit order data going into CRC
*/
bool reflect_data;
/**
* @brief Reflect bit order of final remainder
*/
bool reflect_remainder;
/* End of the mandatory fields.*/
/**
* @brief Operation complete callback or @p NULL
*/
crccallback_t end_cb;
} CRCConfig;
/**
* @brief Structure representing an CRC driver.
*/
struct CRCDriver {
/**
* @brief Driver state.
*/
crcstate_t state;
/**
* @brief Current configuration data.
*/
const CRCConfig *config;
#if CRC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
/**
* @brief Mutex protecting the peripheral.
*/
mutex_t mutex;
#endif /* CRC_USE_MUTUAL_EXCLUSION */
#if defined(CRC_DRIVER_EXT_FIELDS)
CRC_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
/**
* @brief Pointer to the CRCx registers block.
*/
CRC_TypeDef *crc;
#if CRC_USE_DMA == TRUE
/**
* @brief Waiting thread.
*/
thread_reference_t thread;
/**
* @brief Remaining data size.
* @note The DMA can handle only 65535 bytes per transfer because
* it's data count register is only 16 bits wide.
*/
size_t rem_data_size;
/**
* @brief CRC DMA stream
*/
const gd32_dma_stream_t *dmastp;
/**
* @brief DMA mode bit mask.
*/
uint32_t dmamode;
#endif
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if GD32_CRC_USE_CRC0 && !defined(__DOXYGEN__)
extern CRCDriver CRCD1;
#endif /* GD32_CRC_USE_CRC0 */
#ifdef __cplusplus
extern "C" {
#endif
void crc_lld_init(void);
void crc_lld_start(CRCDriver *crcp);
void crc_lld_stop(CRCDriver *crcp);
void crc_lld_reset(CRCDriver *crcp);
uint32_t crc_lld_calc(CRCDriver *crcp, size_t n, const void *buf);
#if CRC_USE_DMA
void crc_lld_start_calc(CRCDriver *crcp, size_t n, const void *buf);
#endif
#ifdef __cplusplus
}
#endif
#endif /* CRCSW_USE_CRC1 */
#endif /* HAL_USE_CRC */
#endif /* HAL_CRC_LLD_H_ */
/** @} */

View File

@ -347,6 +347,28 @@
#define rcuResetCAN1() rcuResetAPB1(RCU_APB1RST_CAN1RST)
/** @} */
/**
* @name CRC peripherals specific RCC operations
* @{
*/
/**
* @brief Enables the CRC peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rcuEnableCRC(lp) rcuEnableAHB(RCU_AHBEN_CRCEN, lp)
/**
* @brief Disables the CRC peripheral clock.
*
* @api
*/
#define rcuDisableCRC() rcuDisableAHB(RCU_AHBEN_CRCEN)
/** @} */
/**
* @name DMA peripherals specific RCU operations
* @{

View File

@ -161,6 +161,17 @@
#define GD32_HAS_CAN1 TRUE
#define GD32_CAN_MAX_FILTERS 28
/* CRC attributes.*/
#define GD32_HAS_CRC TRUE
#define GD32_CRC_PROGRAMMABLE FALSE
/* STM32 compatibility define. */
#if GD32_CRC_USE_CRC0 == TRUE
#define STM32_CRC_USE_CRC1 TRUE
#else
#define STM32_CRC_USE_CRC1 FALSE
#endif
/* DAC attributes.*/
#define GD32_HAS_DAC_CH1 TRUE
#define GD32_DAC_CH1_DMA_STREAM GD32_DMA_STREAM_ID(1, 2)

View File

@ -199,11 +199,11 @@ typedef struct
typedef struct
{
__IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */
__IO uint8_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */
__IO uint32_t DATA; /*!< CRC Data register, Address offset: 0x00 */
__IO uint8_t FDATA; /*!< CRC Independent data register, Address offset: 0x04 */
uint8_t RESERVED0; /*!< Reserved, Address offset: 0x05 */
uint16_t RESERVED1; /*!< Reserved, Address offset: 0x06 */
__IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */
__IO uint32_t CTL; /*!< CRC Control register, Address offset: 0x08 */
} CRC_TypeDef;
/**
@ -637,20 +637,20 @@ typedef struct
/* */
/******************************************************************************/
/******************* Bit definition for CRC_DR register *********************/
#define CRC_DR_DR_Pos (0U)
#define CRC_DR_DR_Msk (0xFFFFFFFFU << CRC_DR_DR_Pos) /*!< 0xFFFFFFFF */
#define CRC_DR_DR CRC_DR_DR_Msk /*!< Data register bits */
/******************* Bit definition for CRC_DATA register *********************/
#define CRC_DATA_DATA_Pos (0U)
#define CRC_DATA_DATA_Msk (0xFFFFFFFFU << CRC_DATA_DATA_Pos) /*!< 0xFFFFFFFF */
#define CRC_DATA_DATA CRC_DATA_DATA_Msk /*!< Data register bits */
/******************* Bit definition for CRC_IDR register ********************/
#define CRC_IDR_IDR_Pos (0U)
#define CRC_IDR_IDR_Msk (0xFFU << CRC_IDR_IDR_Pos) /*!< 0x000000FF */
#define CRC_IDR_IDR CRC_IDR_IDR_Msk /*!< General-purpose 8-bit data register bits */
/******************* Bit definition for CRC_FDATA register ********************/
#define CRC_FDATA_FDATA_Pos (0U)
#define CRC_FDATA_FDATA_Msk (0xFFU << CRC_FDATA_FDATA_Pos) /*!< 0x000000FF */
#define CRC_FDATA_FDATA CRC_FDATA_FDATA_Msk /*!< General-purpose 8-bit data register bits */
/******************** Bit definition for CRC_CR register ********************/
#define CRC_CR_RESET_Pos (0U)
#define CRC_CR_RESET_Msk (0x1U << CRC_CR_RESET_Pos) /*!< 0x00000001 */
#define CRC_CR_RESET CRC_CR_RESET_Msk /*!< RESET bit */
/******************** Bit definition for CRC_CTL register ********************/
#define CRC_CTL_RST_Pos (0U)
#define CRC_CTL_RST_Msk (0x1U << CRC_CTL_RST_Pos) /*!< 0x00000001 */
#define CRC_CTL_RST CRC_CTL_RST_Msk /*!< RESET bit */
/******************************************************************************/
/* */

View File

@ -20,7 +20,7 @@ ifeq ($(HALCONFDIR),)
endif
endif
HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define"))
HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h $(HALCONFDIR)/halconf_community.h | egrep -e "\#define"))
ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/GD/GD32VF103/hal_adc_lld.c
@ -31,6 +31,7 @@ endif
# Drivers compatible with the platform.
include ${CHIBIOS_CONTRIB}/os/hal/ports/GD/GD32VF103/CAN/driver.mk
include ${CHIBIOS_CONTRIB}/os/hal/ports/GD/GD32VF103/CRC/driver.mk
include ${CHIBIOS_CONTRIB}/os/hal/ports/GD/GD32VF103/DAC/driver.mk
include ${CHIBIOS_CONTRIB}/os/hal/ports/GD/GD32VF103/DMA/driver.mk
include ${CHIBIOS_CONTRIB}/os/hal/ports/GD/GD32VF103/GPIO/driver.mk