Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
RICHUNCLEPENNYBAGS
Dec 21, 2010
Hey, this is not exactly embedded programming, but do any of you guys have any experience doing stuff in Windows with USB? I'm interested in trying to make a Guncon3 driver for Windows as a personal project and I'd like to know if you have resources to recommend. Like I'd guess the first thing I want to do is just be able to get the raw output of the thing so I can try to work out what signals it actually sends? I just have this idea and not much sense of how to go about it.

I make ASP.NET applications for a living so this is a bit of a departure from stuff I normally work on.

Adbot
ADBOT LOVES YOU

armorer
Aug 6, 2012

I like metal.
A long time ago I made a post in here about getting up and running doing AVR programming on windows. I said I would follow up at some point with a linux walkthrough. Is there interest in that still? I could write up something that goes through the various free linux command line tools, including debugging.

Slanderer
May 6, 2007

RICHUNCLEPENNYBAGS posted:

Hey, this is not exactly embedded programming, but do any of you guys have any experience doing stuff in Windows with USB? I'm interested in trying to make a Guncon3 driver for Windows as a personal project and I'd like to know if you have resources to recommend. Like I'd guess the first thing I want to do is just be able to get the raw output of the thing so I can try to work out what signals it actually sends? I just have this idea and not much sense of how to go about it.

I make ASP.NET applications for a living so this is a bit of a departure from stuff I normally work on.


Wireshark on linux might support USB capture, so give that a try? There might be capture software for Windows too. There are also inline USB protocol analyzers and data loggers, but those can be expensive.

BattleMaster
Aug 14, 2000

I used USBTrace when I was working on from-scratch USB firmware for a PIC and it did a pretty good job. It's commercial though, but it looks like there are free things too.

JawnV6
Jul 4, 2004

So hot ...
For the Windows development side there's this MSDN. Without any kind of documentation or existing driver to sniff it's going to be pretty difficult though.

BattleMaster
Aug 14, 2000

JawnV6 posted:

For the Windows development side there's this MSDN. Without any kind of documentation or existing driver to sniff it's going to be pretty difficult though.

At the very least, setting up a sniffer on a PC would let you see the device's descriptors which will tell you the endpoints and their types, which is the first step towards making a driver so that the device will enumerate properly. Once you have a stub of a driver that makes it through the enumeration process you can sniff it further to see what it tries to send to the host.

I would wager that even if it doesn't enumerate as an HID, that it will work similarly with transfers over the control endpoint or a second interrupt endpoint.

Edit: Not gonna say it's the easiest thing in the world especially if you've never touched USB before, but Windows handles the descriptor fetching so even without a driver you should be able to sniff everything without having to write any code. Also an input device is the easiest case to work with, it's not like we're talking mass storage here

Edit 2: Actually since the Guncon3 is based on IR tracking it's possible that it sends image data over a bulk endpoint in addition to an HID-like interrupt endpoint, but that's not so bad either

BattleMaster fucked around with this message at 18:36 on May 6, 2015

Aurium
Oct 10, 2010

armorer posted:

A long time ago I made a post in here about getting up and running doing AVR programming on windows. I said I would follow up at some point with a linux walkthrough. Is there interest in that still? I could write up something that goes through the various free linux command line tools, including debugging.

I think it would be great if you did. Debugging is of particular interest to me.

robostac
Sep 23, 2009

Slanderer posted:

Wireshark on linux might support USB capture, so give that a try? There might be capture software for Windows too. There are also inline USB protocol analyzers and data loggers, but those can be expensive.

Microsoft Message Analyzer is quite good (and free) for windows USB capture.

There are a few libusb ports for windows (eg libusbK) that will let you send / recieve to USB endpoints without writing a driver, which might be a good way to get started.

The first step should be connecting the device and getting the descriptors to see if it's going to be a standard usb class or a completely custom thing. USBView (either the microsoft version or the improved USBTreeView - http://www.uwe-sieber.de/usbtreeview_e.html#download) is good for this.

