cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Visitor
Visitor
560 Views
Registered: ‎12-04-2018

OCM access conflict on ZYNQ7020

Jump to solution

Hello,

I want to setup two ARM cores' system on ZYNQ7020. OCM will be shared memory between two ARMs to exchange signals. So I design a simple testing to verify access conflict for one 32 bits as below: ***********************************************************************

ARM0:

... //wakeup ARM1 code

while(nFlag == 0)

{

nFlag = *(volatile unsigned int*)(OCM_BASE_ADDR + 0x0020);

}

printf("ARM0 received signal : 0x%x \n\r",nFlag);

***********************************************************************

ARM1:

printf("ARM1 Hello World\n\r"); *(volatile unsigned int*)(OCM_BASE_ADDR + 0x0020) = 0x4567; ***********************************************************************

ARM0 enter read OCM loop immediately after it wake ARM1 up. ARM1 print firstly after wakeup, then write OCM on 32bits. The purpose is to test whether writing can be successful during reading operation by another core at the same time.

The result is:

The last block(0xFFFF0000) was ok. The data can be transmitted from ARM1 to ARM0. The first three blocks(0x00000000) sometimes were failed. ARM0 can't read out data(0x4567). However, if I add read operation after writing on ARM1 side, the data 0x4567 always be there even if ARM0 read fail.

I confused that why two parts of OCM have different behaviour and why ARM1 can read out correct data but ARM0 can't.

0 Kudos
Reply
1 Solution

Accepted Solutions
Xilinx Employee
Xilinx Employee
441 Views
Registered: ‎02-01-2008

If you right click on your function call and select something like 'go to definition' you will see the src for Xil_SetTlbAttributes(). It does setup the attribute for a block of memory. I just don't recall the size of that block. So one call for addr 0 may cover all 3 blocks.

Yes, OCM could be used for normal data exchange. There are a few address ranges to look out for. For example, the top of OCM around 0xffffff00 is used by cpu #2. This address range is a wfe loop. You could connect your debugger to cpu #2 and start single stepping to get an idea where this assembly is located. There is also a case around 0xFFFF0000 where the cpu could use this address region for a soft reset. The A9's can use LOWVEC or HIGHVEC for the vector table. Looking at fsbl linkerscript, I see:

ps7_ram_1_S_AXI_BASEADDR : ORIGIN = 0xFFFF0000, LENGTH = 0x0000FE00

So Stay away from OCM higher than 0xFFFFFE00 cause that's where some of the A9 startup code is and the wfe loop.

Normally you wouldn't use HIGHVEC so 0xFFFF0000 should be fine.

Also, check the System address map in the zynq technical reference manual. There are limitations to what masters can see OCM vs DDR at low memory.

There is a way to move all four 64KB sections of OCM to high memory such that low memory is all DDR but that's another topic. The technical ref manual also covers the high OCM and addr filter registers if you want OCM from 0xFFFC0000 to 0xFFFFFFFF

View solution in original post

0 Kudos
Reply
5 Replies
Adventurer
Adventurer
520 Views
Registered: ‎09-13-2018
Did you disable data cache ?
0 Kudos
Reply
Visitor
Visitor
495 Views
Registered: ‎12-04-2018

Yes, I thought two cores' OCM cache were disabled by Xil_SetTlbAttributes(0xFFFF0000,0x14de2); before I do writting and reading operation. However, Now I think the code only impact last OCM block, it doesn't touch the first three blocks. I try to test by below two kinds of method:

  1. Add 'Xil_DCacheDisable();'   and  'Xil_ICacheDisable();' to disable all the cache. The first three blocks read correctly.
  2. Add 'Xil_SetTlbAttributes(0x00000000,0x14de2); ' to disable first three blocks' cache. They read correctly.

So which method do you recommend?

What's the definition for each bit of '0x14de2'?

Thank you!

0 Kudos
Reply
Xilinx Employee
Xilinx Employee
477 Views
Registered: ‎02-01-2008

I suggest you use the SetTlbAttributes method. That will still allow your application to use cache.

You can check the ARM specs for the TLB attributes. Once upon a time I created this note:

// B3-1315 short description translation table format
//
// * B3-1317 (Section format)
//
// Using DDR OCM GP0 SRAM QSPI
// b0 b0 b0 b0 b0 b0 // [31:20] - Section base addr PA[31:20]
// b0 b0 b0 b0 b0 b0 // [19] - NS (Non Secure)
// b0 b0 b0 b0 b0 b0 // [18] - 0
// b0 b0 b0 b0 b0 b0 // [17] - nG (Not Global)
// b1 b1 b0 b0 b0 b0 // [16] - S (Sharable)
// b0 b0 b0 b0 b0 b0 // [15] - AP[2]
// b100 b101 b100 b000 b000 b000 // [14:12] - TEX[2:0] TEX Region type encoding. See the ARM Architecture Reference Manual.
// b11 b11 b11 b11 b11 b11 // [11:10] - AP[1:0]
// b0 b0 b0 b0 b0 b0 // [9] - implementation defined
// b1111 b1111 b0000 b0000 b0000 b0000 // [8:5] - Domain number of the TLB entry.
// b0 b0 b0 b0 b0 b0 // [4] - XN (execute never)
// b01 b01 b11 b00 b11 b10 // [3:2] - CB
// b1 b1 b1 b1 b1 b1 // [1] - 1
// b0 b0 b0 b0 b0 b0 // [0] - PXN
//
// 7 4 5 4 3 2 1 0
// 31:28 27:24 23:20 19:16 15:12 11:8 7:4 3:0
//
//
// page B3-1358 architecture reference manual
//
// TEX[2:0] C B Description | Memory type | Page Shareable
// 000 0 0 Strongly-ordered | Strongly-ordered | Shareable
// 1 Shareable Device | Device | Shareablea
// 1 0 Outer and Inner Write-Through, no Write-Allocate | Normal | S bitb
// 1 Outer and Inner Write-Back, no Write-Allocate | Normal | S bitb
// 001 0 0 Outer and Inner Non-cacheable | Normal | S bitb
// 1 Reserved | - | -
// 1 0 IMPLEMENTATION DEFINED | IMPLEMENTATION | IMPLEMENTATION
// | DEFINED | DEFINED
// 1 Outer and Inner Write-Back, Write-Allocate | Normal | S bitb
// 010 0 0 Non-shareable Devicea | Device | Non-shareablea
// 1 Reserved | - | -
// 1 x Reserved | - | -
// 011 x x Reserved | - | -
// 1BB A A Cacheable memory: AA = Inner attribute | Normal | S bitb
// BB = Outer attribute
// AA/BB
// 00 Non-cacheable
// 01 Write-Back, Write-Allocate
// 10 Write-Through, no Write-Allocate
// 11 Write-Back, no Write-Allocate

 

// AP[2] AP[1:0] PL1 and PL2 access Unprivileged access Description
// 0 00 No access No access All accesses generate Permission faults
// 01 Read/write No access Access only at PL1 or higher
// 10 Read/write Read-only Writes at PL0 generate Permission faults
// 11 Read/write Read/write Full access
// 1 00 - - Reserved
// 01 Read-only No access Read-only, only at PL1 or higher
// 10 Read-only Read-only Read-only at any privilege level, deprecateda
// 11 Read-only Read-only Read-only at any privilege levelb

0 Kudos
Reply
Visitor
Visitor
456 Views
Registered: ‎12-04-2018

@johnmcd Thanks a lot for your clear answer!

Could you help clarify one more things?

1. 'Xil_SetTlbAttributes(0x00000000,0x14de2);' can impact all of first 3 blocks? I needn't to set 'Disable' by other address like as'Xil_SetTlbAttributes(0x00010000,0x14de2);' and 'Xil_SetTlbAttributes(0x00020000,0x14de2);'?

2. After setting 'Disable' during init stage, the address(0x00000000 and 0xFFFF0000) space of OCM can be used normally for data exchange. Am I right?

0 Kudos
Reply
Xilinx Employee
Xilinx Employee
442 Views
Registered: ‎02-01-2008

If you right click on your function call and select something like 'go to definition' you will see the src for Xil_SetTlbAttributes(). It does setup the attribute for a block of memory. I just don't recall the size of that block. So one call for addr 0 may cover all 3 blocks.

Yes, OCM could be used for normal data exchange. There are a few address ranges to look out for. For example, the top of OCM around 0xffffff00 is used by cpu #2. This address range is a wfe loop. You could connect your debugger to cpu #2 and start single stepping to get an idea where this assembly is located. There is also a case around 0xFFFF0000 where the cpu could use this address region for a soft reset. The A9's can use LOWVEC or HIGHVEC for the vector table. Looking at fsbl linkerscript, I see:

ps7_ram_1_S_AXI_BASEADDR : ORIGIN = 0xFFFF0000, LENGTH = 0x0000FE00

So Stay away from OCM higher than 0xFFFFFE00 cause that's where some of the A9 startup code is and the wfe loop.

Normally you wouldn't use HIGHVEC so 0xFFFF0000 should be fine.

Also, check the System address map in the zynq technical reference manual. There are limitations to what masters can see OCM vs DDR at low memory.

There is a way to move all four 64KB sections of OCM to high memory such that low memory is all DDR but that's another topic. The technical ref manual also covers the high OCM and addr filter registers if you want OCM from 0xFFFC0000 to 0xFFFFFFFF

View solution in original post

0 Kudos
Reply