From 6ac9e40dfa171c6093555f3f96c0116229c371ca Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 12 Jul 2018 13:58:45 +0200 Subject: Fix STM32 LLD CRCv1 large data bug in DMA mode * STM32 DMA can only handle 65535 bytes per transfer so larger data sets have to split up to be correctly handled when using DMA --- os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.c | 20 +++++++++++++++----- os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.h | 6 ++++++ 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'os') diff --git a/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.c b/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.c index 701b87d..180a383 100755 --- a/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.c +++ b/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.c @@ -121,9 +121,14 @@ static void crc_lld_serve_interrupt(CRCDriver *crcp, uint32_t flags) { /* Stop everything.*/ dmaStreamDisable(crcp->dma); - /* Portable CRC ISR code defined in the high level driver, note, it is - a macro.*/ - _crc_isr_code(crcp, crcp->crc->DR ^ crcp->config->final_val); + 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->dma->channel->CPAR+0xffff); + } else { + /* Portable CRC ISR code defined in the high level driver, note, it is a macro.*/ + _crc_isr_code(crcp, crcp->crc->DR ^ crcp->config->final_val); + } } #endif @@ -308,12 +313,17 @@ uint32_t crc_lld_calc(CRCDriver *crcp, size_t n, const void *buf) { #if CRC_USE_DMA == TRUE void crc_lld_start_calc(CRCDriver *crcp, size_t n, const void *buf) { + /* The STM32 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->dma, buf); dmaStreamSetMemory0(crcp->dma, &crcp->crc->DR); #if STM32_CRC_PROGRAMMABLE == TRUE - dmaStreamSetTransactionSize(crcp->dma, n); + dmaStreamSetTransactionSize(crcp->dma, sz); #else - dmaStreamSetTransactionSize(crcp->dma, (n / 4)); + dmaStreamSetTransactionSize(crcp->dma, (sz / 4)); #endif dmaStreamSetMode(crcp->dma, crcp->dmamode); diff --git a/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.h b/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.h index 213d346..e879103 100644 --- a/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.h +++ b/os/hal/ports/STM32/LLD/CRCv1/hal_crc_lld.h @@ -202,6 +202,12 @@ struct CRCDriver { * @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 */ -- cgit v1.2.3