armorer
Aug 6, 2012

I like metal.

Aurium posted:

I think it would be great if you did. Debugging is of particular interest to me.

Okay, I got debugging working using avarice and gdb. You could front-end gdb with something if you want, but I won't go into that. In my write-up I'll be using an AVR Dragon, Mint 16 (out of date, should probably work on any more recent Ubuntu/Debian-based distro), and an atmega328p. The atmega328p doesn't support JTAG, so I'm using debugWire, but it should be even easier to do on an AVR chip that supports JTAG.

RICHUNCLEPENNYBAGS
Dec 21, 2010
Thanks for the various advice on USB, folks.

BattleMaster
Aug 14, 2000

RICHUNCLEPENNYBAGS posted:

Thanks for the various advice on USB, folks.

If you need a hand, post a USB capture log from plugging it in and I can take a look at the descriptors for you. I've never written drivers, just device firmware (from scratch, so even though it was hideous I learned a lot) for generic USB classes, but at the very least I know enough from that to interpret the descriptors.

BattleMaster fucked around with this message at 10:15 on May 7, 2015

RICHUNCLEPENNYBAGS
Dec 21, 2010

BattleMaster posted:

If you need a hand, post a USB capture log from plugging it in and I can take a look at the descriptors for you. I've never written drivers, just device firmware (from scratch, so even though it was hideous I learned a lot) for generic USB classes, but at the very least I know enough from that to interpret the descriptors.

Thanks!

This is what you're talking about, right?

code:

    =========================== USB Port1 ===========================

Connection Status        : 0x01 (Device is connected)
Port Chain               : 2-1-1
Supported Protocols      : 0x01 (1.1)
Properties               : 0x00
 IsUserConnectable       : no
 PortIsDebugCapable      : no

      ======================== USB Device ========================

DriverKeyName            : ERROR_FILE_NOT_FOUND

        +++++++++++++++++ Device Information ++++++++++++++++++
Device ID                : USB\VID_0B9A&PID_0800\6&355110A3&0&1
Driver KeyName           : 
Legacy BusType           : PNPBus
Class                    : 
Service                  : 
Enumerator               : USB
Location Info            : Port_#0001.Hub_#0006
Location IDs             : PCIROOT(0)#PCI(1400)#USBROOT(0)#USB(1)#USB(1), ACPI(_SB_)#ACPI(PCI0)#ACPI(XHC_)#ACPI(RHUB)#ACPI(HS01)#USB(1)
Container ID             : {d32e0c10-f31d-11e4-826d-7824af361ecc}
Manufacturer Info        : -
Capabilities             : 0x00 (-)
Address                  : 1
Problem Code             : 28 (CM_PROB_FAILED_INSTALL)
Power State              : D3 (supported: D0, D2, D3, wake from D0, wake from D2)

        ---------------- Connection Information ---------------
Connection Index         : 0x01 (1)
Connection Status        : 0x01 (DeviceConnected)
Current Config Value     : 0x00
Device Address           : 0x16 (22)
Is Hub                   : 0x00 (no)
Number Of Open Pipes     : 0x00 (0)
Device Bus Speed         : 0x01 (Full-Speed)

        ------------------ Device Descriptor ------------------
bLength                  : 0x12 (18 bytes)
bDescriptorType          : 0x01 (Device Descriptor)
bcdUSB                   : 0x110 (USB Version 1.10)
bDeviceClass             : 0x00 (defined by the interface descriptors)
bDeviceSubClass          : 0x00
bDeviceProtocol          : 0x00
bMaxPacketSize0          : 0x08 (8 bytes)
idVendor                 : 0x0B9A
idProduct                : 0x0800
bcdDevice                : 0x8000
iManufacturer            : 0x00 (No String Descriptor)
iProduct                 : 0x00 (No String Descriptor)
iSerialNumber            : 0x00 (No String Descriptor)
bNumConfigurations       : 0x01

        -------------- Configuration Descriptor ---------------
