Reading data over the SPI bus using DMA witth STM32F479 - spi

I am using the STM32F479 microcontroller along with a AFE440 Analog Front End. When data is ready to be read on the AFE I get a trigger via the ADC_RDY pin on the Microcontroller. At this point I need to read 4 different registers on the AFE all with 3 bytes of data and store them in a buffer. (3 * 4 = 12 bytes total). Then I want my processor to sleep until I get another event on the ADC_RDY pin at which point I read another 12 bytes. I want to store the 12 bytes read each time in a FIFO buffer of size 120 bytes.
I would like to read and store the bytes into the Buffer all using DMA. My processor will be a sleep during this transaction. It will wake up once the FIFO buffer is full with 120 bytes and process the data.
How would I go about setting this up with ST ?

Related

PC set Capabilities.InputReportByteLength to one more that USB device packet size - why?

I am playing around with a PIC16F1455, using the USB port based on this article: https://www.codeproject.com/Tips/530836/Csharp-USB-HID-Interface
I send data to the port, and I set the packet size (Configuration descriptor) to 8 bytes.
However, the PC sees the Capabilities.InputReportByteLength as 9 bytes
And when I receive I get 9 bytes, the first one always being 00, followed by the 8 bytes I send from my device.
Can anyone tell me why this happens?
And this first 00, what is this used for?
Can I put something real there?

STM32 USB Custom HID only 1 byte per transaction

