Author Topic: Cleanest way to block 32F417 USB interrupts?  (Read 6282 times)

0 Members and 1 Guest are viewing this topic.

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4132
  • Country: gb
  • Doing electronics since the 1960s...
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #25 on: January 10, 2022, 10:05:20 pm »
I am using some ST code for USB. Being ST, it is ultra messy, but there isn't a whole lot of it. It is a pile of tables, tables of function codes, all kinds of crap. Plus a bug which has been there for years, which we fixed today and which many others must have fixed before but never told anybody.

But, like I said just above, no matter how much you pipeline the flash access, you still have to face the day of reckoning eventually (unless you have enough RAM to store the entire file being written, or you are writing to a RAM disk) and the apparently traditional solution, returning USBD_BUSY while the flash is unavailable (used by another thread, or simply programming itself), works on other targets, but not on mine, and I have only got one life (still working on that one) :)

Disabling ints is now rock solid. I just had to stick a 20ms delay at the end of the flash write (making it 40ms) but nobody will notice this. One day I can revisit this. I doubt they will have the will though, and why break a working system to make it "classically correct". I've just spent an hour documenting today's work.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15398
  • Country: fr
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #26 on: January 10, 2022, 11:14:40 pm »
As long as the USB interrupts are not blocked for longer than the allowed USB request time-out, there's no reason you should have a problem.
Yes this is not really pretty, but I understand the pain of having to use a not-so-good third-party library.

Alternatively, you could consider TinyUSB - which I find pretty good so far. The STM32F4 is supported. I understand that you won't switch now, but maybe for a future design. And it would make porting to a different MCU vendor a lot easier too. TinyUSB supports DFU, mass storage and a number of other USB classes.

https://github.com/hathach/tinyusb
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4132
  • Country: gb
  • Doing electronics since the 1960s...
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #27 on: January 11, 2022, 07:15:41 am »
What sort of max latency is likely to be allowed? I did a google but didn't find much. This
https://www.keil.com/pack/doc/mw/USB/html/_u_s_b__interrupt__transfers.html
tells me that USB FS is likely to be polling at 1kHz but that's a different question.
A lot of hits suggest the default timeout is 5 seconds!

That Tiny USB looks good. We are using MSC and CDC only. And it all seems to work ok - until I got to this "shared flash" business and started testing it rigorously.

What always worries me with these things is how much of these open source projects has been tested. People using them for hobbies don't have an incentive to do lots of testing, and people who use them for a product are highly unlikely to report issues they fixed because

a) commercial use may not be allowed
b) the fixes were done in company time and are the property of the company
c) you don't want to be helping your competitors
d) you don't want your boss to find out that you lifted your code from some website :)

Hence there is a huge amount of code online which has bugs bad enough to make it useless but "somehow" nobody noticed :)
« Last Edit: January 11, 2022, 07:22:02 am by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline voltsandjolts

  • Supporter
  • ****
  • Posts: 2449
  • Country: gb
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #28 on: January 11, 2022, 09:33:44 am »
As long as the USB interrupts are not blocked for longer than the allowed USB request time-out, there's no reason you should have a problem.

Can you explain or provide references for this statement?

The USB device needs to be ready to handle setup requests or data requests (even if just to NAK them) which can be issued by the host at any time.
Without an immediate response, the USB bus is in an error state and you are depending on the grace period provided by the host driver before being disconnected.
Also SOF interrupt (1ms intervals on FS) might be needed in your system.
 

Online mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13995
  • Country: gb
    • Mike's Electric Stuff
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #29 on: January 11, 2022, 09:51:41 am »
You don't say what your product requirements are, but for something like a datalogger, might it be acceptable to simply never access flash from your application while the USB is plugged in?
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline Doctorandus_P

  • Super Contributor
  • ***
  • Posts: 3886
  • Country: nl
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #30 on: January 11, 2022, 11:56:38 am »
This is the problem:

The problem is that the USB ISR calls the SPI2 code which then talks to the serial flash - all inside the ISR.

In general, lengthy operations should never be done in ISR's.
Normally your ISR flags that something needs to happen, and then when your application has some time it will do whatever that needs to happen, but the ISR has long been exited.
These days with microcontrollers with multiple ISR levels it's maybe less of an issue, but if you only have one ISR level, then it blocks all others. I usually keep ISR's to a few hundred instructions, which means other ISR's never have to wait long before they can get serviced.

The complexity of your application is probably better off with a small RTOS. It probably gen be done without,but an RTOS makes it easier (and therefore quicker (in programmer time), more robust and better maintainable) to organize the scheduling of different parts of the program.
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 536
  • Country: sk
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #31 on: January 11, 2022, 01:40:09 pm »
As long as the USB interrupts are not blocked for longer than the allowed USB request time-out, there's no reason you should have a problem.
The USB device needs to be ready to handle setup requests or data requests (even if just to NAK them) which can be issued by the host at any time.
Please point me to an USB device implementation which won't NAK a busy endpoint in hardware. In other words, you don't need software/interrupt handling for the NAKs alone.

