Hello all,
I am using the PE components (including mcuonelcipse) for a FRDM-K22F board using KDS 3.1.0 I am using the FreeRTOS PE component.
The RTOS system has a shell task and a couple of LED tasks. The FRDM board is connected to a DS3232 RTC and a 24C32 EEPROM, connected with short wires.
The code hangs intermittently at the line highlighted below. I can duplicate the problem in various conditions.
The difficult part: It works a lot of the time.
I can duplicate the problem calling PE functions in my code and using the shell interface.
As an example of the problem, I can read the data from the RTC registers if I start at address 0. If I try to start reading at a higher address it will hang.
Some of the PE components work properly (tested via shell) like setting / reading date/time on the RTC. Other PE components hang immediately when they access the bus - I2CSPY, 24Cxx EEPROM.
I have tested this with *similar* results on FRDM boards for KL46, KL26, and K22F. By this I mean the same project with different processor - the I2C fails for different operations
I have NOT been able to duplicate the problem without the RTOS but I haven't tested that extensively.
The flag that is being tested "GI2C_deviceData.dataTransmittedFlg", can be changed through the debugger when halted and the code will continue properly.
The same problem exists with the receive flag.
I suspect that in some conditions the interrupt that triggers those flags being set is being disabled. I think this is related to the RTOS (I'm new to FreeRTOS) but not sure where to go next. I have seen a couple threads indicating the same problem but it isn't clear if/how they were resolved.
I have been chasing this for a couple days. Any thoughts or advice welcome!
Thanks
Ian
Solved! Go to Solution.
Hi Ian,
GI2C1_ScanDevice() will hang by design if there is no timeout enabled. So this is expected. That function is not intended to be used without a timeout (or would have to implement it's own timeout, but that's not implemented).
I hope this makes things clear(er)?
Thanks,
Erich
Hi lan and Erich,
I tried to use DS1307 with Freertos on FRDM-K22F board and using the same PE from Mr. Erich. The system hanged at the line as below when I enabled I2C interrupt.
PE_ISR(Unhandled_ivINT_I2C0)
{
PE_DEBUGHALT();
}
What could be the problem?
Please advise me.
Thank you,
Zohan
Hi Zohan,
that's really strange. It means that the I2C interrupts are not properly handled in the driver. Can you share your project?
Erich
Hi Ian,
that dataTransmittedFlg is set in the I2C interrupt routine. So if it hangs there, it means that the interrupt has not been triggered somehow. One common reaons is that you might have some critical sections in your application, and if they are nested, they are supposed to be nested.
Can you check when it hangs that your NVIC and global core interrupts are still enabled? If not, check your critical sections if they are used in a nested way, but the section handling you are using is not designed for nesting.
Another common problem is not having set the correct interrupt levels for the RTOS. See RTOS for ARM Cortex-M
Your Systick (and therefore the RTOS) shall run with the lowest priority. This should be 15 (see below):
So if you are calling any RTOS functions from the I2C interrupt hooks (e.g. from OnMasterBlockSent() hook), you need to make sure that the interrupt priority of the I2C interrupt is numerically *higher* than MaxSysCall interrupt priority, as the RTOS is masking/disabling all the interrupts from that number and higher (Note: on ARM the higher the number, the lower the priority/urgency!). Failure to use interrupts properly results in sporadic errors as in your case.
Next, the question is if you are using the I2C from multiple tasks? If so, you have to protect access to the bus with a mutex. The GenericI2C component has a setting for this:
If you would like to do your own mutual exclusion, you could enable the two hooks below:
I hope this helps,
Erich
Hi Erich,
Thanks for your reply. I have been poking at this on and off for the last few days. Some of the information I started with is not correct. I have identified the situation when it hangs - no ACK from the device, either from not a valid address or not accessing valid register within the part (oops and oops).
I started over with a new PE project looking like this:
All works properly except when no ACK. In this case CI2C1_OnMasterBlockSent() never gets call and therefor never sets the dataTransmittedFlg flag.
The simplest operation like res = GI2C1_ScanDevice(0x__); still hangs here:
do { /* Wait until data is sent */
} while (!GI2C1_deviceData.dataTransmittedFlg);
I can avoid the problem for now but I will need to resolve it at some point soon.
Any more thoughts?
Thanks,
Ian
Hi Ian,
are you saying that it works most of the time, but for unknown reasons the external device does not respond with an ACK? There is a 'Timeout' setting (will need the Timeout component added, and you will need to feed it with an 'add tick' method) which can help you to get out of blocked situations. But you need to make sure that timeout is handled properly if using with an RTOS: because of context switch, the timeout needs to be longer because the task might get switched out.
I hope this helps,
Erich
Hi Erich,
It's even simpler than you described (I think). It hangs every time if it does not receive an ACK. If I remove all devices from the bus (pullups still connected) and call GI2C1_ScanDevice(...) it hangs.
Maybe that is the expected behavior for the I2C component but I thought the GI2C1_deviceData.dataTransmittedFlg flag would be set even if no ACK was received. The PE_ISR(CI2C1_Interrupt) is triggered even when no ACK is received and the I2C status register TransferComplete flag is set.
Adding the timeout does resolve the problem but I expected the GI2C1_WriteAddress(...) function to return with an error rather than just hang.
Have I missed something or does the PE component not support this?
Thanks,
Ian
Hi Ian,
GI2C1_ScanDevice() will hang by design if there is no timeout enabled. So this is expected. That function is not intended to be used without a timeout (or would have to implement it's own timeout, but that's not implemented).
I hope this makes things clear(er)?
Thanks,
Erich
Thanks Erich, I understand my mistake now: need the timeout. It does seem to me that it would be simpler and cleaner to check if data has been transmitted and then checking if the receive ACK flag has been sent. I expect that wouldn't be very portable, so not practical for PE components.
Thanks for your time and insight on this. I will put my RTOS problems in a separate thread. And a big thank you for your blog and many tutorials!
Ian