I know that maximum speed of USB HID device is 64 kbps, but on oscilloscope I get transactions every 1 ms, which contain only ONE byte. My HID report descriptor listed below. What i must change to achieve 64Kbps? Currently my bInterval = 0x01 (1 ms polling for interrupt endpoint), but actual speed is 65 bytes/s, because it add reportID byte to my 64-byte data. I think, USB should not divide single 64+1 packet to 65 singlebyte packets. For experiment I use reportID=1 (from STM32 to PC). From PC side I use hidapi.dll to interact.
__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
/* USER CODE BEGIN 0 */
USAGE_PAGE(USAGE_PAGE_UNDEFINED)
USAGE(USAGE_UNDEFINED)
COLLECTION(APPLICATION)
REPORT_ID(1)
USAGE(1)
LOGICAL_MIN(0)
LOGICAL_MAX(255)
REPORT_SIZE(8)
REPORT_COUNT(64)
INPUT(DATA | VARIABLE | ABSOLUTE)
REPORT_ID(2)
USAGE(2)
LOGICAL_MIN(0)
LOGICAL_MAX(255)
REPORT_SIZE(8)
REPORT_COUNT(64)
OUTPUT(DATA | VARIABLE | ABSOLUTE)
REPORT_ID(3)
USAGE(3)
LOGICAL_MIN(0)
LOGICAL_MAX(255)
REPORT_SIZE(8)
REPORT_COUNT(64)
OUTPUT(DATA | VARIABLE | ABSOLUTE)
REPORT_ID(4)
USAGE(4)
LOGICAL_MIN(0)
LOGICAL_MAX(255)
REPORT_SIZE(8)
REPORT_COUNT(64)
OUTPUT(DATA | VARIABLE | ABSOLUTE)
/* USER CODE END 0 */
0xC0 /* END_COLLECTION */
};
HID uses interrupt IN/OUT to convey reports. In USB, Interrupt transfers are polled by host every 1 ms. Every time endpoint is polled, it may yield a 64-byte report (for Low/Full speed). That's probably where you get the 64kB/s figure from. Actually, limit is 1k report / second. Also note these limits are different for High-speed and Super-speed devices.
Report descriptor is one thing. What you actually send as interrupt-IN is something else. It should match, but this is not enforced by anything. You should probably look into the code that builds the interrupt IN transfer payload.
Side note: all you seem interested in is to send arbitrary chunks of data, then HID is probably not the relevant profile. Using bulk endpoints looks more appropriate (and you'll not be limited by interrupt endpoint polling rate).

CANOpen network load higher than expected

I am working on a project with a master computer connected via a CANOpen network to 4 slaves.
At each time step, the computer receives a measurement message from each slave, and sends them a control message. In total, 4 messages are received and 4 messages are sent at each time sample.
The message sent is a PDO with 6 data bytes (8 bytes including COB-ID)
The message received is a PDO with 8 data bytes (10 bytes including COB-ID)
My CAN network is configured at 1Mbit/s, and I run my program at 1000 Hz (1 ms sampling time). As the total load resulting from the messages described is 576 bits/cycle, the total load expected in the network is 576kbit/s, or 57%.
What I see, however, is that:
The controlling computer measures a load of ~86% (with minima of 68% and peaks of 100%).
A USB CAN bus analyser I connect to the network registers a traffic
of messages (count-wise) that is around half of what I nominally
expect (i.e., 4 sent, 4 received each cycle, for 50 seconds should result in 50k messages, while I only see 18-25k). Moreover, I receive
1-2 error messages per cycle from the slave devices that the
network is overloaded. Before it is pointed out, even counting the
size of these messages as part of traffic wouldn't get close to
explain the anomaly in load.
What I'd like to know is whether my way of calculating the CANOpen network load is correct. For instance, are there any protocol-specific handshakes, CRCs, or any sort of extra bytes sent to make the network simply work? It's nothing I could see in the wiki page of CANOpen, but I do know there are such appendices to messages in the original CAN bus standard.
In a CAN message, there is more than the data to be transmitted.
There is also the arbitration ID (11- or 29bits, depending on whether you use CAN 2.0A or 2.0B), there is a 15 bit CRC, an 7 bit EOF marker, the control field and also some other reserved bits.
Depending on the data, there may also be stuff bits.
Using CAN2.0B and assuming 48 bits (6 bytes) of data, you will get a message size of roughly 132 bits and roughly 151 bits for your 64 bits messages.
Summing this up, you will get roughly 1132 bits per cycle which is too much for a 1Mbit/s bus and 1000 Hz.
Hope that helps.

Recvfrom() return value

Im using UDP packets and I want to be cleared about some points :
1 - what exactly does "recvfrom" Returns ? I mean if i send a packet with size of 450 byte + 20 byte of IP header + 8 byte UDP header does recvfrom returns 478 bytes as a whole or there could be something like :
it received 10 bytes,300 bytes,100 bytes,68 bytes ?
2 - does the return value of "recvfrom" related to packet fragmentation ?
note :
* Im talking with the assumption that "recvfrom" was successful
* I chose 450 byte to be sure that Im less than the min MTU
For an UDP socket, recvfrom() reads the UDP data. So it returns 450 , provided you supply a buffer that is at least 450 bytes big.
If you supply a buffer that is smaller than the received data, the data will be truncated, and recvfrom() will read as much data as can fit in the buffer you give it.
The IP layer will be the part that fragments an UDP packet, on the receiving host it will reassemble it. This is transparent to the sending/receiving application.

Initializing SD card in SPI issues

I've had a look at Stack Overflow question Initialization of a microSD card using an SPI interface and didn't see any answers that matched my issue (that is, things I haven't already tried).
I have a similar issue where I'm trying to access a SD card through a microcontroller's SPI interface (specifically an HC908). I've tried following the flow charts in the Physical Layer Simplified Specification v2.00 and it seems to initialize correctly on Transcend 1 GB & 2 GB and an AE&C 1 GB card. But I'm having problems on three other random cards from my stash of old cards that I've used on my camera.
My code is all HC908 assembler. I scoped out the SPI clock line and during initialization it's running about 350 kHz (the only speed multiplier that the HC908 supplies at my low MCU clock speed that falls within the 100 - 400 kHz window).
Here are the results of the three cards that aren't completing my initialization routine (all done consecutively without changing any code or timing parameters):
Canon 16Meg card (labeled as SD):
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (indicates idle)
Send CMD8 [0x48000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command set local flag to indicate v1 or MMC card
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
because illegal command branch to error routine
Send CMD13 [0x4D000000000D] (show status buffer) and Loop up to 8 times waiting for high bit on response to go low
R1= 0x05 (idle and illegal command)
Is the illegal command flag stuck? Should I be doing something after CMD8 to clear that flag?
SanDisk UltraII 256Meg
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD8 [0x48000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command set local flag to indicate v1 or MMC card
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send 0xFF 4 times to read OCR
OCR = 0xFFFFFFFF
Send CMD55 [0x770000000065] (1st part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD41 [0x6900000000E5] (2nd part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command, assume card is MMC
Send CMD1 [0x4100000000F9] (for MMC) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Repeat the CMD1 50 times (my arbitrary number to wait until idle clears)
Every R1 response is 0x05 (idle and illegal command)
Why is OCR all F? Doesn't seem proper at all. Also, why does ACMD41 and CMD1 respond illegal command? Is CMD1 failing because the card is waiting for a valid ACMD after the CMD55 even with the illegal command response?
SanDisk ExtremeIII 2G:
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD8 [0x40000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? My loop shows the responses for each iteration and I got 0xFF 0xFF 0xC1 0x7F... is the card getting out of sync?)
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle and back in sync)
Send 0xFF 4 times to read OCR
OCR = 0x00FF80
Send CMD55 [0x770000000065] (1st part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x5F (??? loop responses are 0xFF 0xFF 0xF0 0x5F... again out of sync?)
Send CMD41 [0x6900000000E5] (2nd part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command, but back in sync???)
Because illegal command, assume card is MMC
Send CMD1 [0x4100000000F9] (for MMC) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? loop responses are 0xFF 0xFF 0xC1 0x7F... again out of sync?)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? loop responses are 0xFF 0xFF 0xC1 0x7F... again out of sync?)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x00 (out of idle)
Send CMD9 [0x4900000000AF] (get CSD) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x3F (??? loop responses are 0xFF 0xFF 0xC1 0x3F... again out of sync?)
Code craps out because Illegal command bit is high.
What on Earth is wrong with that card?
Sometimes it is in sync, other times not. (The above pattern is repeatable.) I've scoped this one out and I'm not seeing any rogue clock cycles going through between MOSI/MISO transfers.
OK... I found my problem. For anyone else who runs into this issue, it is important to remember to send an extra 0xFF after getting responses. This gives the card an extra eight clock cycles to prepare itself for the next command. Some cards don't seem to need it (the Transcends that I'm using for example), but others require it.
I actually put a simple loop at the beginning of my 'write command' routine that sends 0xFF until it gets 0xFF as a response just so I don't have to go to all the different places where I read responses to make sure I put an extra send 0xFF. Because as far as the SD card is (usually) concerned in SPI mode, if there are no clock cycles coming in, time stands still.
One thing that I noted and have yet to find an answer for (but so far it isn't hurting anything), after I read the 16 bytes of the CSR, there seem to be an additional 2 bytes of non-0xFF that comes out... Is that a CRC16? Odd since the CSR has a CRC built in...
If you enabled CRC (with CMD59), then yes, data blocks will have CRC16 appended.
For more info see "Physical Layer Simplified Specification Version 2.00", chapters "Bus Transfer Protection" and "Data Read".
This is important: I've had very much trouble with SD/MMC card, until I found out that I had to select an operating voltage.
You do so, by sending ACMD41 with the bit set for the voltage you're supplying the card with.
Note: Only a single bit may be selected.
If you don't select a voltage or select more than one, it will KEEP looping in idle-state and never exit on some SD cards.
That is: If your ACMD41 keeps sending response 0x01, you have not selected a voltage.
The voltage is in ACMD41's 32-bit parameter bits 23...8.
For 3.2V ... 3.3V, this is bit 20, so for instance you could:
acmdSDAppOpCond[2] = (1 << (20 & 7)); /* 3.2V .. 3.3V */
That's hex-value 0x10, so your ACMD41 would look like this...
0x69 0x40 0x10 0x00 0x00 0xCD
...or if it's a SDSC card...
0x69 0x00 0x10 0x00 0x00 0x5F
Here's a short (and incomplete) table of the most common values:
Bit23: 3.5V..3.6V
Bit22: 3.4V..3.5V
Bit21: 3.3V..3.4V
Bit20: 3.2V..3.3V
Bit19: 3.1V..3.2V
Bit18: 3.0V..3.1V
Bit17: 2.9V..3.0V
Bit16: 2.8V..2.9V
Bit15: 2.7V..2.8V
You do NOT have to switch CS high at ANY point in time. You can keep it low ALL the time.