bLength                  : 0x09 (9 bytes)
bDescriptorType          : 0x02 (Configuration Descriptor)
wTotalLength             : 0x0020 (32 bytes)
bNumInterfaces           : 0x01
bConfigurationValue      : 0x01
iConfiguration           : 0x00 (No String Descriptor)
bmAttributes             : 0x80
 D7: Reserved, set 1     : 0x01
 D6: Self Powered        : 0x00 (no)
 D5: Remote Wakeup       : 0x00 (no)
 D4..0: Reserved, set 0  : 0x00
MaxPower                 : 0x32 (100 mA)

        ---------------- Interface Descriptor -----------------
bLength                  : 0x09 (9 bytes)
bDescriptorType          : 0x04 (Interface Descriptor)
bInterfaceNumber         : 0x00
bAlternateSetting        : 0x00
bNumEndpoints            : 0x02 (2 Endpoints)
bInterfaceClass          : 0xFF (Vendor Specific)
bInterfaceSubClass       : 0x00
bInterfaceProtocol       : 0x00
iInterface               : 0x00 (No String Descriptor)

        ----------------- Endpoint Descriptor -----------------
bLength                  : 0x07 (7 bytes)
bDescriptorType          : 0x05 (Endpoint Descriptor)
bEndpointAddress         : 0x02 (Direction=OUT  EndpointID=2)
bmAttributes             : 0x03 (TransferType=Interrupt)
wMaxPacketSize           : 0x0008 (8 bytes)
bInterval                : 0x10 (16 ms)

        ----------------- Endpoint Descriptor -----------------
bLength                  : 0x07 (7 bytes)
bDescriptorType          : 0x05 (Endpoint Descriptor)
bEndpointAddress         : 0x82 (Direction=IN  EndpointID=2)
bmAttributes             : 0x03 (TransferType=Interrupt)
wMaxPacketSize           : 0x000F (15 bytes)
bInterval                : 0x04 (4 ms)
I set up Microsoft Message Analyzer but I feel like kind of a dummy in that I can't figure out which USB traffic actually belongs to this device. But maybe that's not the right tack anyway.

BattleMaster
Aug 14, 2000

That's what I was hoping for, thanks. It looks pretty simple.

These

code:
idVendor                 : 0x0B9A
idProduct                : 0x0800
bcdDevice                : 0x8000
identify it to the driver. The first two are obvious from their names, but the last one is a version number in BCD with the decimal place after the first digit (in this case, it's version 80.00, yikes that's a high version).

code:
iManufacturer            : 0x00 (No String Descriptor)
iProduct                 : 0x00 (No String Descriptor)
iSerialNumber            : 0x00 (No String Descriptor)
Those would normally be the ID numbers of human-readable strings that identify it to the PC; this is how the computer knows the name of what you've plugged in even if you don't have drivers. They're optional, and the fact that it has no string descriptors assigned is no surprise given that it's not meant to be connected to a PC. In this case, it probably will show up as an unknown device, but this doesn't mean anything is broken. There are more strings defined in other descriptors, but for this device all of them are null as well.

The device has one configuration, which is the typical and most simple case; when you plug in a device, the computer has to tell it which configuration it wants to use and they're mutually exclusive, but luckily we won't have to deal with this.

The configuration descriptor defines one interface. An interface is a set of endpoints that perform one function. Devices with multiple interfaces are composite devices that perform multiple different functions, and again we're lucky to not have to deal with this.

code:
bInterfaceClass          : 0xFF (Vendor Specific)
bInterfaceSubClass       : 0x00
bInterfaceProtocol       : 0x00
If the interface was a standard function (mass storage, human interface, communications, etc..) this would be defined here. Vendor-specific just means that it isn't a standard type.

The interface defines two endpoints.

code:
        ----------------- Endpoint Descriptor -----------------
bLength                  : 0x07 (7 bytes)
bDescriptorType          : 0x05 (Endpoint Descriptor)
bEndpointAddress         : 0x02 (Direction=OUT  EndpointID=2)
bmAttributes             : 0x03 (TransferType=Interrupt)
wMaxPacketSize           : 0x0008 (8 bytes)
bInterval                : 0x10 (16 ms)

        ----------------- Endpoint Descriptor -----------------
bLength                  : 0x07 (7 bytes)
bDescriptorType          : 0x05 (Endpoint Descriptor)
bEndpointAddress         : 0x82 (Direction=IN  EndpointID=2)
bmAttributes             : 0x03 (TransferType=Interrupt)
wMaxPacketSize           : 0x000F (15 bytes)
bInterval                : 0x04 (4 ms)
Endpoints are where all the action happens.

Endpoint 0 is the control endpoint that already exists (it's how all of these descriptors are sent to begin with). Endpoints don't have to be sequentially-numbered, and in this device there's no Endpoint 1; it skips right to 2.

Endpoints are pretty much just logical dropboxes for data that the host wants to send to the device or that the device wants to send to the host. The host initiates all communications and will say things like "hey, here's data for endpoint 2" or "send me the data in endpoint 2". Packets can be smaller than the size the descriptor says (but not bigger, obviously) and it's also valid for the endpoint to not be ready to be polled when the host asks about it, or for the device to not be ready to receive one.

Endpoint 2 is set up as a bidirectional interrupt endpoint (bidirection endpoints count as two separate endpoints.) Interrupt endpoints are designed to be polled at set intervals and are prioritized. Because of this, interrupt endpoints are generally used for human interface devices like game controllers (and mice, and keyboards, etc.) because of their predictability and guaranteed data rate.

Interestingly, the IN endpoint (directions are relative to the host, so IN means from the gun to the computer) has not only a much faster polling rate (4 milliseconds or 250 Hz) and a larger packet size than the OUT endpoint, at 15 bytes versus 8 bytes. I wouldn't expect to see much traffic on the OUT endpoint, so hopefully you don't need to send anything.

Therefore, Endpoint 2 IN is where most of your attention will be focused, and will hopefully be all that you need to deal with in writing a driver. It's likely that one 15 byte packet contains absolutely all controller state, given the weird size of it.

That should be all you need to know. I would imagine that it would be easy to set up a stub driver that opens up the endpoints and just tosses the input to /dev/null, and that the hard part is actually just properly acting on the data from the gun. If you can do that, you can use a packet sniffer on the endpoint to see what happens when you press buttons and such.

Edit: I was expecting it to send image data from a camera to the host so that the host itself can do the image processing and positioning like the Wii Remote does; it may still do that, but given the lack of a bulk endpoint I think it is very unlikely as the interrupt endpoints lack the throughput for that. The control endpoint (endpoint 0) has a packet size of 8 (which is standard, but can be much higher) so I don't think it's using that for image data either (it isn't intuitive but control endpoints can be used for data, old USB 1.1 HID keyboards sent keycodes via an interrupt IN and used control OUT for toggling the keyboard's status lights).

If it does do the image processing itself and only spits out the screen co-ordinate, then there might be a signal that the host needs to send to tell it to enter calibration mode. I don't have one to look at myself so I can't say for sure, but keep that in mind as you poke at it. If there is a signal to initiate calibration, then it's almost certainly going to be sent via Endpoint 2 OUT.

BattleMaster fucked around with this message at 07:31 on May 8, 2015

robostac
Sep 23, 2009

RICHUNCLEPENNYBAGS posted:

I set up Microsoft Message Analyzer but I feel like kind of a dummy in that I can't figure out which USB traffic actually belongs to this device. But maybe that's not the right tack anyway.

The best way I've found is to set a filter for the vendor / product id. In your case this would be:
code:
(Microsoft_Windows_USB_USBPORT.Fid_USBPORT_Device.IdVendor == 0x0B9A) and
(Microsoft_Windows_USB_USBPORT.Fid_USBPORT_Device.IdProduct == 0x0800)

RICHUNCLEPENNYBAGS
Dec 21, 2010
You guys are really helpful. Thanks again.

peepsalot
Apr 24, 2007

        PEEP THIS...
           BITCH!

I'm also working on a USB related project and had not heard of Microsoft message analyzer before, so I thought I would give it a shot.

I'm trying to follow the first video on this page:
https://msdn.microsoft.com/en-us/library/windows/hardware/dn741264%28v=vs.85%29.aspx

I'm on windows 7, and the interface looks a little different from the video. There is no "Capture / Trace" "tab" as mentioned in the video so that's where I'm currently stuck.

Am I losing my mind or is this the most incomprehensible UI produced by microsoft to date?

e: Well I eventually was able to start a USB trace, but none of the devices I try plugging in show up in the log :confused:
Is there something special I need to do to capture enumeration events?

I only see these two devices VID/PID (I'm grouping by UsbDevice in the Analysis grid view to try to see them)
VID:8087 PID:8008
VID:8087 PID:8000
Which I think are intel hubs that are built into the motherboard.

peepsalot fucked around with this message at 21:45 on May 8, 2015

Popete
Oct 6, 2009

This will make sure you don't suggest to the KDz
That he should grow greens instead of crushing on MCs

Grimey Drawer

armorer posted:

A long time ago I made a post in here about getting up and running doing AVR programming on windows. I said I would follow up at some point with a linux walkthrough. Is there interest in that still? I could write up something that goes through the various free linux command line tools, including debugging.

If you could writeup something on using an AVR emulator on Linux that would be cool. A guide to setting up and using simavr for instance.

armorer
Aug 6, 2012

I like metal.

Popete posted:

If you could writeup something on using an AVR emulator on Linux that would be cool. A guide to setting up and using simavr for instance.

I will see about adding that in. I haven't had time to do the writeup yet, but I have everything prepared for it other than running an emulator. It is a pretty solid thing to add though so I'll see what I can do.

Tan Dumplord
Mar 9, 2005

by FactsAreUseless
Hey, I'll bet this is the place to talk this out:

I'm working with a Cortex M3-based synth module (Patchblocks) and I'm trying to wrap my head around why my FM sounds like poo poo. The implementation uses Q10 fixed-point arithmetic on 32-bit with the following sin():

code:
inline int32_t sin(int32_t x) {
	const int qN = 13, qA= 12, qP= 15, qR= 2*qN-qP, qS= qN+qP+1-qA;
	x = x<<(30-qN);              // input is Q13 quadrant (0..4)
	if( (x^(x<<1)) < 0)          // test for quadrant 1 or 2
		x= (1<<31) - x;
	x= x>>(30-qN);
	return x * ( (3<<qP) - (x*x>>qR) ) >> qS;	// output is Q12 (-1..1)
}
The built-in Sine oscillator has a phase accumulator and goes like this:

code:
	if(RESET){
		data->phase = 0;
	}
   	data->out0 = sin((data->phase >> 4) * 4) >> 3;
	data->phase += (FREQUENCY << 7) / SMP_RATE;
	data->phase %= (1<<17);
When I perform FM with two of these oscillators, it sounds like rear end when the modulation depth is not constant. I'd like to explore what the limitations of this sine implementation are, and maybe build an LUT-based sine function at Q16. My goal would be to produce an FM block that does not accumulate significant phase errors.

I have no background in math so I'm kind of over my head. I rolled my own FM block but it sounds pretty bad. I've done FM on floating point before to good result, but something is going awry here in fixed-point land:

code:
#define _SIN(_phase) sin((_phase >> 4) * 4) >> 3

    register int32_t v;

    v = D_FREQ * D_MODMULT;
    v >>= 3;
    v /= SMP_RATE;
    v += D_MODPHASE;
    D_MODPHASE = v % (1 << 17);

    v = _SIN(D_MODPHASE);
    v *= D_MODDEPTH;
    v >>= 3;
    v += D_CARPHASE;
    v %= (1 << 17);
    v = _SIN(v);
    D_OUT = v;

    v = D_FREQ << 7;
    v /= SMP_RATE;
    v += D_CARPHASE;
    D_CARPHASE = v % (1 << 17);
Feel free to point me at reading material if I'm missing some fundamentals.

Edit: fixed a bug that caused the modulation phase to be incorrect, but it doesn't solve the problem.

Tan Dumplord fucked around with this message at 16:43 on May 14, 2015

Tan Dumplord
Mar 9, 2005

by FactsAreUseless
Well, implementing CORDIC sine at Q16 didn't completely eliminate the problem, but it did reduce it. Guess I'll try a LUT next, as I don't think I have any headroom to go to a higher bit depth CORDIC.

Also, CORDIC uses 7 times more CPU than the built-in sin.

Tan Dumplord fucked around with this message at 13:54 on May 15, 2015

yippee cahier
Mar 28, 2005

The CMSIS library provides a LUT based sin function, which you may already have in your environment. I'm on my phone, so not sure on the supported datatypes.

Star War Sex Parrot
Oct 2, 2003

Pretty basic but I thought it was still a fun project, so cross-posting:

Star War Sex Parrot posted:

Managed to reproduce the functionality of a TC-80N3! Sure maybe it's not as pretty....




Tan Dumplord
Mar 9, 2005

by FactsAreUseless

sund posted:

The CMSIS library provides a LUT based sin function, which you may already have in your environment. I'm on my phone, so not sure on the supported datatypes.

Well this saves me from debugging my 1/4 wave LUT with linear interpolation.

CMSIS has Q15 and Q31 LUT sin with cubic interpolation. I didn't have CMSIS, so I got it and hacked the Q15 sin file into a header. Unfortunately, I'm still getting crackling when modulating the depth, so either there's something wrong with my math or fixed-point FM is a lost cause.

I'd try the Q31, but I don't know if I'd really gain anything as I'd probably end up shifting away any of the extra resolution.

taqueso
Mar 8, 2004


:911:
:wookie: :thermidor: :wookie:
:dehumanize:

:pirate::hf::tinfoil:

sliderule posted:

Well this saves me from debugging my 1/4 wave LUT with linear interpolation.

CMSIS has Q15 and Q31 LUT sin with cubic interpolation. I didn't have CMSIS, so I got it and hacked the Q15 sin file into a header. Unfortunately, I'm still getting crackling when modulating the depth, so either there's something wrong with my math or fixed-point FM is a lost cause.

I'd try the Q31, but I don't know if I'd really gain anything as I'd probably end up shifting away any of the extra resolution.

Can you make a test that runs through a bunch of inputs and saves the output of the sin function, then plot it and see if it looks like what you would expect?

Tan Dumplord
Mar 9, 2005

by FactsAreUseless

taqueso posted:

Can you make a test that runs through a bunch of inputs and saves the output of the sin function, then plot it and see if it looks like what you would expect?

Yeah I'll set up a test rig with parallel fixed and floating-point implementations and see what I find.

Tan Dumplord
Mar 9, 2005

by FactsAreUseless
Well, visualizing the waveforms helped me find a few errors with one sine implementation and helped me optimize the headroom of my multiplications and eliminate precision loss, but it hasn't pointed to where the clicking is coming from.

Errors between the fixed and floating point implementations don't exceed 1% at modulation depth 40, and when I modulate the depth over time, errors are proportional to the depth. Also, the error delta from sample to sample does not exceed the maximum error.

Carrier phase and modulator phase accrue no error. Raw sine error < 0.025% at Q15 and < 0.11% at Q10. I've checked for clipping.

Now I guess I need to generate a WAV file to check if it's just happening within the Patchblocks emulator.

edit: Oh wonderful. The WAV sounds fine, so it must be a problem trying to run this algorithm live. Time to profile.

Tan Dumplord fucked around with this message at 22:28 on May 17, 2015

Tan Dumplord
Mar 9, 2005

by FactsAreUseless
Well, I ported Patchblocks' sine function to the testbench, and the awful crackling appears. This gives me hope that the new implementation will work with some optimization.

The crackling is coming from a bug in the sine function that returns -1 for some values near 1/2 pi. I guess it shows up with FM because there are a greater range of phases that can occur at sample time.

edit: *sigh*, PB sine ranges from -1.0 to 1.0 Q12, which means that I can't << 3 to make a valid Q1.15. arm_sin_q15 clips to 0x7FFF.

Tan Dumplord fucked around with this message at 00:10 on May 19, 2015

Tan Dumplord
Mar 9, 2005

by FactsAreUseless
I figured if I am going to keep building stuff with fixed-point math, I would need some tools.

code:
     */+: *
OP 1 Max: 4186 << 7
OP 1 Min: 4185 << 7
  OP 1 Q: 7
OP 2 Max: 4186 << 7
OP 2 Min: 4185 << 7
  OP 2 Q: 7
535808 * 535808 = 287090212864 (39 bits)
Calculating optimal shifts for Q31...

        op1 >>= 4;              // max: 33488
        op2 >>= 4;              // max: 33488
        res = op1 * op2;        // max: 1121446144 (Q6)

Worst error: 981.078125 (0.0056%)
(Low ranges used because it's brute force (O(n^2)) and I don't have all day to test.)

Popete
Oct 6, 2009

This will make sure you don't suggest to the KDz
That he should grow greens instead of crushing on MCs

Grimey Drawer
I'm over here struggling to get this CRC32 function to work properly and you're making me feel real dumb. :cripes:

Tan Dumplord
Mar 9, 2005

by FactsAreUseless
Worry not, I'm pretty dumb myself. At this very instant I am struggling to get a simple multiplication to work in Arm ASM inline in GCC. I'm sure I'll come here and ask a really dumb question very shortly.

e: or not... shaved 5 instructions off of gcc -O1, but I think I replaced thumb instructions with Arm ones. So better CPU usage, worse code size.

Tan Dumplord fucked around with this message at 16:36 on May 20, 2015

carticket
Jun 28, 2005

white and gold.

Popete posted:

I'm over here struggling to get this CRC32 function to work properly and you're making me feel real dumb. :cripes:

CRCs are voodoo. Last week I learned how to back calculate the value to run through to get an expected output because ST's older CRC32 peripheral resets to 0xFFFFFFFF always.

Popete
Oct 6, 2009

This will make sure you don't suggest to the KDz
That he should grow greens instead of crushing on MCs

Grimey Drawer

Mr. Powers posted:

CRCs are voodoo. Last week I learned how to back calculate the value to run through to get an expected output because ST's older CRC32 peripheral resets to 0xFFFFFFFF always.

So I have a binary blob cross compiled on my Ubuntu build machine and I run crc32 on it to get the original value. Then I boot my system (Android with 2.6.35 kernel) and attempt to recalculate the CRC across the same binary blob. I ported over U-Boots crc32 command line function into Linux user land for my board and it never gives me the same crc32. If I use the same crc32 at the U-Boot command line it comes out correct but for whatever reason my port doesn't work...

BattleMaster
Aug 14, 2000

Popete posted:

So I have a binary blob cross compiled on my Ubuntu build machine and I run crc32 on it to get the original value. Then I boot my system (Android with 2.6.35 kernel) and attempt to recalculate the CRC across the same binary blob. I ported over U-Boots crc32 command line function into Linux user land for my board and it never gives me the same crc32. If I use the same crc32 at the U-Boot command line it comes out correct but for whatever reason my port doesn't work...

Could it be caused by a difference in endianness between x86 and ARM?

Popete
Oct 6, 2009

This will make sure you don't suggest to the KDz
That he should grow greens instead of crushing on MCs

Grimey Drawer

BattleMaster posted:

Could it be caused by a difference in endianness between x86 and ARM?

That was my thought too but I can execute the crc32 function from UBoot before booting to Android and it comes out correct. I then ported that Uboot crc32 function to user land and have it running continuously once Android boots and its incorrect. Perhaps I missed some endian check though when I brought the code over.

SybilVimes
Oct 29, 2011
When I did my CS degree, we had to do our CRC in hardware, with 74 series gates *shakes fist*

Popete
Oct 6, 2009

This will make sure you don't suggest to the KDz
That he should grow greens instead of crushing on MCs

Grimey Drawer

SybilVimes posted:

When I did my CS degree, we had to do our CRC in hardware, with 74 series gates *shakes fist*

Well when I did my computer engineering degree we had to do our 16 bit shift multiplier in VLSI transistor layout and we had to make our own gate libraries!

*shakes fist harder*

carticket
Jun 28, 2005

white and gold.

Popete posted:

So I have a binary blob cross compiled on my Ubuntu build machine and I run crc32 on it to get the original value. Then I boot my system (Android with 2.6.35 kernel) and attempt to recalculate the CRC across the same binary blob. I ported over U-Boots crc32 command line function into Linux user land for my board and it never gives me the same crc32. If I use the same crc32 at the U-Boot command line it comes out correct but for whatever reason my port doesn't work...

This is because there isn't just one CRC32 and its dumb. Is the initial value 0xFFFFFFFF or 0? Is it byte or word oriented, and if byte, what order? Is it the same polynomial (it probably is)? The STM32 does little endian word-oriented with an initial value of 0xFFFFFFFF. It took us a while to get this figured out, then we had to get IAR to generate a CRC the same way. Pain in the rear end.

Dotcom656
Apr 7, 2007
I WILL TAKE BETTER PICTURES OF MY DRAWINGS BEFORE POSTING THEM
Hi guys. I've just found this thread today and figured it would be good to read what other people are doing since I've recently gotten involved in embedded programming. I joined a lab at my university where we primary work with Teensy 3.1s and some flavors of MSP430s for ultra low power sensors. So far I've explored and created a testbed for a low power computational RFID backscatter analysis (which was mostly finding existing code and adapting it for my own use) and I helped with writing a basic accelerometer driver and getting some radios to talk to each other!

Popete
Oct 6, 2009

This will make sure you don't suggest to the KDz
That he should grow greens instead of crushing on MCs

Grimey Drawer

Mr. Powers posted:

This is because there isn't just one CRC32 and its dumb. Is the initial value 0xFFFFFFFF or 0? Is it byte or word oriented, and if byte, what order? Is it the same polynomial (it probably is)? The STM32 does little endian word-oriented with an initial value of 0xFFFFFFFF. It took us a while to get this figured out, then we had to get IAR to generate a CRC the same way. Pain in the rear end.

Yeah I actually initially tried out a CRC32 that my buddy had written and it uses the same polynomial as the UBoot and Linux lib/crc32c.c code. The polynomial starts as 0xFFFFFFFF and has a set polynomial. Like I said I ended up just porting over the UBoot CRC32 function into my userland program and tried running it there but ended up with differing results. This could be a byte order issue still though as I'm reading out this blob from eMMC and dumping it into RAM where I then run CRC32 across it.

Adbot
ADBOT LOVES YOU

Pan Et Circenses
Nov 2, 2009

Popete posted:

So I have a binary blob cross compiled on my Ubuntu build machine and I run crc32 on it to get the original value. Then I boot my system (Android with 2.6.35 kernel) and attempt to recalculate the CRC across the same binary blob. I ported over U-Boots crc32 command line function into Linux user land for my board and it never gives me the same crc32. If I use the same crc32 at the U-Boot command line it comes out correct but for whatever reason my port doesn't work...

I'm assuming this code is C? Does the CRC algorithm make any assumption about the actual sizes of data types (int, short, etc...)? Does the code comply with strict aliasing rules? Have you tried running the various CRC on a single word or other small datum to get a better idea how its output diverges?

  • Locked thread