This repository has been archived by the owner on Jun 5, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 223
Add suport to use hardware CRC calculation for F4 series #526
Open
josesimoes
wants to merge
2
commits into
NETMF:dev
Choose a base branch
from
Eclo:hardware-crc-calculation
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
146 changes: 146 additions & 0 deletions
146
DeviceCode/Targets/Native/STM32F4/DeviceCode/STM32F4_CRC/CRC_functions.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
{ | ||
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; | ||
} |
37 changes: 37 additions & 0 deletions
37
DeviceCode/Targets/Native/STM32F4/DeviceCode/STM32F4_CRC/dotNetMF.proj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.