Skip to content
This repository has been archived by the owner on Jun 5, 2019. It is now read-only.

Add suport to use hardware CRC calculation for F4 series #526

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,9 @@ void __section("SectionForBootstrapOperations") STM32F4_BootstrapCode()
RCC->APB1ENR = RCC_APB1ENR_PWREN; // PWR clock used for sleep;
RCC->APB2ENR = RCC_APB2ENR_SYSCFGEN; // SYSCFG clock used for IO;

// Enable the CRC peripheral clock
RCC->AHB1ENR |= RCC_AHB1ENR_CRCEN;

// stop HSI clock
#if SYSTEM_CRYSTAL_CLOCK_HZ != 0
RCC->CR &= ~RCC_CR_HSION;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
//////////////////////////////////////////////////////////////////////////////////////////
//
// 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
//
// Copyright (c) Microsoft Open Technologies. All rights reserved.
// Implementation for CMSIS: Copyright (c) Eclo Solutions Lda
//
// *** Interface for Cortex-M CRC Calculation Unit ***
//
//////////////////////////////////////////////////////////////////////////////////////////

#include <tinyhal.h>

#define CRC_BASE (AHB1PERIPH_BASE + 0x3000U)
#define CRC ((CRC_TypeDef *) CRC_BASE)

typedef struct
{
CRC_TypeDef *Instance; /*!< Register base address */
}CRC_HandleTypeDef;


/*
Interface to Cortex-M CRC calculation unit that implements the equivalent to the software implementation at Support\CRC project.
CRC-32 (Ethernet) polynomial: 0x4C11DB7.
buffer: pointer to the region block to be CRCed
size: lenght of buffer to compute CRC
crc: previous CRC value to start CRC computing
*/

/* NOTE: is good for F1, L1, F2 and F4 units series, other have diferent configurations and polynomial coefficients */

static UINT32 ReverseCRC32(UINT32 targetCRC)
{
// nibble lookup table for _REVERSE_ CRC32 polynomial 0x4C11DB7
static const UINT32 crc32NibbleTable[16] =
{
0x00000000, 0xB2B4BCB6, 0x61A864DB, 0xD31CD86D, 0xC350C9B6, 0x71E47500, 0xA2F8AD6D, 0x104C11DB,
0x82608EDB, 0x30D4326D, 0xE3C8EA00, 0x517C56B6, 0x4130476D, 0xF384FBDB, 0x209823B6, 0x922C9F00
};
UINT8 counter = 8;

while(counter--)
{
targetCRC = (targetCRC >> 4) ^ crc32NibbleTable[targetCRC & 0x0F];
}

return targetCRC;
}

UINT32 FastCRC32(UINT32 initial_crc, uint8_t data)
{
// nibble lookup table for CRC32 polynomial 0x4C11DB7
static const UINT32 crc32NibbleTable[16] =
{
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
};

initial_crc = crc32NibbleTable[(initial_crc >> 28) ^ (data >> 4)] ^ (initial_crc << 4) ;
initial_crc = crc32NibbleTable[(initial_crc >> 28) ^ (data & 0xF)] ^ (initial_crc << 4) ;

return initial_crc;
}

UINT32 SUPPORT_ComputeCRC(const void* buffer, int size, UINT32 initCrc)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have any performance measurements on the hardware based solution vs. software? The table based software approach is pretty small in code size, big on data size for the table and reasonably fast, so I'm curios to see how much better the hardware form is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't hard measure it. But being the CRC peripheral in the silicon it would be expected to be way faster than any software algorithm.
Anyway you can read all about ST own comparison on their App note above. They claim the hardware peripheral is about 60 times faster than the software equivalent.

