I've been working on code to test the speed of the APIC using the PIT. There are several problems I can't figure out. First, when testing my ISRs for the two timers, I get general protection faults on the iretq instructions. Second, neither timer actually fires any interrupts. Any help on this would be much appreciated.
Link to the relevant file.
The general protection faults were caused by having an invalid CS register due to not reloading the CS register after loading the GDT. It's not in the code I linked to at all.
Related
I am using NUCLEO-H755ZI-Q board, Which has two cores cortex m4 and cortex m7, To enable the lwip I have to enable CPU ICache and CPU DCache
But during runtime the program exits through SCB_EnableDCache(); function. Kindly help me if had missed something.
I was able to resolve this issue. this was more specific to cube ide 1.7 when i rolled back to 1.6 it was working fine. Issue is with the code generation from cube mx
Reference from CMSIS-Core, the description for __STATIC_FORCEINLINE void SCB_EnableDCache(void)
Before enabling the data cache, you must invalidate the entire data
cache SCB_InvalidateDCache(), because external memory might have
changed from when the cache was disabled. After reset, you must
invalidate SCB_InvalidateDCache() each cache before enabling it.
So I think you can try to SCB_InvalidateDCache() before SCB_EnableDCache().
On the other hand, can you provide the error message or the state of the error?
I think that helps figure out the root cause.
I encountered the following issue while using Keil MDK 5 for STM32H743.
I had a communication problem with my SPI code and after a while I found out that it was due to the Periodic Windows Update.
When it is activated, it seems that the debugger is reading regularly the SPI data register, which reads the FIFO (so changes the state of the FIFO). Consequently when the software reads the FIFO, some bytes have been "lost" (or consumed by the debugger).
Is it an expected behaviour ? Do you know if it is due to Keil or to the STM32 ?
I don't fully understand how an access from the debugger to a register is working: I guess there is a read command sent over SWD but then, internally does the access to memory go through AHB / APB like for code executing on the CPU ?
Any registers that modify behaviour by being read (such as clearing status bits) can be problematic when debugging and the registers are shown in the debug window.
The best bet is to only look at the registers when you stop (close the DR window for the peripheral), and always be aware that you may clear status bits etc.
It is the way the processor works and nothing to do with the debugger.
It is a very common debug issue with serial comms etc.
if you have DR display in your watch window (or any other similar windows on the debugger screen) and you step through the code every time you step (or generally break) the data is read.
That is the only possible reason.
My understanding is that a non-maskable interrupt enforces context switching (which causes a process to be moved from CPU to ready queue). If the interrupt happens at a time when the process is executing its critical section, it may make the output indeterministic. One solution is to roll back to the state when the process entered the critical section, but I don't know if that is possible. Please help clarify this. Thanks in advance!
If there would be a way that roll back would happen, I honestly do not know.
Yes, there is ways of doing so by software of course, the developer could implement guards in his/her code to check if there is an anomaly if so they are will repeat the process again to avoid the corrupted data.
I need to implement a multitasking system with MPU for ARM Cortex M3/M4 processors.
In that system, there will be a Kernel which manages resource in Privileged mode and user applications in Unprivilege mode. And I want to seperate User Application from rest of it and system resources.
Therefore, when I switch to a new task, I am releasing Stack and Global Memory area of user application.
It can be done easily using ARM Cortex MPU registers.
But problem is that, when a context switching is occurred, I need to use also some global variables of Kernel.
For example, I am calling a function to get next TCB in PendSV Handler during context switching but task pool is out of user app area and it is protected from user application.
So, it seems there should be balance, right? What are the secure and efficient strategies for memory protection?
Privilieged mode can be raised before context switching when Yield function is called but it does not seem a good solution.
What are the general strategies on that issue?
Perhaps you might take a look at an existing open source implementation and see what design decisions were made there. FreeRTOS for example has Cortex-M MPU support here; it may not answer your exact question directly and you may have to inspect the source code to get complete details.
Possibly divide the data memory into three regions - user, kernel and shared.
I have these options in my homework. I will explain my reason and I hope someone can critique them?
Indicate whether the following CPU instructions are the user-only or the O/S only or both?
Execution of 'sleep' instruction that halts CPU execution
user-only because I've only seen programmers writing sleep
Loading the 'program counter' PC register with a new memory address
I think it's O/S only.
Reading of disk controller register
O/S only.
'trap' that generates interrupt
From what I understand trap is usually a user-program fault and since O/S is a software application, so probably BOTH
Loading of alarm timeout value into clock register
O/S only
Reading the processor status word PSW register
O/S only.
Loading the memory lower bounds register
O/S only
Adding the contents of two memory locations
both. O/S needs to do computation too.
I don't really understand how to make a distinction between user and O/S specific instructions. They are all essentially "user" programs..
Can someone verify these answers, tell me why I am wrong, and how to tackle these questions?
I don't really understand how to make a distinction between user and O/S specific instructions. They are all essentially "user" programs.
Here's the difference: Did you start a task to have that happen, or did it happen on its own?
Did you start a task to read from the hard drive, or did you merely instruct the OS to do so? (all device access is an OS instruction, for the most part)
Sometimes professors want you to say that "reading the hard drive is user initiated" but "preemptive multitasking by the OS is always OS initiated" or "user actions may remain in a limited state while waiting on a device to finish responding and the OS to return control in a pre-emptive multitasking OS"
These are how I interpret the answers, but if you can't find these answers in the coursework then adopting my answers won't help you any. Notice that I gave a short blurb after each to explain why I chose these things. I am not your professor and have no way to know what he/she intends, so be sure that you can understand my responses. Also, having programmed in ASM helps to answer some of these ...
Execution of 'sleep' instruction that halts CPU execution
O/S. Sleep is actually just a counter that says to skip execution for one or more cycles, and is most often modeled by an API call. This can allow the scheduler access to delay reloading the pre-empted task until many rounds later. Once again, many very basic platforms would require a NOP loop counter to even come close to emulating a sleep command.
Loading the 'program counter' PC register with a new memory address
O/S. The Program Counter register is intended to be used by the system to keep track of the current execution of a program, and during multi-process pre-emption may be used to save the current execution point of the program.
Reading of disk controller register
O/S. In general User commands do not interface the disk subsystem, although on older systems they may be accessed, often by direct register access. In more modern systems, the disk is accessed only by the O/S, and is only accessed by the User via API.
'trap' that generates interrupt
User, O/S. This is when we generate a request for the O/S to handle a situation for us, so we give up control to the internal kernel. It can also result in something returning a faulted condition.
Loading of alarm timeout value into clock register
O/S. These timers are often regarded as having system-only level access, as they are used to monitor the rest of the system. Will be generally protected in CPUs that support such protection (such as those that support ring-level execution prevention).
Reading the processor status word PSW register
User, O/S. Notably the PSW registers are system-level controlled ONLY. On rare occasion one may find a system which allows one, two or merely some of the PSW registers to be read by a user. Since these are status fields for program execution, they aren't normally required to be user readable.
Loading the memory lower bounds register
User, O/S. All memory register assignment is done through CPU commands which are directly received from the binary executable loaded into the CPUs registers. There are no restrictions (aside from changing execution ring level, in participating processors) which are particularly prevented from happening at the application level. Some device interaction may or may not be permitted, and often registers are how devices are interacted with on older hardware. Note that the base memory address may not be 0, and the O/S may intercept memory calls specifically to sandbox the application.
Adding the contents of two memory locations
User, O/S. This is a fundamental requirement of algorithm design, and is often one of the first and most basic commands designed into a CPU unit.