TC234 QSPI non-DMA problem

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
User16286
Level 4
Level 4
First like received
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
0 Likes
12 Replies
NeMa_4793301
Level 6
Level 6
10 likes received 10 solutions authored 5 solutions authored
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.
0 Likes
User16286
Level 4
Level 4
First like received
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
0 Likes
User16286
Level 4
Level 4
First like received
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);
...
0 Likes
User16286
Level 4
Level 4
First like received
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
0 Likes
User16286
Level 4
Level 4
First like received
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.
0 Likes
User16286
Level 4
Level 4
First like received
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?
0 Likes
User16286
Level 4
Level 4
First like received
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
0 Likes
cwunder
Employee
Employee
5 likes given 50 likes received 50 solutions authored
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.
0 Likes
User16286
Level 4
Level 4
First like received
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
0 Likes
User16286
Level 4
Level 4
First like received
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
0 Likes
User16286
Level 4
Level 4
First like received
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
0 Likes

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 

0 Likes