LizardLad_1
Posts: 126
Joined: Sat Jan 13, 2018 12:29 am

Taking exception 3 [Prefetch Abort]

Tue Sep 11, 2018 11:27 am

Hello all,

I am not sure of the cause of this error. I know it only occurs when I turn the MMU on and without it the error doesn't occur. I would like to find this bug myself so the information may be a bit vague ask for clarification if it is needed. When I execute the program in qemu the program doesn't print out the exception cause as it should, QEMU prints out Taking exception 3 [Prefetch Abort] with the cause located at the same address as the target address. This means the error is recursive in my vector table. I'm not sure yet exactly what this error means but if you can help it would be greatly appreciated.

LdB
Posts: 910
Joined: Wed Dec 07, 2016 2:29 pm

Re: Taking exception 3 [Prefetch Abort]

Tue Sep 11, 2018 11:54 am

Pretty sure it is telling you that you the address is invalid to the MMU.

Now there is something really weird with init_audio_jack which may be related.

init_audio_jack has no return or end to the code block.
If you intended it to just run into the play code then that code shouldn't be in it's own section.

You get what can happen don't you the linker may well put "play_audio" in a totally different place to " init_audio_jack" because they aren't in the same section and the linker can't see they are connected. Then init_audio_jack would then drop thru into whatever gets stuck after it by the linker.

You need to completely rethink that block it's crazy at the moment, if they are connected they need to be in the same section. Alternatively init_audio_jack needs a return.

Also found another obvious address problem which you repeat a number of times

Code: Select all

mov w0,PERIPHERAL_BASE + GPIO_BASE  // you load the value of w0
str w1,[x0,GPIO_GPFSEL4]   // but then use x0 as an address ... what makes you think upper part of x0 is zero
Pretty sure it should be

Code: Select all

mov x0,PERIPHERAL_BASE + GPIO_BASE  //  load the value into x0
You also seem to run over x0 in the next few lines of code , pretty sure the "//set clock" is bad

Why don't you convert the code to C I am sure it would be a lot safer :-)

If you need me to convert Peter Lemons code just tell me which one you want.

LdB
Posts: 910
Joined: Wed Dec 07, 2016 2:29 pm

Re: Taking exception 3 [Prefetch Abort]

Tue Sep 11, 2018 1:28 pm

Haha I found which one of Peter's code you used .. here is the proper conversion for init_audio_jack WITH A RETURN and it all works correctly now :-)

I can play your music fine by sending core2 to play_audio or just use core0 to play it after the render (core0 deadloops obviously). Not sure if it's my speakers but volume is low.

Code: Select all

.section .text.init_audio_jack, "ax", %progbits
.balign	4
.globl init_audio_jack;
.type init_audio_jack, %function
init_audio_jack:
	mov x0,PERIPHERAL_BASE + GPIO_BASE
	mov w1,GPIO_FSEL0_ALT0
	orr w1,w1,GPIO_FSEL5_ALT0
	str w1,[x0,GPIO_GPFSEL4]

	// Set Clock
	mov w0,(PERIPHERAL_BASE + CM_BASE) & 0x0000FFFF
	mov w1,(PERIPHERAL_BASE + CM_BASE) & 0xFFFF0000
	orr w0,w0,w1
	mov w1,CM_PASSWORD
	orr w1,w1,0x2000 // Bits 0..11 Fractional Part Of Divisor = 0, Bits 12..23 Integer Part Of Divisor = 2
	str w1,[x0,CM_PWMDIV]

	mov w1,CM_PASSWORD
	orr w1,w1,CM_ENAB
	orr w1,w1,CM_SRC_OSCILLATOR + CM_SRC_PLLCPER // Use 650MHz PLLC Clock
	str w1,[x0,CM_PWMCTL]

	// Set PWM
	mov w0,(PERIPHERAL_BASE + PWM_BASE) & 0x0000FFFF
	mov w1,(PERIPHERAL_BASE + PWM_BASE) & 0xFFFF0000
	orr w0,w0,w1
	mov w1,0x2C48 // Range = 13bit 44100Hz Mono
	str w1,[x0,PWM_RNG1]
	str w1,[x0,PWM_RNG2]

	mov w1,PWM_USEF2 + PWM_PWEN2 + PWM_USEF1 + PWM_PWEN1 + PWM_CLRF1
	str w1,[x0,PWM_CTL]
	ret
	
Also don't forget to set the value of x0 in the play_audio as it now doesn't come in from the setup so like this :-)

Code: Select all

