cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
sergant
Newbie
Newbie
1,146 Views
Registered: ‎07-31-2019

Writing bytes on AXI error

Hello everyone!

We're developing a project on ZYNQ-7000. In FPGA has been created some registers, and mapped in memory. We use it for tunning fpga alogorithms. We've been working for a long time and now unexpectedly ran into a problem when enabled optimizing switches in gcc compiler. It turned out that the data in the registers are not written correctly. I managed to fix the problem in a simple assembly example. So, the problem occurs unly when I store 1 or 2 bytes. In 4 bytes storing everething is ok in my test, but I'm not sure will problem not appear again. Unfortunately, our fpga developer has quited, and we can't tune fpga code fine. I'm a software developer, and I can work with this register by 4 bytes only. Can anybody answer, will writes correct in this case, or we must to dig deeper in AXI?

 

BOOST_AUTO_TEST_CASE(bus_error_asm)
{
   using namespace m5;
   using namespace m5::registry;

   static const size_t registry_memory_address = 0x4000000;
   static const size_t registry_memory_size    =   4000000;

   util::physical_memory   registry_mem_{registry_memory_address, registry_memory_size};
   fpga_registry_driver    registry_{registry_mem_.get().addr, false};

   asm volatile(
      "movw	r3, 0x5678                 \n\t" // Set in r3 value 0x5678
      "strh	r3, [%[mem1_ptr], #0]      \n\t" // Store from r3 value to mem1_ptr
      "movw r3, 0x4321                 \n\t" // Set in r3 value 0x4321
      "strh  r3, [%[mem2_ptr], #0]      \n\t" // Store from r3 value to mem2_ptr
      "movw	r3, 0                 \n\t" // Set in r3 value 0
      "strh 	r3, [%[mem1_ptr], #2]      \n\t" // Store from r3 value to mem1_ptr
      "strh 	r3, [%[mem2_ptr], #2]      \n\t" // Store from r3 value to mem2_ptr
            // Here, in mem1_ptr is 0x4321, not 0x5678
   :
   :
      [mem1_ptr] "r" (&registry_.dsp_board()->board[0].low_amp),
      [mem2_ptr] "r" (&registry_.dsp_ctrl_common()->stable_period_diff)
   :
      "r3", "memory"
   );

   BOOST_CHECK_EQUAL(registry_.dsp_board()->board[0].low_amp, 0x5678);
   BOOST_CHECK_EQUAL(registry_.dsp_ctrl_common()->stable_period_diff, 0x4321);
}

 

0 Kudos
8 Replies
dgisselq
Scholar
Scholar
1,133 Views
Registered: ‎05-21-2015

Are the failing writes unaligned writes?

Dan

0 Kudos
sergant
Newbie
Newbie
1,126 Views
Registered: ‎07-31-2019

Not only. Aligned writes fails too, if after that I do an analigned write in the same word.

movw r3 #value1
strh r3 [%[aligned_ptr1]]         <--- aligned write, but in *aligned_ptr1 will be value2 instead of value1
movw r3 #value2
strh r3 [%[aligned_ptr2]]
movw r3 #0
strh r3 [%[aligned_ptr1] #2]    <--- analigned write

I have to check single analigned writes.

0 Kudos
dgisselq
Scholar
Scholar
1,120 Views
Registered: ‎05-21-2015

Not quite my question.

The examples you show above are where a half word directly maps to the 32-bits on a bus.  An unaligned half-word write would be to an offset of 3 from the word boundary, not 0, 1, or even to since all of these fit within a single bus "beat".

Dan

0 Kudos
dgisselq
Scholar
Scholar
1,110 Views
Registered: ‎05-21-2015

One other thing to look for ... in many common AXI-lite implementations, to include all of those generated from the VIvado demonstration code I've examined, there's a write-after-write bug which will drop the second write.  Could that be what's going on here?

Feel free to check out this article for more details.

Dan

0 Kudos
numbat
Adventurer
Adventurer
846 Views
Registered: ‎04-27-2011

I'm running into the same problem. Unaligned writes using strh to M_AXI_HPM0_LPD (32 bits wide) on a Zynq UltraScale+ MPSoC trigger a processor fault (Cortex-R5 #0, baremetal).

This is happening inside memcpy() in a SDK 2018.2 installation:

0013a5d2:   beq.n   +16     ; addr=0x0013a5e6: memcpy + 0x0000009a
0013a5d4:   lsls    r2, r2, #31
0013a5d6:   itt     ne
0013a5d8:   ldrbne.w r3, [r1], #+1
0013a5dc:   strbne.w r3, [r0], #+1
0013a5e0:   bcc.n   +2      ; addr=0x0013a5e6: memcpy + 0x0000009a
0013a5e2:   ldrh    r3, [r1, #0]
0013a5e4:   strh    r3, [r0, #0] ; <- r0 contains 0x98000075, this triggers a jump to DataAbortHandler in the vector table
.section .vectors, "a"
_vector_table:
	ldr	pc,=_boot
	ldr	pc,=Undefined
	ldr	pc,=SVCHandler
	ldr	pc,=PrefetchAbortHandler
	ldr	pc,=DataAbortHandler
	NOP	/* Placeholder for address exception vector*/
	ldr	pc,=IRQHandler
	ldr	pc,=FIQHandler

The call was memcpy(0x98000000, &valid_data, 119);

Stacey

0 Kudos
numbat
Adventurer
Adventurer
833 Views
Registered: ‎04-27-2011

I'll just add that unaligned writes work correctly with the strb instruction.

Stacey
0 Kudos
dgisselq
Scholar
Scholar
757 Views
Registered: ‎05-21-2015

Of course!  There's no such thing as an unaligned byte-wise operation.  That's because all single byte transactions are automatically aligned, since there's no way to create an unaligned byte transaction.

Halfwords can be unaligned if one part of the word falls on one bus word, and the other part falls on another bus word.  For example, with a 32-bit bus, if you try to write to byte 3 and 4.  Byte 3 will  be issued in the first write beat, and byte 4 in the second write beat.  The problem only gets worse with full word writes.

Dan

0 Kudos
numbat
Adventurer
Adventurer
747 Views
Registered: ‎04-27-2011

Indeed. My followup was directed to anyone trying to work around this bug with the SDK 2018.2 memcpy to an external AXI bus on an Ultrascale+ Zynq part.

Stacey

0 Kudos