Nonetheless, SETUP must not be NAK-ed according to usb2.0 8.4.6.4, so that limits the maximum USB service latency to roughly 3 frames (SETUP is retried 3 times, I am lazy to find the verse) i.e. 3ms.

JW
« Last Edit: January 11, 2022, 01:44:26 pm by wek »
 

Offline voltsandjolts

  • Supporter
  • ****
  • Posts: 2449
  • Country: gb
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #32 on: January 11, 2022, 01:43:48 pm »
Please point me to an USB device implementation which won't NAK a busy endpoint in hardware. In other words, you don't need software/interrupt handling for the NAKs alone.

Yes, of course. But you have to tell the hardware to NAK automatically by some bit setting.
The OP is just disabling USB interrupts at some random time, without care of any ongoing transaction or NAK hardware status.
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 536
  • Country: sk
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #33 on: January 11, 2022, 01:51:18 pm »
Please point me to an USB device implementation which won't NAK a busy endpoint in hardware. In other words, you don't need software/interrupt handling for the NAKs alone.

Yes, of course. But you have to tell the hardware to NAK automatically by some bit setting.
I don't have a very wide knowledge about all the USB device incarnations out there, but I'd be very surprised if any of them would not start NAKing automatically after transmitting/receiving a single packet (or FIFO exhaustion), until further software handling.

Note, that I never said it's a good thing to indiscriminately stop the USB interrupts, see also my comments in the thread on ST"s forum Peter linked to above.

JW
 

Offline voltsandjolts

  • Supporter
  • ****
  • Posts: 2449
  • Country: gb
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #34 on: January 11, 2022, 02:22:10 pm »
but I'd be very surprised if any of them would not start NAKing automatically after transmitting/receiving a single packet (or FIFO exhaustion), until further software handling.

OK, I concede and concur. You must set a bit to not NAK a data transfer, but that bit is then cleared after a transfer by hardware so the default is to NAK (and then you are just subject to the timeout set by the host api call).
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4132
  • Country: gb
  • Doing electronics since the 1960s...
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #35 on: January 11, 2022, 02:39:17 pm »
Thank you all for your input.

Some random replies:

Evidently, on Windows at least, disabling the USB global interrupt doesn't break anything - for the current flash write period which is about 15-17ms (writing 512 bytes at a time, and at a measured 33kbytes/sec). So it is certainly not the case that after 3ms it bombs out.

I am using FreeRTOS, and apart from init in main() etc, almost everything runs under that. I am fairly familiar with it, and yes it's a wonderful way to write software. In fact I wrote my own RTOS, from scratch, for a Z180 c. 1986 and then a better one for a Z280 in 1988 which ran a pretty complex datacomms product. Software rapidly gets truly horrible without an RTOS.

USB is set up as an RTOS task and then runs mostly under interrupts, which appears to be ST's intention given that they supplied the code :) IMHO the only point of argument here is that the flash write is also done inside the ISR, but (as I posted above) if one wasn't doing that, say one was farming out the flash write to a one-shot RTOS task, then one needs to get that RTOS task to return a suitable USB response (instead of the ISR doing it) and return that response only when the flash write is finished.

Re disabling flash access when a USB cable is inserted, that's a bit drastic :) This product one doesn't need super performance, and one could never get "performance" anyway with a 15-17ms flash write time :) (which translates to a totally crappy but in this case perfectly adequate 33kbytes/sec write speed, and the 21mbps SPI speed limits the read speed to a measured ~1.5mbyte/sec).
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 536
  • Country: sk
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #36 on: January 11, 2022, 03:13:53 pm »
Evidently, on Windows at least, disabling the USB global interrupt doesn't break anything
I personally try to avoid evidence-based programming and the "it works for me" paradigm, but I understand the tradeoff between expense and gain.
So it is certainly not the case that after 3ms it bombs out.
That's 3ms after host attempts to send a SETUP. That happens only during enumeration (which is not the case here) and when involved protocols need to transfer some control information (e.g. in MSC/BOT, Reset Recovery implies Clear Feature to be sent to the device - but Reset Recovery means host has already decided that transfer is over). Host of course may decide to send a SETUP to the control endpoint for whatever reason whenever it wants (e.g. for some obscure power-saving measure), but in practice this will be rare.

There may be other reasons for timeouts, e.g. would you have isochronous endpoints you'd need to handle them timely otherwise problems occur quite rapidly.

JW
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4132
  • Country: gb
  • Doing electronics since the 1960s...
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #37 on: January 11, 2022, 03:37:34 pm »
I am happy to try to do this differently, and for sure the "correct" solution ought to be to return some sort of "try again in a while" status because that must be what all the $3 USB-serial converters must be doing :)

Just making the ISR very short is trivial: copy the 512 byte sector into a buffer, and return USBD_OK. An RTOS task can then write the flash. The "slight problem" is that the host will be back in well under a millisecond, trying to write the next one ;)
« Last Edit: January 11, 2022, 03:45:26 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 28050
  • Country: nl
    • NCT Developments
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #38 on: January 11, 2022, 04:12:51 pm »
I am happy to try to do this differently, and for sure the "correct" solution ought to be to return some sort of "try again in a while" status because that must be what all the $3 USB-serial converters must be doing :)