.section .text.play_audio, "ax", %progbits
.balign	4
.globl play_audio;
.type play_audio, %function
play_audio:
	mov x0,PERIPHERAL_BASE + GPIO_BASE
	mov w0,(PERIPHERAL_BASE + PWM_BASE) & 0x0000FFFF
	mov w1,(PERIPHERAL_BASE + PWM_BASE) & 0xFFFF0000
	orr w0,w0,w1

	Loop:
		adr x1, _binary_src_audio_Interlude_bin_start // X1 = Sound Sample
		ldr w2, =_binary_src_audio_Interlude_bin_end
		and w2, w2, 0x0000FFFF // W2 = End Of Sound Sample
		ldr w3, =_binary_src_audio_Interlude_bin_end
		and w3, w3, 0xFFFF0000
		orr w2,w2,w3
		FIFO_Write:
			ldrh w3,[x1],2 // Write 2 Bytes To FIFO
			lsr w3,w3,3 // Convert 16bit To 13bit
			str w3,[x0,PWM_FIF1] // FIFO Address
			
			ldrh w3, [x1], 2
			lsr w3, w3, 3
			str w3, [x0, PWM_FIF1]
		FIFO_Wait:
			ldr w3,[x0,PWM_STA]
			tst w3,PWM_FULL1 // Test Bit 1 FIFO Full
			b.ne FIFO_Wait
		cmp w1,w2 // Check End Of Sound Sample
		b.ne FIFO_Write
	b Loop // Play Sample Again

User avatar
Ultibo
Posts: 139
Joined: Wed Sep 30, 2015 10:29 am
Location: Australia
Contact: Website

Re: Taking exception 3 [Prefetch Abort]

Tue Sep 11, 2018 11:50 pm

LizardLad_1 wrote:
Tue Sep 11, 2018 11:27 am
I would like to find this bug myself so the information may be a bit vague ask for clarification if it is needed.
Yes, the only way to truly understand what is happening is to work it out yourself, no matter how painful and tedious that may be ;).
LizardLad_1 wrote:
Tue Sep 11, 2018 11:27 am
I'm not sure yet exactly what this error means but if you can help it would be greatly appreciated.
A prefetch abort commonly relates to the CPU attempting to execute code in an area of memory that is either not marked as executable or not marked as readable, so as an example you may have a function pointer that points to something other than code and trying to call that function generates the prefetch abort.

On the other hand a data abort normally relates to trying to read or write data that is located in an area of memory that is either not readable or not writable.

It only occurs when the MMU is on because without it all memory is readable, writable and executable.
Ultibo.org | Make something amazing
https://ultibo.org

Threads, multi-core, OpenGL, Camera, FAT, NTFS, TCP/IP, USB and more in 3MB with 2 second boot!

LizardLad_1
Posts: 126
Joined: Sat Jan 13, 2018 12:29 am

Re: Taking exception 3 [Prefetch Abort]

Wed Sep 12, 2018 4:58 am

I figured out the exception occurs in the mmu_init function with the last call setting the sctlr_el1 register.I believe the memory to all be readable and executable so I'm not sure what the problem is.

LdB
Posts: 910
Joined: Wed Dec 07, 2016 2:29 pm

Re: Taking exception 3 [Prefetch Abort]

Wed Sep 12, 2018 7:40 am

I believe you are probably having the issue bzt had the qemu emulation is different to the hardware case.
Your MMU is coming online on real silicon without issue, the only problem it is creating was it stops your render working (the whole cache coherency thing again) and it stops the sound working which I am guessing will be same issue or needs a memory barrier somewhere.
Your debugger code isn't triggering at all that I can see and the only abort I was getting was off that sound code.

However I would also like to offer a suggestion that you start building it up one bit at a time at as there are numerous errors that need to be fixed. There are still serious issues with stuff that should have been long since dealt with like only half a vector table and your debugger code still doesn't comes up on the screen properly. Cut it back to the bare essentials and get everything working properly.

if it helps ... put the kernel8.img file on your SD ... I fixed the cache issues :-)
https://github.com/LdB-ECM/Exchange/tre ... MwithUART2
That is your MMU code engaged, with your sound playing on core 2 while getting the VC4 to rotate graphics with core0 and no there is no problems with it ... works perfectly.

I didn't bother using your start.s because the vector table links in all this other stuff and I was too lazy to use your library I just used GCC standard. I will see if I can bring Eric Anholts VC4_plane merger code online and merge your graphics text onto the renderbuffer.
You can't really afford to write text to the render buffer even though its valid to do so ... it's too slow and it will get the flashes up. What you want to do is merge your text buffer onto the render buffer like when it starts up and has the text and render on same screen.

User avatar
Ultibo
Posts: 139
Joined: Wed Sep 30, 2015 10:29 am
Location: Australia
Contact: Website

Re: Taking exception 3 [Prefetch Abort]

Wed Sep 12, 2018 11:47 pm

