Hello,
We are porting our app from vxworks 6.9 to 7.
release : vxworks 7.2103
board : customized Freescale P1020RDB-PC
BSP : fsl_p1p2_2_0_2_1
The bootloader stands in the last NOR flash sector. The app contains a "reboot" action, implemented by a customized "reboot" function, which gets the bootloader entry point (0XFBFE0004) and jumps to its address. SysToMonitor abridged & commented Source follows :
STATUS sysToMonitor(int startType /* parameter passed to ROM to tell it how to boot */
)
{
FUNCPTR pRom = 0XFBFE0004; /* NORflash last sector */
int token;
token = intCpuLock();
cacheDisable(INSTRUCTION_CACHE);
cacheDisable(DATA_CACHE);
vxMsrSet(0);
mmuE500TlbDynamicInvalidate();
mmuE500TlbStaticInvalidate();
(*pRom) (startType); /* jump off to romInit.s */ => triggers EXC_OFF_INST exception
return(OK); /* in case we ever continue from ROM monitor */
}
Works fine under 6.9, doesnt work under vx7 : call to entry point triggers an "EXC_OFF_INST " exception, JTAG stepping lands in "mmuE500InstMissHandler".
Maybe changes between vxworks 6.9 & 7 TLB management described below can explain what happens.
And maybe the solution could be to modify vxworks 7 TLB initialization, to add missing NORflash PTEs, which could be the reason of the "instruction TLB miss" exception triggered when our app tries to jump in bootloader code (i.e romInit) which resides in NORflash last sector.
1) vxworks 6.9 :
- sysLib.c BSP file ("Freescale P1010RDB board system-dependent library") declares 2 arrays "sysStaticTlbDesc" and "sysPhysMemDesc" :
TLB_ENTRY_DESC sysStaticTlbDesc [] = {
/* effAddr, Unused, realAddr, ts | size | attributes | permissions */
/* TLB #0. Flash */
/* needed be first entry here */
{
FLASH_BASE_ADRS, 0x0, FLASH_BASE_ADRS,
_MMU_TLB_TS_0 | _MMU_TLB_SZ_16M | _MMU_TLB_IPROT |
_MMU_TLB_PERM_W | _MMU_TLB_PERM_X | _MMU_TLB_ATTR_I |
_MMU_TLB_ATTR_G
},
{
(FLASH_BASE_ADRS + 0x1000000), 0x0, (FLASH_BASE_ADRS + 0x1000000),
_MMU_TLB_TS_0 | _MMU_TLB_SZ_16M | _MMU_TLB_IPROT |
_MMU_TLB_PERM_W | _MMU_TLB_PERM_X | _MMU_TLB_ATTR_I |
_MMU_TLB_ATTR_G
},
/* DDR */
{
0x00000000, 0x0, 0x00000000,
_MMU_TLB_TS_0 | _MMU_TLB_SZ_1G | _MMU_TLB_PERM_W |
_MMU_TLB_PERM_X | CAM_DRAM_CACHE_MODE | _MMU_TLB_IPROT |
_MMU_TLB_ATTR_M
},
/* BCSR */
{
BCSR_BASE_ADRS, 0x0, BCSR_BASE_ADRS,
_MMU_TLB_TS_0 | _MMU_TLB_SZ_16M | _MMU_TLB_ATTR_I |
_MMU_TLB_ATTR_G | _MMU_TLB_PERM_W | _MMU_TLB_IPROT
},
{
(BCSR_BASE_ADRS + 0x1000000), 0x0, (BCSR_BASE_ADRS + 0x1000000),
_MMU_TLB_TS_0 | _MMU_TLB_SZ_16M | _MMU_TLB_ATTR_I |
_MMU_TLB_ATTR_G | _MMU_TLB_PERM_W | _MMU_TLB_IPROT
},
/* FPGA */
{
FPGA_BASE_ADRS, 0x0, FPGA_BASE_ADRS,
_MMU_TLB_TS_0 | _MMU_TLB_SZ_16M | _MMU_TLB_ATTR_I |
_MMU_TLB_ATTR_G | _MMU_TLB_PERM_W | _MMU_TLB_IPROT
},
{
(FPGA_BASE_ADRS + 0x1000000), 0x0, (FPGA_BASE_ADRS + 0x1000000),
_MMU_TLB_TS_0 | _MMU_TLB_SZ_16M | _MMU_TLB_ATTR_I |
_MMU_TLB_ATTR_G | _MMU_TLB_PERM_W | _MMU_TLB_IPROT
},
{
CCSBAR, 0x0, CCSBAR,
_MMU_TLB_TS_0 | _MMU_TLB_SZ_1M | _MMU_TLB_ATTR_I |
_MMU_TLB_ATTR_G | _MMU_TLB_PERM_W | _MMU_TLB_IPROT
},
};
int sysStaticTlbDescNumEnt = NELEMENTS (sysStaticTlbDesc);
/* macro to compose 64-bit PHYS_ADDRs */
#define PHYS_64BIT_ADDR(h, l) (((PHYS_ADDR)(h) << 32) + (l))
/*
* sysPhysMemDesc[] is used to initialize the Page Table Entry (PTE) array
* used by the MMU to translate addresses with single page (4k) granularity.
* PTE memory space should not, in general, overlap BAT memory space but
* may be allowed if only Data or Instruction access is mapped via BAT.
*
* PTEs are held, strangely enough, in a Page Table. Page Table sizes are
* integer powers of two based on amount of memory to be mapped and a
* minimum size of 64 kbytes. The MINIMUM recommended Page Table sizes
* for 32-bit PowerPCs are:
*
* Total mapped memory Page Table size
* ------------------- ---------------
* 8 Meg 64 K
* 16 Meg 128 K
* 32 Meg 256 K
* 64 Meg 512 K
* 128 Meg 1 Meg
* . .
* . .
* . .
*
* [Ref: chapter 7, PowerPC Microprocessor Family: The Programming Environments]
*
*/
PHYS_MEM_DESC sysPhysMemDesc [] = {
{
(VIRT_ADDR) PHYS_MEM_START,
(PHYS_ADDR) PHYS_MEM_START,
PHYS_MEM_SIZE,
MMU_ATTR_VALID_MSK | MMU_ATTR_PROT_MSK | MMU_ATTR_CACHE_MSK,
MMU_ATTR_VALID | MMU_ATTR_SUP_RWX | TLB_CACHE_MODE |
MMU_ATTR_CACHE_COHERENCY
},
{
(VIRT_ADDR) CCSBAR,
(PHYS_ADDR) CCSBAR,
CCSR_SIZE,
MMU_ATTR_VALID_MSK | MMU_ATTR_PROT_MSK | MMU_ATTR_CACHE_MSK,
MMU_ATTR_VALID | MMU_ATTR_SUP_RWX | MMU_ATTR_CACHE_OFF |
MMU_ATTR_CACHE_COHERENCY | MMU_ATTR_CACHE_GUARDED
},
{
(VIRT_ADDR) FLASH_BASE_ADRS,
(PHYS_ADDR) FLASH_BASE_ADRS,
FLASH_SIZE,
MMU_ATTR_VALID_MSK | MMU_ATTR_PROT_MSK | MMU_ATTR_CACHE_MSK,
MMU_ATTR_VALID | MMU_ATTR_SUP_RWX | MMU_ATTR_CACHE_OFF |
MMU_ATTR_CACHE_COHERENCY | MMU_ATTR_CACHE_GUARDED
},
{
(VIRT_ADDR) BCSR_BASE_ADRS,
(PHYS_ADDR) BCSR_BASE_ADRS,
BCSR_SIZE,
MMU_ATTR_VALID_MSK | MMU_ATTR_PROT_MSK | MMU_ATTR_CACHE_MSK,
MMU_ATTR_VALID | MMU_ATTR_SUP_RWX | MMU_ATTR_CACHE_OFF |
MMU_ATTR_CACHE_COHERENCY | MMU_ATTR_CACHE_GUARDED
},
{
(VIRT_ADDR) FPGA_BASE_ADRS,
(PHYS_ADDR) FPGA_BASE_ADRS,
FPGA_SIZE,
MMU_ATTR_VALID_MSK | MMU_ATTR_PROT_MSK | MMU_ATTR_CACHE_MSK,
MMU_ATTR_VALID | MMU_ATTR_SUP_RWX | MMU_ATTR_CACHE_OFF |
MMU_ATTR_CACHE_COHERENCY | MMU_ATTR_CACHE_GUARDED
},
};
vxworks 6.9 initializes hardware according to the following sequence :
usrInit → sysHwInit → mmuE500TlbStaticInit → mmuE500TlbStaticEntrySet → mmuPpcTlbWriteExecute(...)
I guess this creates necessary PTEs, it works fine when jumping to bootloader.
2) vxworks 7 init sequence is different :
usrRoot -> boardInit -> usrAimCpuInit -> usrCpuArchInit -> cpuE500LibInit
-> mmuE500EarlyInit
-> mmuE500StaticTlbInfoInit : seems to build mmuE500StaticTlbArray from sysPhysMemDesc
( sysPhysMemDesc is filled by vxFdtPhysMemInfoGet )
-> mmuE500TlbStaticInit : seems to build only one TLB PTE for RAM.
- no NORflash TLB seems to be created
NB1 : we cant use the vxworks 7 reboot function, as it calls freescale vx7 BSP "sysToMonitor" (implemented by qoriqReset) function, which uses the P1010 HRESET/HRESET_REQ signals, which are not used (i.e not managed by our FPGA) on our board.
NB2 : case submitted to WR already, but no help for now..
Thx in advance for any help.