Correctly calculate K8x QSPI SFA1AD, SFA2AD, SFB1AD and SFB2AD Register values.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Correctly calculate K8x QSPI SFA1AD, SFA2AD, SFB1AD and SFB2AD Register values.

820 Views
deniscollis
Contributor V

Does anyone know how to determine the correct settings for the K8x QSPI registers

QSPI_SFA1AD
QSPI_SFA2AD
QSPI_SFB1AD
QSPI_SFB2AD

Given the following QSPI Flash possibilities:

  1. (Dual) 2 x 64MB
  2. (Dual) 2 x 32MB
  3. (Single) 1 x 32MB

I really cannot get a satisfactory result using the documentation.

deniscollis_0-1660949492976.png

It's clear from this that the K8x QSPI can manage two dual-die chips, for a total of 4 dies.  Our board uses only a single chip, which can be either a single- or dual-die.

For example, starting with simplest case, a single 32MB die connected as Serial Flash A1.  The top address should be QSPI_AMBA_BASE + 32MB:

0x68000000 + 0x2000000 = 0x6A000000

How exactly do I squeeze 0x6A000000 into 22 bits?

Thanks,
Denis

Labels (1)
Tags (2)
0 Kudos
2 Replies

791 Views
Daniel-Aguirre
NXP TechSupport
NXP TechSupport

Hi,

The Reference Manual for the K80 Sub-family has an example on calculating this registers (the example is made with a 256MB though). The section in which this example is given is 36.7.7 Parallel mode ( page 977, rev. 4 09/2015). Maybe this could give a better insight on how to calculate this registers.

Also, there is a note regarding the usage of single-die flash devices, in which TOP_ADDR_MEMx2 (where x is either A or B) needs to have the same value as TOP_ADDR_MEMx1, and size equals 0, for full mapping to only one flash device (Below table 36-14 QuadSPI AMBA Bus Memory Map, page 937, rev. 4, 09/2015).

Let us know if this information was useful or not.

0 Kudos

802 Views
deniscollis
Contributor V

Elsewhere in the reference manual the reset values of the registers are indicated as 0x6FFFFC00:

deniscollis_0-1661185288954.png

...which seems to indicate that the top addresses are not byte counts. Instead, given that the least significant 10-bits are always 0, the most significant 22-bits are 1K block counts.

0x6FFFFC00 >> 10 is 0x1BFFFF
0x68000000 >> 10 is 0x1A0000 (The bottom address is 0x68000000)
1BFFFF - 1A0000 = 0x1FFFF (This is the 1K-block top address, and offset 128K x 1K-blocks) 

The reset values place the full 128MB into Chip-A, Bank-1

Even though the QSPI peripheral itself is capable of handling 4 dies, programmers like Segger's J-Link only address 2 dies. I will therefore assume that no-one has designed their board with 4 dies.

So, assuming single- or dual-die only, and given that Segger fixes the address ranges for each bank at 64MB we can ALWAYS set the registers as follows:

QSPI_SFA1AD = 6BFFFC00 [TPDA1 = 1AFFFF] (64MB)
QSPI_SFA2AD = 6BFFFC00 [TPDA2 = 1AFFFF] (0)

QSPI_SFB1AD = 6FFFFC00 [TPDB1 = 1BFFFF] (64MB)
QSPI_SFB2AD = 6FFFFC00 [TPDB2 = 1BFFFF] (0)

This is irrespective of the die sizes. It is therefore important that memory origins and sizes in your linker scripts correctly match the ranges as per in installed chip, and not those set in the QSPI top-address registers.

 

 

/* Example for a board with a dual(2x) 64MB flash chip with 2x 1MB XiP: */
MEMORY
{
PROGRAM_FLASH   (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 /* 256K */
EXT_PGM_FLASH_A (rx) : ORIGIN = 0x04000000, LENGTH = 0x00100000 /* 1M   */ 
EXT_PGM_FLASH_B (rx) : ORIGIN = 0x08000000, LENGTH = 0x00100000 /* 1M   */
SRAM_LOWER     (rwx) : ORIGIN = 0x1fff0000, LENGTH = 0x00010000 /* 64K  */
SRAM_UPPER     (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000 /* 192K */
XIP_RESERVE_A   (rx) : ORIGIN = 0x68000000, LENGTH = 0x00100000 /* 1M   */ 
EXT_FILES_A     (rx) : ORIGIN = 0x68100000, LENGTH = 0x03F00000 /* 63M  */
XIP_RESERVE_B   (rx) : ORIGIN = 0x6C000000, LENGTH = 0x00100000 /* 1M   */ 
EXT_FILES_B     (rx) : ORIGIN = 0x6C100000, LENGTH = 0x3F0 0000 /* 63M  */
}

/* Example for a board with a dual(2x) 32MB flash chip with 2x 1MB XiP: */
MEMORY
{
PROGRAM_FLASH   (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 /* 256K */
EXT_PGM_FLASH_A (rx) : ORIGIN = 0x04000000, LENGTH = 0x00100000 /* 1M   */ 
EXT_PGM_FLASH_B (rx) : ORIGIN = 0x08000000, LENGTH = 0x00100000 /* 1M   */
SRAM_LOWER     (rwx) : ORIGIN = 0x1fff0000, LENGTH = 0x00010000 /* 64K  */
SRAM_UPPER     (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000 /* 192K */
XIP_RESERVE_A   (rx) : ORIGIN = 0x68000000, LENGTH = 0x00100000 /* 1M   */ 
EXT_FILES_A     (rx) : ORIGIN = 0x68100000, LENGTH = 0x01F00000 /* 31M  */
XIP_RESERVE_B   (rx) : ORIGIN = 0x6C000000, LENGTH = 0x00100000 /* 1M   */ 
EXT_FILES_B     (rx) : ORIGIN = 0x6C100000, LENGTH = 0x1F0 0000 /* 31M  */
}


/* Example for a board with a single 32MB flash chip with 1MB XiP: */
MEMORY
{
PROGRAM_FLASH   (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 /* 256K */
EXT_PGM_FLASH_A (rx) : ORIGIN = 0x04000000, LENGTH = 0x00100000 /* 1M   */ 
SRAM_LOWER     (rwx) : ORIGIN = 0x1fff0000, LENGTH = 0x00010000 /* 64K  */
SRAM_UPPER     (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000 /* 192K */
XIP_RESERVE_A   (rx) : ORIGIN = 0x68000000, LENGTH = 0x00100000 /* 1M   */ 
EXT_FILES_A     (rx) : ORIGIN = 0x68100000, LENGTH = 0x01F00000 /* 31M  */
}

 

 

 

 

 

 

  

 

 

0 Kudos