LizardLad_1 wrote:
Wed Sep 12, 2018 4:58 am
I figured out the exception occurs in the mmu_init function with the last call setting the sctlr_el1 register.I believe the memory to all be readable and executable so I'm not sure what the problem is.
If the exception happens immediately after enabling the MMU it would tend to indicate that something is incorrect with your page tables or MMU configuration. The next instruction after enabling the MMU will be fetched using the new configuration so if anything is wrong it will fail very quickly.

The full details of setting up and enabling the MMU are found throughout the ARM manuals but a very rough outline of the steps required is:

Step 0: (as soon as possible after boot) Invalidate entire L1 cache (and the entire L2 cache if running on CPU0)

Step 1: Create page tables
Step 2: Ensure data and instruction caches are disabled
Step 3: Invalidate entire TLB
Step 4: Setup registers (TTBR etc)
Step 5: Perform instruction barrier
Step 6: Enable data and instruction caches and enable MMU
Step 7: Perform instruction barrier

Of course step 4 includes a whole world of choices and options that cover many pages of the manuals.
Ultibo.org | Make something amazing
https://ultibo.org

Threads, multi-core, OpenGL, Camera, FAT, NTFS, TCP/IP, USB and more in 3MB with 2 second boot!

LizardLad_1
Posts: 126
Joined: Sat Jan 13, 2018 12:29 am

Re: Taking exception 3 [Prefetch Abort]

Fri Sep 28, 2018 8:32 am

Hello all,

I know I have left this thread for a while however I would like to ask LdB I have fixed the half vector table however as you stated there were numerous errors that required correction before I go further. Would you please list these mistakes as apart from the dodgy interrupt table I thought my code was fairly solid. Another thing how were you using the GNU standard libm?

EDIT 1:
Thanks for fixing the coherency issues LdB. I was looking at your CoreExecute Function however I'm struggling to understand it. I know what it does and why it's required but I don't understand how. You also state in your comments it returns nothing, if it returns nothing your core execute fail is redundant because there isn't any return value visible to the calling function.

LdB
Posts: 910
Joined: Wed Dec 07, 2016 2:29 pm

Re: Taking exception 3 [Prefetch Abort]

Sun Sep 30, 2018 3:37 pm

LizardLad_1 wrote:
Fri Sep 28, 2018 8:32 am
I know I have left this thread for a while however I would like to ask LdB I have fixed the half vector table however as you stated there were numerous errors that required correction before I go further. Would you please list these mistakes as apart from the dodgy interrupt table I thought my code was fairly solid.
I will need to go back over it as was a few weeks ago to go thru it again .. I will pick it up in later post.
LizardLad_1 wrote:
Fri Sep 28, 2018 8:32 am
Another thing how were you using the GNU standard libm?
What is the actual question ... why are you thinking the standard library couldn't be used?

Typically the only standard libraries you can't use straight up in baremetal are the ones that use memory allocation or file IO because there is no implementation. The memory system is usually trivial it can vary from 20 lines of code for a simple scheme to a few hundred for a full blown scheme. The file IO system which covers "stdio" etc is far more complex and mostly we implement what we need.
LizardLad_1 wrote:
Fri Sep 28, 2018 8:32 am
Thanks for fixing the coherency issues LdB. I was looking at your CoreExecute Function however I'm struggling to understand it. I know what it does and why it's required but I don't understand how. You also state in your comments it returns nothing, if it returns nothing your core execute fail is redundant because there isn't any return value visible to the calling function.
Rather than answer your question directly what I did I want to give you a generic answer because there is no 1 solution. What you are basically trying to do communicate between the cores and this is where it gets tricky and there is no 1 idea or best solution, every solution has pros and cons.

So lets talk about some O/S and we a switching between "thingos" .. now I use the term "thingos" because I don't want to call the tasks, processes, fibres etc because they all have specific meanings to particular systems. So a thingo does some work and our O/S must roll thru those thingos on some sort of scheduler and however we try and organize it the cores will need to communicate, so lets get to the why. At some point when inside a scheduler you will need to access a table or something that each and every core use. Lets take the obvious one of the core wants to terminate a thingo but the other cores are helping with the thingo. What we have is a thing called a Kernel Critical Section that one core needs to stop all other cores using the thingo.

Now to the specific answer you usually can't pass a result back from the call because how long should it wait for the response????
The other core(s) is doing stuff and when asked to halt use of a thingo, worst case perhaps the thingo crashed the core or it's stuck on an IO that has faulted ... in which case it's never going to respond. So if you start relying on responses you have a very fragile O/S.

