Dec 26, 2019
12:29 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dec 26, 2019
12:29 PM
I'm writing an SD card driver using the SPI interface.
As part of the initialization sequence, I need to send 10 0xff bytes to the SD card.
I call IfxQspi_SpiMaster_exchange() to write the data to the card.
i only see three 0xff bytes on the SPI bus in the logic analyzer.
I do some investigating.
IfxQspi_SpiMaster_exchange() calls IfxQspi_SpiMaster_write() to write the data.
IfxQspi_SpiMaster_write() calculates the available FIFO size which is 4, minus 1 for the BACON configuration data.
Ifx_SizeT count = (Ifx_SizeT)(IFXQSPI_HWFIFO_DEPTH - 1 - IfxQspi_getTransmitFifoLevel(qspiSFR)); // -1, since BACON allocates one FIFO entry
count = __min(job->remaining, count);
...
(count == 3 at this point)
I am not using DMA, so it writes the BACON to the FIFO:
...
IfxQspi_writeBasicConfigurationBeginStream(qspiSFR, chHandle->bacon.U);
...
It then writes 3 bytes into the FIFO:
...
IfxQspi_write8(qspiSFR, cs, job->data, count);
...
then it restores the interrupts and exits out of the function:
...
IfxCpu_restoreInterrupts(interruptState);
}
}
}
How is this code supposed to work?
It seems to be trivially broken.
There seems to be a loop missing somewhere to write the remaining 7 bytes to the FIFO.
Toshi
As part of the initialization sequence, I need to send 10 0xff bytes to the SD card.
I call IfxQspi_SpiMaster_exchange() to write the data to the card.
i only see three 0xff bytes on the SPI bus in the logic analyzer.
I do some investigating.
IfxQspi_SpiMaster_exchange() calls IfxQspi_SpiMaster_write() to write the data.
IfxQspi_SpiMaster_write() calculates the available FIFO size which is 4, minus 1 for the BACON configuration data.
Ifx_SizeT count = (Ifx_SizeT)(IFXQSPI_HWFIFO_DEPTH - 1 - IfxQspi_getTransmitFifoLevel(qspiSFR)); // -1, since BACON allocates one FIFO entry
count = __min(job->remaining, count);
...
(count == 3 at this point)
I am not using DMA, so it writes the BACON to the FIFO:
...
IfxQspi_writeBasicConfigurationBeginStream(qspiSFR, chHandle->bacon.U);
...
It then writes 3 bytes into the FIFO:
...
IfxQspi_write8(qspiSFR, cs, job->data, count);
...
then it restores the interrupts and exits out of the function:
...
IfxCpu_restoreInterrupts(interruptState);
}
}
}
How is this code supposed to work?
It seems to be trivially broken.
There seems to be a loop missing somewhere to write the remaining 7 bytes to the FIFO.
Toshi
- Tags:
- IFX
12 Replies
Dec 26, 2019
12:55 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dec 26, 2019
12:55 PM
The remaining data is driven by QSPI interrupts. Are you sure you've got interrupts configured correctly? Check the example in the iLLD help file for how to declare the interrupt and connect the handler.
Dec 26, 2019
03:00 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dec 26, 2019
03:00 PM
UC_wrangler wrote:
The remaining data is driven by QSPI interrupts. Are you sure you've got interrupts configured correctly? Check the example in the iLLD help file for how to declare the interrupt and connect the handler.
I'm looking at the Infineon library code, and it doesn't look like it uses interrupts for the non-DMA SPI case.
In IfxQspi_SpiMaster_initModule I see this code:
if (config->dma.useDma)
{
...
// initialize interrupt for tx
dmaCfg.channelInterruptTypeOfService = config->base.isrProvider;
dmaCfg.channelInterruptPriority = config->base.txPriority;
...
// initialize interrupt for rx
dmaCfg.channelInterruptTypeOfService = config->base.isrProvider;
dmaCfg.channelInterruptPriority = config->base.rxPriority;
}
So the interrupts are only configured if config->dma.useDma is TRUE.
I am not using DMA, so this routine does not configure the interrupts.
So installing an interrupt handler will not fix this problem.
Toshi
Dec 26, 2019
03:34 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dec 26, 2019
03:34 PM
This seems to work. YMMV.
IFX_STATIC void IfxQspi_SpiMaster_write(IfxQspi_SpiMaster_Channel *chHandle)
...
}
else
{
/* If using non-DMA mode, this code should continue to loop until all the data is transferred.
FIXED 12/26/2019 TM */
while (job->remaining > 0)
// if (job->remaining > 0)
{
IfxQspi_SpiMaster *handle = chHandle->base.driver->driver;
Ifx_QSPI *qspiSFR = handle->qspi;
IfxQspi_ChannelId cs = (IfxQspi_ChannelId)(chHandle->bacon.B.CS);
...
IFX_STATIC void IfxQspi_SpiMaster_write(IfxQspi_SpiMaster_Channel *chHandle)
...
}
else
{
/* If using non-DMA mode, this code should continue to loop until all the data is transferred.
FIXED 12/26/2019 TM */
while (job->remaining > 0)
// if (job->remaining > 0)
{
IfxQspi_SpiMaster *handle = chHandle->base.driver->driver;
Ifx_QSPI *qspiSFR = handle->qspi;
IfxQspi_ChannelId cs = (IfxQspi_ChannelId)(chHandle->bacon.B.CS);
...
Dec 26, 2019
04:24 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dec 26, 2019
04:24 PM
Here's the next problem.
I need to manually deassert the SD card CS (SLSO) after the 10 0xff bytes are sent.
However, IfxQspi_SpiMaster_write() is nonblocking, e.g. it returns control before the last byte has been sent.
So what happens is the code deasserts CS after the fifth 0xff byte.
How can I check to ensure all bytes have been sent before deasserting CS?
Toshi
I need to manually deassert the SD card CS (SLSO) after the 10 0xff bytes are sent.
However, IfxQspi_SpiMaster_write() is nonblocking, e.g. it returns control before the last byte has been sent.
So what happens is the code deasserts CS after the fifth 0xff byte.
How can I check to ensure all bytes have been sent before deasserting CS?
Toshi
Dec 26, 2019
06:19 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dec 26, 2019
06:19 PM
Looks like I can check STATUS.PHASE to determine if the transfer is finished.
Would be nice to have an API call to check this, but I can check the hw register.
Would be nice to have an API call to check this, but I can check the hw register.
Dec 26, 2019
06:55 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dec 26, 2019
06:55 PM
It looks like CS is not deasserted for a full SPI clock before the QSPI goes into an idle state.
I'm assuming this is controlled by BACON.TRAIL?
I'm assuming this is controlled by BACON.TRAIL?
Dec 27, 2019
02:02 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dec 27, 2019
02:02 PM
I'm trying to set a SPI clock of 100 khz.
I set the module clock to 1 Mhz, and the channel clock to 100 khz.
The actual SPI clock I see in the logic analyzer is 250 khz.
I've found about 6 bugs in the iLLD Ethernet driver code, and another 6 or so in the MultiCAN code.
Now I'm starting to find bugs in the Infineon QSPI code.
I spend about 95% of my programming time on the Tricore debugging and patching Infineon libraries.
Is there any testing done on the Infineon libraries before they are released?
Toshi
I set the module clock to 1 Mhz, and the channel clock to 100 khz.
The actual SPI clock I see in the logic analyzer is 250 khz.
I've found about 6 bugs in the iLLD Ethernet driver code, and another 6 or so in the MultiCAN code.
Now I'm starting to find bugs in the Infineon QSPI code.
I spend about 95% of my programming time on the Tricore debugging and patching Infineon libraries.
Is there any testing done on the Infineon libraries before they are released?
Toshi
Dec 27, 2019
05:14 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dec 27, 2019
05:14 PM
I don't use the iLLD's
Concerning the QSPI baudrate for 100 kHz, assuming the fBAUD2 = 200MHz (CCUCON0.BAUD2DIV=1 and fPLL is used for the clock source fSOURCE), then you can set TQ=4, Q=49, A=3, B=1, and C=3.
Concerning the QSPI baudrate for 100 kHz, assuming the fBAUD2 = 200MHz (CCUCON0.BAUD2DIV=1 and fPLL is used for the clock source fSOURCE), then you can set TQ=4, Q=49, A=3, B=1, and C=3.
Dec 27, 2019
07:12 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dec 27, 2019
07:12 PM
Yeah, I just noticed the same thing.
iLLD is broken because it assumes the QSPI input clock is IfxScuCcu_getMaxFrequency() which is wrong.
There is a prescaler on the SCU output to the QSPI module (CCUCON0.BAUD2DIV) which it fails to use.
After I fixed this, everything works correctly.
I did two projects using the STM32 and found zero bugs in their Standard Peripheral Library.
I've found so many iLLD bugs during this project it's ridiculous.
iLLD is not production-quality code.
iLLD is intern-quality low-level drivers.
Toshi
iLLD is broken because it assumes the QSPI input clock is IfxScuCcu_getMaxFrequency() which is wrong.
There is a prescaler on the SCU output to the QSPI module (CCUCON0.BAUD2DIV) which it fails to use.
After I fixed this, everything works correctly.
I did two projects using the STM32 and found zero bugs in their Standard Peripheral Library.
I've found so many iLLD bugs during this project it's ridiculous.
iLLD is not production-quality code.
iLLD is intern-quality low-level drivers.
Toshi
Jan 31, 2020
03:17 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jan 31, 2020
03:17 PM
deepakseshan1 wrote:
Hello TMorita,
I trust you are doing well. I am also trying to initiate a QSPI communication(non-DMA method) and I found your messages are very useful.
Regarding "Count==3" referrening to jobs remaining. But I am passing 10 bytes of data and the count is still (count == 3). Please can you shed some slight on what count is referring to?
Thank you for your support in advance,
Deepak
You are making some fundamentally incorrect assumptions.
You are assuming the iLLD code mostly works, and you can make the hardware work just by using the API.
This is an incorrect assumption from my experience.
You have to start with the assumption that the iLLD libraries are broken.
From what I can tell, someone wrote the iLLD libraries and debugged it enough to get one demo working for each interface.
Everything else not used by the demo driver is usually broken.
I've used three drivers so far in iLLD.
The Ethernet driver was really, really broken and took about six weeks to get working.
The CAN was only slightly broken and took two weeks to get working.
The QSPI driver is even more broken than the Ethernet driver, and I've spent about four weeks on it so far.
The code is so atrocious I didn't fix it - I rewrote the critical parts that I absolutely needed.
You can't use the iLLD code out of the box - you have to fix it before it's usable.
Think of it as the Ikea Low Level Driver that comes in broken pieces that require repair before using.
Toshi
Feb 02, 2020
03:28 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Feb 02, 2020
03:28 PM
I do not work for Infineon, and I am not Infineon tech support.
The code I wrote belongs to the company who is currently paying me, which is not Infineon.
The way I see this, you have these options:
1) Debug the Infineon libraries.
If you are capable of understanding hardware manuals, this is the best option.
2) Change processor vendors
If you have influence in the processor selection for your application, then choose a different processor where the vendor API is not a buggy borderline-unusable mess.
3) Buy a support contract from an Infineon partner
There are third-party companies that can provide support for Infineon Tricore libraries.
There is a Infineon webpage that lists all the third-party partners here: https://www.infineon.com/cms/en/partner-network/
4) Ask your manager for a reassignment
You may be able to talk to your manager and explain that you do not have the aptitude to do embedded programming.
In some cases, you can be reassigned to a different position, but in other cases, you may be terminated.
So there is some risk in choosing this option.
5) Look for another job
If your job requires you to program the Tricore and this is non-negotiable, and you do not have the skill to debug the Infineon libraries, and your organization is unwilling to pay for a support contract, and you cannot be reassigned to a different position, then i would recommend looking for a new job (which does not require programming embedded processors).
Hopefully this discussion has helped clarify your options.
Toshi
The code I wrote belongs to the company who is currently paying me, which is not Infineon.
The way I see this, you have these options:
1) Debug the Infineon libraries.
If you are capable of understanding hardware manuals, this is the best option.
2) Change processor vendors
If you have influence in the processor selection for your application, then choose a different processor where the vendor API is not a buggy borderline-unusable mess.
3) Buy a support contract from an Infineon partner
There are third-party companies that can provide support for Infineon Tricore libraries.
There is a Infineon webpage that lists all the third-party partners here: https://www.infineon.com/cms/en/partner-network/
4) Ask your manager for a reassignment
You may be able to talk to your manager and explain that you do not have the aptitude to do embedded programming.
In some cases, you can be reassigned to a different position, but in other cases, you may be terminated.
So there is some risk in choosing this option.
5) Look for another job
If your job requires you to program the Tricore and this is non-negotiable, and you do not have the skill to debug the Infineon libraries, and your organization is unwilling to pay for a support contract, and you cannot be reassigned to a different position, then i would recommend looking for a new job (which does not require programming embedded processors).
Hopefully this discussion has helped clarify your options.
Toshi
Jan 13, 2022
05:57 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jan 13, 2022
05:57 AM
Condition is So worst feels like 5th option is the correction option .
HI @User16286 if possible can we connect.
have some Doubts on QSPI Queue Part