Page 1 of 1
CRC hardware on pyboard
Posted: Fri Apr 17, 2015 6:53 pm
by manitou
I'm trying to test the CRC hardware on the pyboard (ref manual chapter 4) using stm. If I enable the CRC peripheral, values do change in the CRC data register, but they don't match any test vectors for CRC32.
Here is a session, where i enable the CRC peripheral, reset it, set data register to 0, and print data register.
Code: Select all
>>> import stm
>>> print(hex(stm.mem32[stm.RCC + stm.RCC_AHB1ENR]))
0x10000f
>>> stm.mem32[stm.RCC + stm.RCC_AHB1ENR] = 0x10100f
>>> stm.mem32[stm.CRC+stm.CRC_CR] = 1
>>> print(hex(stm.mem32[stm.CRC+stm.CRC_DR]))
-0x1
>>> stm.mem32[stm.CRC+stm.CRC_DR] = 0
>>> print(hex(stm.mem32[stm.CRC+stm.CRC_DR]))
-0x38fb2285
CRC32 of 4 bytes of 0 should be 0x2144df1c
Is there really CRC hardware on STM32F405RG?
Any hints?
If one can get it working, one could add python access to the firmware. There seems to be HAL support ...
test vectors
http://www.febooti.com/products/filetwe ... t-vectors/
crc calculator
http://www.lammertbies.nl/comm/info/crc ... ation.html
Re: CRC hardware on pyboard
Posted: Sat Apr 18, 2015 12:01 am
by dhylands
It seems that the 405 HW uses the reversed polynomial 0x4C11DB7 where you used what I would consider the traditional polynomial of 0xedb88320
So if you take your result -0x38fb2285 and make it positive, you'll get: 0xC704DD7B
Now convert that to binary: 1100 0111 0000 0100 1101 1101 0111 1011 and now bit reverse that bit sequence (i.e. read that bit sequence from right to left) and you'll get:
1101 1110 1011 1011 0010 0000 1110 0011
FInally bit negate that (since that's what the crc32 algo does with the intermediary result at the very end and you get:
0010 0001 0100 0100 1101 1111 0001 1100 which is 0x2144df1c
An issue you'll run into with stm and reading the registers is that you'll run ito issues trying to read values with bit 31 isn't equal to bit 30, since micropython can only represent 31-bit small ints. So I think you'd need a helper routine to do a 32-bit register read and return a proper mulit-precision int or return it as 2 16-bit small ints. The datasheet says that the register needs be accessed by 32-bit words, so the CRC_DR register needs to be read as a single 32-bit entity.
Re: CRC hardware on pyboard
Posted: Tue May 05, 2015 1:15 am
by cloudformdesign
That's a really unfortunate result of the 31bit magic. I think it's worth it to create an issue for the stm module to return the actual in value - - if that has to be multiple precision then so be it.
Re: CRC hardware on pyboard
Posted: Tue May 05, 2015 8:42 pm
by pythoncoder
This could be addressed using the inline assembler. The following code puts the 32 bit result into a single element Python array (bypassing the MicroPython limitation). The getcrc() function then coerces the return value into a Python integer of arbitrary precision. I'm no expert on CRC so you'll need to check the correctness of the output of the following (please report back). But it does produce values with differing bits in b31 and b30.
Code: Select all
from array import array
import stm
def enable_crc():
stm.mem32[stm.RCC + stm.RCC_AHB1ENR] = stm.mem32[stm.RCC + stm.RCC_AHB1ENR] | 0x1000
def reset_crc():
stm.mem32[stm.CRC+stm.CRC_CR] = 1
@micropython.asm_thumb
def getval(r0, r1):
movwt(r3, stm.CRC + stm.CRC_DR)
str(r1, [r3, 0])
ldr(r2, [r3, 0])
str(r2, [r0, 0])
def getcrc(value):
a = array('i', [0])
getval(a, value)
return a[0] & 0xffffffff # coerce to arbitrary precision
enable_crc()
reset_crc()
for x in range(20):
print(hex(getcrc(0)))
Re: CRC hardware on pyboard
Posted: Sat Apr 23, 2016 12:40 am
by manitou
Update. Working in C++ on mbed F446RE ( STM32F446xx cortex-m4 @180mhz, hardware float) with the same simple minded CRC hardware as pyboard, I figured out how to do CRC on 32-bit words so that test vector results were good. You have to reverse the bits of the input words, and the final output CRC has to be bit reversed and the bits flipped.
Code: Select all
CRC->CR = 1; //reset
while(CRC->DR != ~0); // wait for reset
CRC->DR = __RBIT(0x41414141); // AAAA ;
result = ~__RBIT(CRC->DR);
The CRC unit only works on 32-bit words, so you'll need additional software if your data stream is not a multiple of 4 bytes.
Re: CRC hardware on pyboard
Posted: Wed May 16, 2018 12:53 am
by tsjoiner
I'm experimenting with hardware crc on the pyboard testing pythoncoder's example above. Don't think I understand. How can I generate a crc for a string "The quick brown fox jumped over the lazy dog" ? Also, how might I generate a matching crc value using standard Python?
Re: CRC hardware on pyboard
Posted: Wed May 16, 2018 3:34 am
by dhylands
I have some C code which will return a CRC32 for an arbitrary file here:
https://github.com/dhylands/projects/tr ... /src/crc32
This produces the same CRC32 that zip uses. So another way to get a CRC32 value is to put the text you want in a zip file and then print detailed info about the zip archive (under zip you can use zip -l -v foo.zip)
MicroPython has some CRC32 code in the ubunascii module. I was able to do:
Code: Select all
>>> import ubinascii
>>> ubinascii.crc32('Test\n')
4202175170
>>> hex(ubinascii.crc32('Test\n'))
'0xfa781ac2'
Using the other utilities mentioned above:
Code: Select all
$ echo Test > test.txt
$ crc32 test.txt
0xfa781ac2 test.txt
$ unzip -l -v test.zip
Archive: test.zip
Length Method Size Cmpr Date Time CRC-32 Name
-------- ------ ------- ---- ---------- ----- -------- ----
5 Stored 5 0% 2018-05-15 20:27 fa781ac2 test.txt
-------- ------- --- -------
5 5 0% 1 file
$ hd test.txt
00000000 54 65 73 74 0a |Test.|
00000005
Re: CRC hardware on pyboard
Posted: Wed May 16, 2018 4:32 am
by tsjoiner
Just ran:
>>> import ubinascii
>>> ubinascii.crc32('Test\n')
on Pyboard 1.1:
MicroPython v1.9.3-558-ga60efa82 on 2018-04-23; PYBv1.1 with STM32F405RG
got:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'crc32'
Re: CRC hardware on pyboard
Posted: Wed May 16, 2018 6:17 am
by pythoncoder
It only works on the Unix build here.
My assembler code simply provides access to the CRC hardware which operates on 32 bit words. You could get a CRC value by putting each character into a 32 bit word and using my code, but I don't think the result would conform to any standard.
Code: Select all
import stm
from array import array
s = 'the quick brown fox jumps over the lazy dog'
a = array('i', ord(p) for p in s)
def enable_crc():
stm.mem32[stm.RCC + stm.RCC_AHB1ENR] = stm.mem32[stm.RCC + stm.RCC_AHB1ENR] | 0x1000
def reset_crc():
stm.mem32[stm.CRC+stm.CRC_CR] = 1
@micropython.asm_thumb
def getval(r0, r1):
movwt(r3, stm.CRC + stm.CRC_DR)
str(r1, [r3, 0])
ldr(r2, [r3, 0])
str(r2, [r0, 0])
def getcrc(value):
a = array('i', [0])
getval(a, value)
return a[0] & 0xffffffff # coerce to arbitrary precision
enable_crc()
reset_crc()
for i in a:
crc = getcrc(i)
print(hex(crc))
Re: CRC hardware on pyboard
Posted: Wed May 16, 2018 6:16 pm
by dhylands
It looks like you can enable it for the pyboard by setting: MICROPY_PY_UBINASCII_CRC32 in ports/stm32/mpconfigport.h
Specifically, I would try adding:
Code: Select all
#define MICROPY_PY_UBINASCII_CRC32 (1)
after the definition of MICROPY_PY_UBINASCII here:
https://github.com/micropython/micropyt ... ort.h#L125