Ideally what you want to happen is when one core needs the other cores to obey a message that as soon as a core acknowledges the message it starts on whatever changed processing then exists. A core not responding after a certain amount of time has all it's thingos released and the core restarted to join all the rest of the cores again. Now it turns out that is not just the behaviour wanted on a multicore system it is also the behaviour wanted on a single core with a switcher "thingo" system. So there is no response back because it would be rare to ever do it, generally that is a bigger picture system problem.

So my example with your code is only half a system don't try and read it as full solution.

Now specifically on the Pi there is physical hardware mailboxes and irq between the cores and you can setup a basic SMP (https://en.wikipedia.org/wiki/Symmetric_multiprocessing). It's the easiest system and plenty of samples out on the net and comes with plenty of problems. At the other end of the scale is MPICH used by 9/10 of the worlds fastest supercomputers and it's a completely software system involving the cores but it can be complex (https://www.mpich.org/)

So there is a vast range of answers between those extremes and I need to know how are you going to setup your specific O/S.

LizardLad_1
Posts: 126
Joined: Sat Jan 13, 2018 12:29 am

Re: Taking exception 3 [Prefetch Abort]

Mon Oct 01, 2018 9:11 am

LdB wrote:
LizardLad_1 wrote:
Fri Sep 28, 2018 8:32 am
Another thing how were you using the GNU standard libm?
What is the actual question ... why are you thinking the standard library couldn't be used?

Typically the only standard libraries you can't use straight up in baremetal are the ones that use memory allocation or file IO because there is no implementation. The memory system is usually trivial it can vary from 20 lines of code for a simple scheme to a few hundred for a full blown scheme. The file IO system which covers "stdio" etc is far more complex and mostly we implement what we need.
I haven't been able to use any system headers and I don't know how to use aarch64-*-gcc or ld to link libm to an executable for a bare metal environment. I would think you have to statically link libm but I can' t find the gnu standard libraries for aarch64 in the repositories. I am running Fedora 28 with the rpmfusion repositories enabled. It may be a compiler misconfiguration but I'm not sure. Thanks to any help you can provide.

LdB
Posts: 910
Joined: Wed Dec 07, 2016 2:29 pm

Re: Taking exception 3 [Prefetch Abort]

Mon Oct 01, 2018 10:24 am

Your answer is a little muddled and I need to check something FEDORA linux may be your O/S but that is of no relevance as you are cross compiling to the Pi. The only relevance your O/S has is that you have the right GCC binaries that work on your O/S that is they are linux executables.

The version of GCC setup for baremetal are usually called aarch64-elf or aarch64-none. There is a couple of subtle library differences between the two with libraries but either will work.

So lets say you wanted to install GCC 7.3.1 you would go to a distribution lets pick linaro
https://releases.linaro.org/components/ ... rch64-elf/

The explaination for the names is here .. you can see you want baremetal
https://www.linaro.org/latest/downloads/
You can see they tell you the directories contain
Both x86_64 Linux and Mingw32 (MS Windows compatible) host binaries are provided:
So if your fedora linux version is 32bit you would choose
gcc-linaro-7.3.1-2018.05-i686_aarch64-elf.tar.xz
So if your fedora linux version is 64 bits you would choose
gcc-linaro-7.3.1-2018.05-x86_64_aarch64-elf.tar.xz

So be clear the 32bit is referring to your O/S it is the format of the binaries nothing to do with code you will output from compiling.

So extract the right binary (32 or 64 bit) to a directory
Now in your makefile you call the executables in that directory and that executable will use the baremetal AARCH64 libraries in that directory. It picks them on a relative path so you don't need to do anything other than extract them all in the directory and call the binary (it knows the library directories from the binary location in the bin directory). So it has no relevance to your normal fedora compiler that it would have installed.

I suspect you are using your normal fedora compiler as you found out if you use your normal fedora compiler you would need to disconnect the libraries and provide replacements. In many cases for cross compiling your compiler wouldn't even support the targetted CPU which is another reason you don't do it that way. There are long elaborate ways to install a baremetal library etc but it's far faster and easier just to install a whole other compiler directory not related to your normal compiler :-)

LizardLad_1
Posts: 126
Joined: Sat Jan 13, 2018 12:29 am

Re: Taking exception 3 [Prefetch Abort]

Sun Oct 07, 2018 1:23 am

Just an update on the original problem it just magically stopped occurring. This means the bug is still in there somewhere but it isn't doing anything at the moment.

LizardLad_1
Posts: 126
Joined: Sat Jan 13, 2018 12:29 am

Re: Taking exception 3 [Prefetch Abort]

Sat Oct 13, 2018 12:01 am

In reply to LdB's last comment, it turns out I was using linaro but I was using the linux targeted toolchain because that was provided by my host OS.

Return to “Bare metal, Assembly language”