2020-07-07 06:41 AM
Hello there!
I'm working on a custom project, using STM32H750VB with the main app running on an external flash (developed on TrueStudio and HAL 1.7.0). I'm using two EXTI pins to get the data from a RFID reader, using Wiegand 34 protocol. Basically the reader keeps the two lines on high level and when a card is on the field, the lines go to low for a very short time, but never at the same time. That's how I get 34 bits from the card.
Using "HAL_GPIO_EXTI_Callback" and "GPIO_MODE_IT_FALLING", everything works flawless on STM32 internal flash. But running the same code on external flash, it fails most of the time, missing one or two bits. Changing the optimization level to "fast" and even placing the code directly on "EXTIx_IRQHandler" (no callback "trash"), didn't solve the problem.
Did you guys get something like that on external flash? Should I expect this performance even on IRQ?
Thanks a lot!
2020-07-07 07:56 AM
QSPI wont bring you the performance of the internal flash, but to provide even a rough analysis I would need the timing settings of the QSPI and somewhat more defined timing parameters than "for a very short time".
Move the vector table and the EXTI handler to the ITCM RAM. The vector table can be copied as it is, and SCB->VTOR adjusted when it is in place. Moving the function requires a bit of work.
Check that ITCM is defined in the linker script (*.ld)
MEMORY
{
DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K
It should be already there, copy the ITCMRAM line there if it is not.
Then define the section that goes into ITCM
_siccmram = LOADADDR(.ccmram);
.ccmram :
{
. = ALIGN(4);
_sccmram = .; /* create a global symbol at ccmram start */
*(.ccmram)
*(.ccmram*)
. = ALIGN(4);
_eccmram = .; /* create a global symbol at ccmram end */
} >ITCMRAM AT> FLASH
insert it after the .bss block in the linker script.
Then in the source code, mark the EXTI handler and whatever functions it calls so that they go to CCM.
__attribute__((section(".ccmram")))
void EXTIx_Handler(void) {
/* do stuff */
}
and make sure that you copy them into CCM before enabling the interrupt.
extern char _sccmram, _eccmram, _siccmram;
memcpy(&_sccmram, &_siccmram, &_eccmram - &_sccmram);
__DSB();__ISB(); // before possibly jumping to technically self modifying code
2020-07-07 08:41 AM
Make sure it is cached properly.
Make sure the timings are optimal.
Put the vector table and critical code in internal FLASH, or RAM.
The part has a boatload of RAM, and there is actually more internal FLASH than advertised.
Perhaps you can quantify the speed/latency in SI units? Some specific application is a bit abstracted for me.
2020-07-30 04:25 PM
Hello again! I'm sorry for taking so long to return. Let me give you more information.
My QSPI is running at 50 MHz using HCLK3 as main clock (200 MHz). The initialization:
.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE
.ChipSelectHighTime = QSPI_CS_HIGH_TIME_5_CYCLE
.ClockMode = QSPI_CLOCK_MODE_0
.FlashID = QSPI_FLASH_ID_2
.DualFlash = QSPI_DUALFLASH_DISABLE
STM32 internal flash is used for bootloader. The bootloader app loads the "SystemClock_Config" and a USB Host + FatFs routine, so I can read the main code from a USB flash drive (.bin file) directly to external flash. After that, bootloader app jumps to external flash.
About the "for a very short time" and Wiegand protocol, I've tried to get a screenshot from my scope but no success yet. But taking one reader model as example, the line goes to low and stays there for 72us, going after to high. It stays for 680us in high, then goes to low again. There are 2 lines, so I can have 17 pulses for one line and 17 pulses for another, never at the same time.
@berendi , thanks for your tip. But I didn't understand the "move the vector table to the ITCM RAM", maybe because my bootloader/main app routine...
@Community member , thanks a lot too. I think SMT32 is cached properly but how about "boatload of RAM" and "more internal flash"?