{
CRC_HandleTypeDef hcrc;

uint32_t index = 0U;
uint32_t arg1;
uint32_t size_remainder = 0U;
volatile UINT32 crc, crc_temp;
volatile UINT32 targetCRC;
volatile UINT32 currentCRC;

// anything to do here?
if(size == 0)
{
return initCrc;
}

// init CRC unit
hcrc.Instance = CRC;

// get pointer to buffer
uint8_t* ptr = (uint8_t*)buffer;

// need to reset CRC peripheral if:
// - CRC initial value is 0
// - the initial CRC is NOT already loaded in the calculation register
if(initCrc == 0 || (hcrc.Instance->DR != initCrc))
{
// Reset CRC Calculation Unit
(&hcrc)->Instance->CR |= CRC_CR_RESET;

// CRC calculation unit is initiated with 0xFFFFFFFF which is not a initial value for our CRC calculation
// feeding 0xFFFFFFFF to the calculation unit will set the register to 0x00000000
while(hcrc.Instance->DR != 0x0)
{
hcrc.Instance->DR = hcrc.Instance->DR;
}
}

if(initCrc != 0 && hcrc.Instance->DR != initCrc)
{
// we have an initial value for CRC calculation and that is not loaded in the CRC calculation register
// load calculation register with REVERSE initial CRC32 value (because of STM32F4 shift order)
hcrc.Instance->DR = ReverseCRC32(initCrc);
}

// set variable to hold how many bytes remain after processing the buffer in steps of 4 bytes
size_remainder = size & 3;

// we'll be reading the buffer in steps of 4 bytes, so the size must be recalculated accordingly
size = size >> 2;

// feed data into the CRC calculator
for(index = 0U; index < size; index++)
{
// take the next 4 bytes as if they were a UINT32
// because the CRC calculation unit expects the bytes in reverse order, reverse the byte order first
arg1 = __REV(*(uint32_t*)(ptr));

// feed the bytes to the CRC
hcrc.Instance->DR = arg1;

// copy to return value
crc = (uint32_t)hcrc.Instance->DR;

// increase pointer by 4 to the next position
// !! we are reading UINT32 from a UINT8 pointer!!
ptr +=4;
}

// compute CRC for remaining bytes, if any
while(size_remainder--)
{
crc = FastCRC32(crc, *(uint8_t*)(ptr++));
}

// Return the CRC computed value
return crc;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<AssemblyName>STM32F4_CRC</AssemblyName>
<ProjectGuid>{A837D336-3ED9-4FDD-8574-68A7DB90B9C4}</ProjectGuid>
<Size>
</Size>
<Description>STM32F4 CRC library</Description>
<Level>HAL</Level>
<LibraryFile>STM32F4_CRC.$(LIB_EXT)</LibraryFile>
<ProjectPath>$(SPOCLIENT)\DeviceCode\Targets\Native\STM32F4\STM32F4_CRC\dotNetMF.proj</ProjectPath>
<ManifestFile>STM32F4_CRC.$(LIB_EXT).manifest</ManifestFile>
<Groups></Groups>
<Documentation>
</Documentation>
<PlatformIndependent>False</PlatformIndependent>
<CustomFilter>
</CustomFilter>
<Required>False</Required>
<IgnoreDefaultLibPath>False</IgnoreDefaultLibPath>
<IsStub>True</IsStub>
<Directory>DeviceCode\Targers\Native\STM32F4\STM32F4_CRC</Directory>
<OutputType>Library</OutputType>
<PlatformIndependentBuild>false</PlatformIndependentBuild>
<Version>4.0.0.0</Version>
</PropertyGroup>

<Import Project="$(SPOCLIENT)\tools\targets\Microsoft.SPOT.System.Settings" />

<PropertyGroup />

<ItemGroup>
<Compile Include="CRC_functions.cpp" />
</ItemGroup>

<Import Project="$(SPOCLIENT)\tools\targets\Microsoft.SPOT.System.Targets" />
</Project>
8 changes: 7 additions & 1 deletion Solutions/MCBSTM32F400/TinyBooter/TinyBooter.proj
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,15 @@
<DriverLibs Include="tinycrt_pal_loader.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\devicecode\pal\TinyCRT\dotNetMF_loader.proj" />
</ItemGroup>
<ItemGroup>
<!-- Software CRC calculation -->
<!--<ItemGroup>
<PlatformIndependentLibs Include="CRC.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\Support\CRC\dotNetMF.proj" />
</ItemGroup>-->
<!-- Hardware CRC calculation -->
<ItemGroup>
<DriverLibs Include="STM32F4_CRC.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Targets\Native\STM32F4\DeviceCode\STM32F4_CRC\dotNetMF.proj" />
</ItemGroup>
<ItemGroup>
<PlatformIndependentLibs Include="WireProtocol.$(LIB_EXT)" />
Expand Down
8 changes: 7 additions & 1 deletion Solutions/MCBSTM32F400/TinyCLR/TinyCLR.proj
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,15 @@
<DriverLibs Include="tinycrt_pal.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\devicecode\pal\TinyCRT\dotNetMF.proj" />
</ItemGroup>
<ItemGroup>
<!-- Software CRC calculation -->
<!--<ItemGroup>
<PlatformIndependentLibs Include="CRC.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\Support\CRC\dotNetMF.proj" />
</ItemGroup>-->
<!-- Hardware CRC calculation -->
<ItemGroup>
<DriverLibs Include="STM32F4_CRC.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Targets\Native\STM32F4\DeviceCode\STM32F4_CRC\dotNetMF.proj" />
</ItemGroup>
<ItemGroup>
<PlatformIndependentLibs Include="WireProtocol.$(LIB_EXT)" />
Expand Down
8 changes: 7 additions & 1 deletion Solutions/MCBSTM32F400/TinyCLR_NONET/TinyCLR_NONET.proj
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,15 @@
<DriverLibs Include="tinycrt_pal.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\devicecode\pal\TinyCRT\dotNetMF.proj" />
</ItemGroup>
<ItemGroup>
<!-- Software CRC calculation -->
<!--<ItemGroup>
<PlatformIndependentLibs Include="CRC.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\Support\CRC\dotNetMF.proj" />
</ItemGroup>-->
<!-- Hardware CRC calculation -->
<ItemGroup>
<DriverLibs Include="STM32F4_CRC.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Targets\Native\STM32F4\DeviceCode\STM32F4_CRC\dotNetMF.proj" />
</ItemGroup>
<ItemGroup>
<PlatformIndependentLibs Include="WireProtocol.$(LIB_EXT)" />
Expand Down
8 changes: 7 additions & 1 deletion Solutions/STM32F429IDISCOVERY/TinyBooter/TinyBooter.proj
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,15 @@
<DriverLibs Include="tinycrt_pal_loader.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\devicecode\pal\TinyCRT\dotNetMF_loader.proj" />
</ItemGroup>
<ItemGroup>
<!-- Software CRC calculation -->
<!--<ItemGroup>
<PlatformIndependentLibs Include="CRC.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\Support\CRC\dotNetMF.proj" />
</ItemGroup>-->
<!-- Hardware CRC calculation -->
<ItemGroup>
<DriverLibs Include="STM32F4_CRC.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Targets\Native\STM32F4\DeviceCode\STM32F4_CRC\dotNetMF.proj" />
</ItemGroup>
<ItemGroup>
<PlatformIndependentLibs Include="WireProtocol.$(LIB_EXT)" />
Expand Down
8 changes: 7 additions & 1 deletion Solutions/STM32F429IDISCOVERY/TinyCLR/TinyCLR.proj
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,15 @@
<DriverLibs Include="tinycrt_pal.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\devicecode\pal\TinyCRT\dotNetMF.proj" />
</ItemGroup>
<ItemGroup>
<!-- Software CRC calculation -->
<!--<ItemGroup>
<PlatformIndependentLibs Include="CRC.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\Support\CRC\dotNetMF.proj" />
</ItemGroup>-->
<!-- Hardware CRC calculation -->
<ItemGroup>
<DriverLibs Include="STM32F4_CRC.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Targets\Native\STM32F4\DeviceCode\STM32F4_CRC\dotNetMF.proj" />
</ItemGroup>
<ItemGroup>
<PlatformIndependentLibs Include="WireProtocol.$(LIB_EXT)" />
Expand Down
8 changes: 7 additions & 1 deletion Solutions/STM32F4DISCOVERY/TinyBooter/TinyBooter.proj
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,15 @@
<DriverLibs Include="tinycrt_pal_loader.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\devicecode\pal\TinyCRT\dotNetMF_loader.proj" />
</ItemGroup>
<ItemGroup>
<!-- Software CRC calculation -->
<!--<ItemGroup>
<PlatformIndependentLibs Include="CRC.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\Support\CRC\dotNetMF.proj" />
</ItemGroup>-->
<!-- Hardware CRC calculation -->
<ItemGroup>
<DriverLibs Include="STM32F4_CRC.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Targets\Native\STM32F4\DeviceCode\STM32F4_CRC\dotNetMF.proj" />
</ItemGroup>
<ItemGroup>
<PlatformIndependentLibs Include="WireProtocol.$(LIB_EXT)" />
Expand Down
8 changes: 7 additions & 1 deletion Solutions/STM32F4DISCOVERY/TinyCLR/TinyCLR.proj
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,15 @@
<DriverLibs Include="tinycrt_pal.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\devicecode\pal\TinyCRT\dotNetMF.proj" />
</ItemGroup>
<ItemGroup>
<!-- Software CRC calculation -->
<!--<ItemGroup>
<PlatformIndependentLibs Include="CRC.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\Support\CRC\dotNetMF.proj" />
</ItemGroup>-->
<!-- Hardware CRC calculation -->
<ItemGroup>
<DriverLibs Include="STM32F4_CRC.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Targets\Native\STM32F4\DeviceCode\STM32F4_CRC\dotNetMF.proj" />
</ItemGroup>
<ItemGroup>
<PlatformIndependentLibs Include="WireProtocol.$(LIB_EXT)" />
Expand Down