View previous topic :: View next topic |
Author |
Message |
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
USB usage clarification |
Posted: Thu Jul 28, 2016 12:53 pm |
|
|
I'm using an USB library from CCS on a PIC18F, but I don't understand this comment on that library.
Quote: | Added USB_ISR_POLLING support. Define this and interrupts will not be used. usb_task() must be called periodically in your main loop. If it is not called faster than once per millisecond, USB may not work (PIC18 and PIC24 only). |
I have not defined USB_ISR_POLLING, so I'm using USB interrupt, Do I must call usb_task() faster than one per millisecond or not?
I know that I must call periodically usb_task() because I tried not to call it and the device doesn't enumerate but, I must do it faster than one millisecond anyway? _________________ Electric Blue |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Thu Jul 28, 2016 1:44 pm |
|
|
It's fractionally more complex than they make clear....
If you #define USR_ISR_POLLING, it removes the definitions to say that the interrupt handler code is actually an ISR. The code is instead called from usb_task, and this must then happen at a high rate. The faster than 1mSec rate is needed if your device uses 'interrupt transfers', since these _require_ replies within 1mSec. Even on other devices the call must be very frequent.
Without USB_ISR_POLLING defined, you still need to call usb_task at a reasonable interval (I'd say about 0.25 second or less). Usb_task no longer handles the actual USB transactions, but does handle some 'housekeeping', if the bus is connected, released etc.. Hence the problems you have if it is not called. |
|
|
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
|
Posted: Thu Jul 28, 2016 2:06 pm |
|
|
Ok, thanks for your answer.
I been using this library from more than four years ago with no problems; now I get worried because I make a little change to the program and suddenly the connection stall.
So I add an instruction to toggle a pin before call usb_task() and get about 120kHz on that pin without the USB connected and about 90kHz with the USB connected; but time to time I get a 6.5ms and not so often a 19.5ms lap no matters if the USB connected or not.
I think that is because I write an external SPI EEPROM inside a low priority interrupt.
As I said before this was working a lot of time with no problem, now I add a few lines of code to send data one time to configure the GPS module and is a disaster, from the USB side of course, the rest of the task works ok, like nothing wrong is happening, I'm lost. _________________ Electric Blue |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Thu Jul 28, 2016 2:43 pm |
|
|
You are taking too long in the interrupt handler.
An EEPROM will have a write time that is in computer terms an age. All the time the code is inside this interrupt, the USB code will be being blocked. Result problems.
Think again. Just set a flag in the handler, and in your main loop, do the SPI write. There will still be exactly the same pauses in the loop rate (while the code waits for the EEPROM write to complete), but the USB interrupt will no longer be being blocked.
General rule is that interrupt handlers must never take longer than the 'worst case' interval for other interrupts. So if you have serial data arriving at 38400bps, no handler may take longer than 10/38400th second (0.26mSec). With USB in use, 1mSec etc. etc.. An EEPROM write, will break this rule for most systems.... |
|
|
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
|
Posted: Thu Jul 28, 2016 2:54 pm |
|
|
Can I move the USB CCS ISR to the high priority interrupt? _________________ Electric Blue |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Fri Jul 29, 2016 12:44 am |
|
|
It's honestly better to move the SSP out of the interrupt.
It is the wrong place for it.
Moving the USB to a higher level, can create problems. First, if you make USB high priority, then INT_EXT (if you use it), will also be hight priority. May not be desirable.
However the big problem comes with variables. CCS does not implement any form of variable protection. With a single interrupt level, your code only has to deal with things being changed in the interrupt, while you are using them in the main. If you add two interrupt levels, then you have to ensure the all the code in the lower level interrupt routines, can also cope with things being changed.
The USB hardware itself, has a single level of 'ownership' protection, that is used between the interrupt code, and the main code. If anything touches the hardware in the middle level code, problems will ensue....
Go back to the old mantra 'keep interrupt handlers quick'. |
|
|
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
|
Posted: Fri Jul 29, 2016 7:06 am |
|
|
I'm already using two levels of interrupts, the GPS RX is in high level interrupt and the rest are using low level interrupt.
I can't move the writes to the external EEPROM so easy, there's many routines that writes and read to the external EEPROM and most writes in different EEPROM places and they do it sequentially; sincerely I can't figure out or even imagine the state machine to solve that in the way that you are tell in me.
There's a lot of lines of code(+10K) and more than five years or development is not a green LED on red LED off program. _________________ Electric Blue |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Fri Jul 29, 2016 8:47 am |
|
|
Just have a count to say what should be written.
You are having to do this already in your interrupt code. Everything you say, is increasing the reasons this should not be in an interrupt handler. |
|
|
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
|
Posted: Fri Jul 29, 2016 9:42 am |
|
|
Ok, I'm going to give a try to move all those routines out of the interrupt handler
There's a way to know what routines are calling from interrupt service another routines?
Because all the warnings point to the same line.
>>> Warning 216 "GPS.c" Line 10217(1,2): Interrupts disabled during call to prevent re-entrancy: (WriteBufferEE) _________________ Electric Blue |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Fri Jul 29, 2016 10:43 am |
|
|
That means you have a call to this both inside an interrupt and outside.
You will find this warning for some of the supplied CCS code. But if you look at the code involved it is always things that take a few instruction cycles. For anything that takes significant time, this makes things even worse (remember _all_ interrupts will be disabled...).
No wonder you have problems if you are using the same SPI write routines inside and outside interrupts. |
|
|
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
|
Posted: Fri Jul 29, 2016 11:14 am |
|
|
First, I know what it means, I just what to know what routines called from inside the interrupt are calling this routine.
Second, I don't call the same routine from inside and outside the ISR.
When the program start, before enter to the main loop and with all the ISR disabled, I call those routines to load the configuration to the RAM.
After that I don't call any of those routines from the main program(main loop).
Third, this code has been working ok for five years until this week when I add a few lines to configure the GPS when it start.
Anyway, now I'm trying what you suggest me and I understand that the all the routines that writes or read from the EEPROM must not have a warning like
>>> Warning 216 "GPS.c" Line 10224(1,2): Interrupts disabled during call to prevent re-entrancy: (ReadByteEE)
But how to find those routines if I have 113 points from where those routine are being called? _________________ Electric Blue |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Fri Jul 29, 2016 3:00 pm |
|
|
Maybe you can modify the EEPROM Write slightly (so you can leave it inside the interrupt) so that it doesn't wait until the write is finished? It could exit the interrupt and 'somehow' continue later? |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Sun Jul 31, 2016 4:48 pm |
|
|
As Ttelmah always said, keep the isr as short as possible, not more than a few PC. Why not to set a flag in the isr and write EEPROM outside?
Write EEPROM takes 4 ms 1 byte so when inside the isr interrupts are disabled for long time.
Regarding GPS, why need high priority interrupt for the rx isr?
I am reading NMEA at 9600 with rx isr and had no problems after learning how to interpret the NMEA message.
Best wishes
Joe |
|
|
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
|
Posted: Tue Aug 02, 2016 12:00 pm |
|
|
I was using high ISR for the GPS RX because I has another 6 interrupts and some was writing in the EEPROM time to time.
In the other hand not all the GPS's came with a default baud rate of 9600bps, mostly use 19200bps and some 115200bps.
Now I change the program and left only the USART's and USB in the ISR and just read the flag of the old interrupts and call the proper subroutine.
I have one prototype running with that program from July 29 and seems stable. _________________ Electric Blue |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Tue Aug 02, 2016 4:19 pm |
|
|
The original NMEA standard boudrate was 4,800 bps back in the beginning of the 90's and it is enough to get all the messages ones a second.
Today most GPS receivers default is 9,600 bps but you can easily change to higher. The question is if your application really need higher update rate.
The GPS receivers get's satellites location ones a second, the 2, 5, 10, 20 Hz modules are calculating the position in between the 1 Hz (DR)
Same as the heading you get from the GPS is a calculated heading based on the object trajectory.
I am proposing you to rethink the necessity of using such a high boudrate as 115200 bps.
Best wishes
Joe |
|
|
|