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
Changes from 1 commit
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
Next Next commit
Add suport to use hardware CRC calculation for F4 series
- add native code project for F4 series
- update TinyBooter and TinyCLR projects in Solutions to be able to choose from hardware/software CRC library
  • Loading branch information
josesimoes committed Nov 7, 2016
commit 899ae0761982b977a4a6820d8540bd35957c4a09
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//////////////////////////////////////////////////////////////////////////////////////////
//
// 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
*/

/* NOTES:
- should be good for F1, L1, F2 and F4 units series, other have diferent configurations and polynomial coefficients
- can only handle buffer sizes multiple of 4 otherwise the calculation is incorrect
- can not handle initial CRC values, only 0 is admited
- all the above can be fixed with more code so feel free to jump in ;)
*/
Copy link
Member

Choose a reason for hiding this comment

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

Given these restrictions how does this work with NETMF, NETMF often chunks data into blocks to maintain the appearance of multitasking in a single thread. So it will compute the CRC for a portion of data, use that result as the starting seed of the next so if only 0 is allowed, won't that fail?

It would be interesting to understand the variations of hardware CRC so that we can adjust the HAL layer API surface to better accommodate real world hardware, if not in the interpreter at least it could be done for AOT compilation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The current working Solutions are for F4 series which are covered by this code.
I thought on adding this note there to make people aware of the hardware differences with other STM32 series.
The hardware variations are documented in ST's AN4187

Copy link
Contributor

Choose a reason for hiding this comment

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

@smaillet-ms Unfortunately, the hardware CRC unit design on F4 is rather limited, further iterations support configurable polynomial, 8/16/32 bit data size, programmable initial value and bit reversal, which makes it significantly easier to use.

The calculation takes 4 AHB clock cycles for 32-bit data; the data size can be dynamically adjusted to minimize the number of accesses (i.e. 32, 16, 8 for 7 bytes).



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 crc;

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

// init CRC unit
hcrc.Instance = CRC;

// Reset CRC Calculation Unit
(&hcrc)->Instance->CR |= CRC_CR_RESET;

uint8_t* ptr = (uint8_t*)buffer;

// CRC calculation unit is initialed with 0xFFFFFFFF which is not good for our CRC calculations
// feeding 0xFFFFFFFF to the calculation unit will set the register to 0x00000000

while(hcrc.Instance->DR != 0x0)
{
hcrc.Instance->DR = 0xFFFFFFFF;
}

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

// Enter Data to 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;
}

// 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
@@ -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)" />
8 changes: 7 additions & 1 deletion Solutions/MCBSTM32F400/TinyCLR/TinyCLR.proj
Original file line number Diff line number Diff line change
@@ -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)" />
8 changes: 7 additions & 1 deletion Solutions/MCBSTM32F400/TinyCLR_NONET/TinyCLR_NONET.proj
Original file line number Diff line number Diff line change
@@ -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)" />
8 changes: 7 additions & 1 deletion Solutions/STM32F429IDISCOVERY/TinyBooter/TinyBooter.proj
Original file line number Diff line number Diff line change
@@ -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)" />
8 changes: 7 additions & 1 deletion Solutions/STM32F429IDISCOVERY/TinyCLR/TinyCLR.proj
Original file line number Diff line number Diff line change
@@ -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)" />
8 changes: 7 additions & 1 deletion Solutions/STM32F4DISCOVERY/TinyBooter/TinyBooter.proj
Original file line number Diff line number Diff line change
@@ -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)" />
8 changes: 7 additions & 1 deletion Solutions/STM32F4DISCOVERY/TinyCLR/TinyCLR.proj
Original file line number Diff line number Diff line change
@@ -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)" />