Just making the ISR very short is trivial: copy the 512 byte sector into a buffer, and return USBD_OK. An RTOS task can then write the flash. The "slight problem" is that the host will be back in well under a millisecond, trying to write the next one ;)

I think you can check the previous buffer hasn't been consumed by the OS yet and thus return BUSY. I assume that the other end will try to write the block again later.

« Last Edit: January 11, 2022, 04:15:10 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 536
  • Country: sk
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #39 on: January 11, 2022, 04:19:57 pm »
I am happy to try to do this differently, and for sure the "correct" solution ought to be to return some sort of "try again in a while" status because that must be what all the $3 USB-serial converters must be doing :)
How many of those USB-serial converters are MSC?

As discussed, there are "wait" opportunities at different layers of the protocol stack, all of them having merits and drawbacks. Plus the badly defined nature of whole USB "norms system" and the desperate need to conform to whatever quirks hosts out there may have.
Just making the ISR very short is trivial: copy the 512 byte sector into a buffer, and return USBD_OK. An RTOS task can then write the flash. The "slight problem" is that the host will be back in well under a millisecond, trying to write the next one ;)
Quote from: me, a couple hours ago in the thread in STM32 forum
As I've said, I would handle things at the endpoint level. While host may still decide to be impatient and time out, the general wait mechanism in USB at data packet level is the NAK mechanism (see USB 2.0 5.3.2, An endpoint can inform the host that it is busy by responding with NAK. NAKs are not used as a retire condition for returning an IRP to a software client. Any number of NAKs can be encountered during the processing of a given IRP. A NAK response to a transaction does not constitute an error and is not counted as one of the three errors described above.) This appears to be widely accepted by hosts and drivers therein. It means, that you don't re-enable an Out endpoint for Rx (or don't write data for Tx to In endpoint and enable it) until whatever transaction with the slow memory is finished, using whatever mechanism (e.g. buffering and leaving the USB interrupt, the transaction to be finished by "main" or RTOS later); attempts of host to send more data to Out endpoint or to poll In endpoint are NAKed by the USB hardware of device.

Yes, this is not something you can click in Cube or fix by adding a few selected lines. Cube, as any library, inevitably caters only for a miniscule fraction of all possible usage cases, arguably the "most common" ones. OTOH, Cube is not the only option. There are open-source and third-party solutions out there, and there are consultants available.

JW
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4132
  • Country: gb
  • Doing electronics since the 1960s...
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #40 on: January 11, 2022, 04:57:12 pm »
"I think you can check the previous buffer hasn't been consumed by the OS yet and thus return BUSY. I assume that the other end will try to write the block again later."

For some reason that doesn't work. The BUSY return screws up USB. We tried that already. As far as the host is concerned, it is exactly the same situation as not having buffering and returning BUSY anytime the flash is not available; the only difference is that there is a delay of one sector. So if the host was trying to write only one sector (and the flash was otherwise busy) it would never get a BUSY, but if it was trying to write 2+ sectors then we are back to the same situation... AFAICT.

From the POV of our end, the difference is that the ISR either takes 18ms, or almost nothing, but either one works ok. I haven't looked at the USB interrupt priority but even if a USB write killed the whole RTOS for 18ms at a time (it certainly does kill timer interrupts spectacularly for the 18ms - presumably USB int has a higher priority) it would not matter because this product will not be doing anything critical while somebody is trying to dump a file onto the USB drive (which will be either a little config file, or a firmware update image).

Basically the concept of "real time" goes out of the window if some process wants to access the flash quickly (even just for reading) IF you are having something writing the flash and blocking it for 18ms at a time :)

WEK - yes the USB-serial converters use a different device type; you are right. We will see if we can work out what you are suggesting.
« Last Edit: January 11, 2022, 06:47:20 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline Deni

  • Regular Contributor
  • *
  • Posts: 70
  • Country: hr
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #41 on: January 15, 2022, 05:03:14 pm »
Plus a bug which has been there for years, which we fixed today and which many others must have fixed before but never told anybody.

So, can YOU tell us what it was?
 
The following users thanked this post: thm_w

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 4132
  • Country: gb
  • Doing electronics since the 1960s...
Re: Cleanest way to block 32F417 USB interrupts?
« Reply #42 on: January 18, 2022, 05:19:30 pm »
Yes; the details are here
https://community.st.com/s/question/0D53W00001Ie4WcSAJ/32f417-how-to-block-usbfs-isr-from-a-shared-resource-serial-flash-on-spi

The  USB code incorrect passes an error status back to the SCSI layer above it. Only a "no error" status is correctly handled.

EDIT: For those interested, this thread sort of continues here
https://www.eevblog.com/forum/microcontrollers/32f417-usb-fs-(not-hs)-and-dma/msg3958874/#msg3958874

The issue was adequately solved by disabling interrupts around the FLASH reads and writes, including the internal portion of the FLASH programming cycle. That takes a total of about 17ms but it doesn't break the USB block device.
« Last Edit: January 25, 2022, 05:24:24 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf