This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello,
we are currently writing our own flash-driver and I got into the OSPI-part in the TRM. I noticed the OSPI also supports automatic polling of the WIP-register of the Flash via the OSPI_WRITE_COMPLETION_CTRL_REG. But I also noticed the sdk-flash-driver does that in SW. Also I found some comments inside the OSPI-driver in the open-function stating that "Set an invalid opcode in the WRITE_COMPLETION_CTRL_REG due to IP limitation".
Which I guess could mean it's not functional?
I didn't find any hint on this in the errata of the AM243x.
Are there more known limitations the OSPI has compared to the functionality stated inside the TRM?
Best regards
Felix
Hi Felix,
The write completion auto polling is disabled because of a couple of reasons:
1. Auto polling in HW is just a way to send read status register by sending 0x05 command to the flash. This is fine in maybe older flashes, but in many new flashes the status register read will also need an address phase. There is no provision to mention this address phase in the configuration registers. That's the main limitation.
2. Auto polling can be a problem in RWW flashes also, where there are non-blocking writes. So to keep the SW simple, we decided to do the write polling in SW.
We write an invalid opcode to the REG to get over another limitation, that if we have 0x05 command in this reg, we can't set that value in the actual FLASH_CMD_REG when we do RDSR in software.
Hope this helped!
Regarding other limitations, I am not sure what exactly you're looking for, but one thing is that although there are 4 chip selects, since there is only 1 set of config registers, if one wants to tie in 4 devices, they have to be identical and all using the same protocol.
Let me know what exact limitations are you looking for here, from an interface POV or driver development POV.
Regards,
Anand Mahadevan SS
Hey Anand,
sorry for the late reply.
Understood and yeah this makes sense.
Well we thought about optimizing our drivers a bit more and maybe reducing the use of while-loops when checking some registers and also the waiting for the WIP-bit was one of those ideas. We thought we may implement a "blocking" technique that would not need any while-loop checking for the WIP-Bit. The problem here is that the write can take sometimes up to 1,8 ms or longer at some flashes and if a task with e.g. prio 5 now polls the WIP in a while-loop all lower prio tasks get blocked. We did a workaround with a sleep(1) (the SDK ClockP_usec-sleep also just does a while-loop if it is lower than one freeRTOS-tick) for that but working with an interrupt would be way more comfortable.
I also checked the STIG-chapter in TRM whcih also could issue an interrupt when the STIG-request is finished. Since the WIP-Bit-read is a STIG-request we could probably use this interrupt in a way, that we trigger the read for WIP, take a Semaphore and if at least the command is sent, receive the interrupt and give the Semaphore.
Also maybe for a bit more understanding: The direct read I guess is the fastest way to read the flash and the indirect write on the other hand let's the OSPI-IP write all the data to flash while the application theoretically could care about other stuff as long as the SRAM is filled. But inside the OSPI-Driver there are also while-loops checking the FIFO-states and so on when writing. The TRM-chapter for DAC is short and as I understood it's the case that a direct write would produce more latency than just passing the data to the SRAM and the let the INDAC do the job, right?
Can we maybe use the watermark-interrupt instead of the while-loops? So referring to the TRM that could be set between 10-250 Bytes at best. So we could say the SW should write one page into the SRAM, start the transaction and the it takes a semaphore which will be released by the interrupt for the watermark and then the sw keeps on passing data to the SRAM. Would this make sense?
Also the delay-register is written automatically by the OSPI-driver with predefined values. would it make sense to tweak a bit the timings at this point?
I guess all previous mentions do not really have a noticeable impact on performance, since it seems we are talking about some ns or µs that we can reduce.
Also I noticed that the OSPI-driver (coming from 08.04 currently, we will update to 08.06 in the nest weeks) did not set the DDR_EN-bit in the DEV_INSTR_RD_CONFIG_REG when enabling DDR. I added it and it works too. Referring to the TRM that would've meant every transaction for Read was made in 8/SDR instead of 8/DDR. is this correct?
Best regards
Felix
Hi Felix,
Thank you for explaining the scenario. I agree, maybe for WIP you can use the STIG interrupt, if you want a non-blocking write.
Your understanding is correct, direct read is faster. When it comes to write, indirect/direct doesn't make a lot of difference in speed since you can only write a page at once. If we want to reduce the CPU load in waiting for the OSPI internal SRAM to clear in indirect mode, we could use watermark level interrupt like you mentioned. But mostly page sizes are 256B or multiples of that, so not sure we could trigger interrupts for the right size. Could do half a page maybe. But that would increase the complexity in SW as well, little bit.
Regarding delay register, you mean dev_delay? Ideally dev_delay data is obtained from flash datasheet, but keeping a sufficiently high value which fits most of the flashes help, that's why we do it in the OSPI driver itself. If you meant the dummy cycles, that's not a fixed value anyway, it is set from the flash driver. Anyways, dev_delay I don't think matters a lot in performance, the difference will 10-15 clock cycles between chip select assert/de-assert.
DDR_EN bit is a bit confusing, I will try to explain it in short. In flashes which support octal DDR, that is 8D in all phases - cmd, addr and data, to support those the controller has another setting called DTR protocol bit. What this means is that cmd is also supposed to be sent in DDR, and the flash already knows to sample in both rising and falling edge. We enable this for the 8D mode. But there are other protocols like 4S-4D-4D where the cmd phase is in SDR, and flash understands that further sampling needs to be done on both clock edges based on the command read in the command phase. In this case, although it is technically DDR, we have to send just the read cmd in SDR mode. I think *this* is enabled by the DDR_EN bit. If the DTR bit is selected, this would have no effect, which is why I think in your case it still worked. So no, we were not originally doing SDR transactions.
Hope this helped, let me know if you have more queries or we can close the thread :)
Regards,
Anand Mahadevan SS
Hey Anand,
glad the thread is still open.
I have one more question and that's about the Chip select. I cannot really find any information of how the CS is driven by the OSPI. I see the CS and decoder-logic but I can't find any info about how this is handled. I can only guess out of the TRM that the IDLE-field also represents the status of the CS-line but it's not really clarified.
The "problem" is that we may need to drive the CS line high on purpose in some cases. e.g. interrupting a read-id-command. Sometimes we get a weird behaviour with our flash-driver (not the TI-one) and I'm trying to identify the problem. Driving the CS High would at least set the flash into standby and thus stop e.g. the read-id-command.
I think that the ENB_SPI_FLD should do this job? At least the description says that all outputs are deactivated and all pins are set to input. But I guess this doesn't drive the CS high? Is it possible to do this with the PERIPH_CS_LINES_FLD?
Or do I need to create a separate GPIO and drive it manually?
Also if there is a possibility directly via the OSPI, are there timing-requirements which need to be considered for the OSPI-IP when enabling and disabling?
Second question:
I also had the case that for the STIG the CMD_EXEC_STATUS_FLD stays 1 and so the command does not execute correctly. After writing a 1 again to the CMD_EXEC_FLD it turned back to 0. I can't find any documantation about what to do in this case. the TRM just says it switches back from 1 to 0 but not what happened if it stays 1. In my case it was right after issuing a write enable 0x06.
I noticed that this behaviour vanished when repowering. It mostly occurs while debugging and loading a new image when in the middle of the process to set the flash from SDR to DDR. So my thought is that the OSPI itself does somehow not correctly reset. I ensure the flash is reset correctly by triggering a reset-pin which is connected to our flash (not via OSPI_RESET_CFG but via a manual GPIO) and if the read id is not valid it automatically triggers a reset again and tries again. In this case I also reset the OSPI but it seems I can't reset it completely without repowering. Is there a way to do this in SW? I also have control over the clocks TISCI_DEV_FSS0, TISCI_DEV_FSS0_FSAS_0 and TISCI_DEV_FSS0_OSPI_0 since we are not using any SysCfg here. Should I disable them before loading a new image via CCS?
Also I did more than the TI-OSPI or previous SDK-Flash-driver did when resetting. I am writing 0x00780081 to the OSPI-config-register at startup as it is stated in the TRM. After closing the OSPI-driver from SDK and opening it again I also call OSPI_norFlashInit1s1s1s even if it is probably not needed since I saw the new (SDK 08.06) ospi-driver sets it to 1s-1s-1s when calling programInstance().
Is there more that needs to be done to reset the OSPI "on the fly"?
I also notived that setting the STIG-values manually via the register-view in CCS and issuing any command does not always work as expected. I noticed that the OSPI-Driver always sets the whole register to 0 when creating a new STIG-request. I also did this but sometimes even with the cmd-cycles adjusted and matching to the data sheet of the flash it somehow does not read the right registers nor does it seem to write them correctly. I followed the instructions of the TRM and the sequence the OSPI-driver uses when calling OSPI_cmdRead or OSPI_cmdWrite. This happened when the flash was set to DDR and the OSPI as well. Could it be that setting the values via register-view does not work correctly all the time or am I probably doing something wrong?
Best regards
Felix
Hi Felix,
Regarding the chip select, I am not sure if it is possible from OSPI IP to do manual trigger, we might have to hook up a GPIO like you mentioned to achieve this. There are no IP specific timing requirements, but there will be requirements from the flash device.
Resetting OSPI controller is very tricky to do on the fly because of the number of configurations we do during the initialization. There is no easy way to do this other than repowering the peripheral. Re-powering can be done by turning off the clocks to the FSS and OSPI IP, the device names which you have mentioned.
Setting values via register-view usually works, that's how we do a lot of trial and error while debugging OSPI/Flash issues. But we have to be very careful about the sequence and understand how certain things can affect the OSPI operations. While doing STIG commands involving register writes, one often misses the WREN command to be sent. Things like these need to be taken care of, but other than that there is no practical difference in doing it via code or CCS register view.
Regards,
Anand M
Hey Anand,
ok, would there be any interferring when using a GPIO for CS with the n_ss_out-configuration? But I think currently I got a good state, which does not requires driving the CS manually anymore.
great! I also saw a RST-Signal in the TRM but I did not find how it is driven:
If it is possible via the clocks then this will also suit our purpose well. What I also tried is setting all registers to their RST-value mentioned in the TRM. I had the feeling (it's a bit hard to verify 100%) that this also worked for resetting. At least when resetting the flash and resetting OSPI via the register-"cleanup" did seem to work for me. The flash-Id could be read out correctly after this.
Ok, then I guess I made some mistakes when using STIG via the registers. especially missing the WREN ;)
Also I got our own flash-driver working, the problem was the fixed read-length of the OSPI_readCmd. It was rxLen before and now it is rxLen-1. So a waitReady with length 1 worked before in OCTAL DDR since the real read bytes were two and after the update I had to adjust my read-length as well. Also this may have been the reason why the STIG got stuck in command-execution.
Maybe you remember our debug-session where we thought the ISSI IS25LX/WX also can transmit 1 Byte in OCTAL DDR. That was not the problem. It also needs to transmit 2 Bytes all the time.
Thanks so far! I understood the handling of the OSPI way better now.
Best regards
Felix
Hi Felix,
Yes, there are multiple ways to reset, easiest way would be the power down. But yes, we could reset the IP registers to the reset value as well. Important thing is resetting the flash.
I am not sure if there is an issue in using GPIO to manually driver CS, something to experiment! Good to know that your driver issues are resolved. Let me know if this thread can be closed now. Keeping threads open for a long time isn't recommended especially if there are too many tangents since it will affect the the thread searchability. You can always do a "Ask a related question" to open a new thread referencing this one.
Regards,
Anand Mahadevan SS
Hey Aakash,
now everything is clarified and we can close the thread. Thank you!
Best regards
Felix