-
Notifications
You must be signed in to change notification settings - Fork 223
Add suport to use hardware CRC calculation for F4 series #526
base: dev
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- 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
There are no files selected for viewing
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 ;) | ||
*/ | ||
|
||
|
||
UINT32 SUPPORT_ComputeCRC(const void* buffer, int size, UINT32 initCrc) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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. |
||
{ | ||
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> |
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.
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.
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.
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
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.
@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).