I have programmed the PQ processor to execute a real FFT, but the operation corrupts SRAM at the SRAM3/SRAM4 boundary (0x20018000)
static q31_t fftInputBuf[512]; // FFT input (real)
static q31_t fftOutputBuf[257][2]; // FFT output (cmplx), need an extra?
static pq_config_t pq_fft_cfg = {kPQ_32Bit, 0, kPQ_32Bit, 0, kPQ_32Bit, 0, kPQ_32Bit, 0, kPQ_32Bit, (uint32_t *)0xE0000000};
PQ_Init(POWERQUAD);
PQ_SetConfig(POWERQUAD, &pq_fft_cfg);
PQ_TransformRFFT((POWERQUAD_Type *)POWERQUAD_BASE, 512, fftInputBuf, fftOutputBuf);
Before the PQ call, here’s what things look like (everything seems to be configured correctly in the PQ registers). Memory at 0x20018000 is fine.
Immediately after the PQ call there is a 256-long word block overwritten at 0x20018000.
By the way, before calling the RFFT function, other PQ functions were called with no ill effects.
Any help is appreciated.
Thanks,
Bruce
Hi,
Can you tell us the part number you are using?
Secondly, based on reference manual, the SRAM4(0x2004_0000~0x2004_3FFF) are used by PowerQuad module.
I have tried to initialize the memory from 0x2001_8000 to zero, it appears that the space is not written by PowerQuad when computing FFT.
I use LPC55S69-EVK board.
I copy it from data sheet of LPC55S66.
Hope it can help you
BR
XiangJun Rong
Hi XiangJun,
Thank you for your reply. We are using the LPC5536.
Since posting the message we have uncovered what the problem is. The App Notes provide erroneous code. In AN12383, p 33 you find this snippet
/* computing by PowerQuad hardware. */
{
pq_config_t pq_cfg;
pq_cfg.inputAFormat = kPQ_32Bit;
#if defined(APP_CFG_POWERQUAD_ENABLE_HW_PRESCALER) &&
(APP_CFG_POWERQUAD_ENABLE_HW_PRESCALER==1)
pq_cfg.inputAPrescale = 9; /* 2 ^9 for 512 len of input. */
#else
pq_cfg.inputAPrescale = 0;
#endif /* APP_CFG_POWERQUAD_ENABLE_HW_PRESCALER */
pq_cfg.tmpFormat = kPQ_32Bit;
pq_cfg.tmpPrescale = 0;
pq_cfg.outputFormat = kPQ_32Bit;
pq_cfg.outputPrescale = 0; /* restore the effect of pre-divider. */
pq_cfg.tmpBase = (uint32_t *)0xE0000000; /* private ram. */
pq_cfg.machineFormat = kPQ_32Bit;
PQ_SetConfig(POWERQUAD, &pq_cfg);
PQ_TransformRFFT(POWERQUAD, APP_FFT_LEN_512, inputQ31, outputQ31);
PQ_WaitDone(POWERQUAD);
}
However, the RFFT requires a temporary buffer to be allocated, and the address of the buffer must be provided in the 'tmpbase' field in the cfg structure. 0xE0000000 causes the overwrite at SRAM 0x20018000.
As I've posted to this board before, NXP *really* needs to provide a better API on how to use each and every function in the PQ with details about what the function provides, and exactly what the calling parameters need to be. The code snippets are fine, but they are incomplete, and in this case erroneous.
Thanks,
Bruce
Hi,
For the LPC55S36 or LPC5536, it uses the SRAM4.
The SRAM4 is located at the address from 0x2001_8000 to 0x2001_BFFF.
I have checked all the powerquad example code, config->tmpBase = (uint32_t *)0xE0000000U; so the AN is correct.
void PQ_GetDefaultConfig(pq_config_t *config)
{
config->inputAFormat = kPQ_Float;
config->inputAPrescale = 0;
config->inputBFormat = kPQ_Float;
config->inputBPrescale = 0;
config->outputFormat = kPQ_Float;
config->outputPrescale = 0;
config->tmpFormat = kPQ_Float;
config->tmpPrescale = 0;
config->machineFormat = kPQ_Float;
config->tmpBase = (uint32_t *)0xE0000000U;
}
Hope it can help you
BR
XiangJun Rong
I now see the entry in the datasheet that indicates that SRAM 4 (0x20018000-0x2001c000) is for PowerQuad use. That brings up three issues:
1) That fact is virtually hidden among hundreds of pages of documents, and is completely unmentioned in the App Notes. Not good.
2) When you enable the PQ peripheral in an MCUXpresso project, like we did, absolutely nothing happens to prevent the linker from putting code and/or data in that location. In fact, for the longest time on our project, the stack was put at the end (by default) of SRAM, which is directly in SRAM 4. Also, not good.
3) FInally, I don't think that it is actually true that the PQ uses SRAM 4 at all. I reduced some data structures in my code and moved the stack to the "end of data" such that SRAM 4 is completely unused. I filled all of SRAM 4 with 0xA5. Then I ran our code, while pointing the tmpbase register to a pre-allocated buffer like this:
static q31_t fftInputBuf[512]; // FFT input (real)
static q31_t fftTmpBuf[512]; // point tmpbase at this!
static q31_t fftOutputBuf[257][2]; // FFT output (cmplx), need an extra?
static pq_config_t pq_fft_cfg = {kPQ_32Bit, 0, kPQ_32Bit, 0, kPQ_32Bit, 0, kPQ_32Bit, 0, kPQ_32Bit, (uint32_t *)fftTmpBuf};
PQ_Init(POWERQUAD);
PQ_SetConfig(POWERQUAD, &pq_fft_cfg);
PQ_TransformRFFT((POWERQUAD_Type *)POWERQUAD_BASE, 512, fftInputBuf, fftOutputBuf);
This code executes flawlessly, the PQ uses the fftTmpBuf as is scratchpad, and SRAM 4 is *undisturbed* over dozens and dozens of PQ calls (including PQ_MatrixScale, PQ_MatrixAddition, PQ_MatrixProduct, PQ_MatrixMultiplication as well as PQ_TransformRFFT)
Note that this is a good thing, because the datasheet implies that SRAM 4 (all 16 kB of it!) can't be used if the PQ is used. And SRAM is a critical resource -- why should an entire 16 kB not be useable. Fortunately it appears that the hardware itself behaves like a programmer would like it to. Simply point tmpbase to a pre-allocated scratch buffer before calling the RFFT and everything is great.
Which brings me to reiterate, that the PowerQuad documentation from NXP is severely lacking. The PQ unit is a massive competitive advantage over all other ARM-based processors and NXP should really take advantage of that be fully, and correctly, documenting it.