µTasker Forum

µTasker Forum => NXPTM M522XX, KINETIS and i.MX RT => Topic started by: m_mikula on November 21, 2007, 08:38:31 PM

Title: DMA problem
Post by: m_mikula on November 21, 2007, 08:38:31 PM
Hi,

I have enabled macros:
DMA_MEMCPY_SET and also SERIAL_SUPPORT_DMA

I use UART0 and UART1 but without DMA - params.ucDMAConfig = 0;

Now the system can't boot, and when I debugging it I identificate that system stops in function uMemcpy in line:

while (!(DMA_SR_BCR3 & DSR_DONE)) { SIM_DMA_3 };                 // wait until the transfer has terminated

Any ideas why?

Question2:
When static __interrupt__ void undef_int(void) function is called, how can I identificate from which interrupt is this function called? I use PEMICRO debbugger on my own hardware...
Title: Re: DMA problem
Post by: mark on November 21, 2007, 09:35:57 PM
Hi

Take a look at the SP5 patch list at:
http://www.utasker.com/forum/index.php?topic=40.0
Point 4 may be what you need to solve the DMA problem(?)

Below is a guide to catching simple exceptions (all exceptions end up in the undefined interrupt routine where the cause can usually be identified quite easily by stopping with the debugger)

Regards

Mark



======================================================================






A common question concerns solving problems with an exception error which has occurred when developing code on the M5223X. All exceptions are handled as an undefined interrupt (see undef_int() in M5223x.c) and the code ends up in a forever loop until the watchdog triggers and restarts the board.

When developing, the watchdog is usually deactivated and so stopping the debugger reveals that the code is running around this forever loop – but how can we identify what has happened?

Fortunately the Coldfire core gives us some very good clues. Sometimes the reason is immediately obvious but sometimes we have to act like detectives and piece the clues together to get a final picture of what happened to lead to the processor ending up in this state.

Here is an example of how such problems can be analysed.

Example 1 – address error. This happens for example when a pointer is set to an invalid address (outside of register and memory space) and an access is attempted.

Consider the following ‘silly code’
Code: [Select]
  unsigned char *silly_pointer = (unsigned char *)0x12345678;
  *silly_pointer = 0x55;

Of course no one writes such silly code on purpose but we still sometimes do it (usually indirectly) so it is a good idea to be able to debug it on the target (note that such errors are often found faster when working with the uTasker simulator, but sometimes they only occur on the target).

When this code runs the processor stops working properly and, if the watchdog is active, will reset after a short period of time. When debugging we disable the watchdog and can take a look at what has happened.

The uTasker project uses a simple catch-all interrupt to handle all unexpected exceptions:
Code: [Select]
// default interrupt handler - and undefined interrupts will arrive here
//
static __interrupt__ void undef_int(void)
{
    while (1) {}                                                         // wait here and analyse with debugger....
}
and the processor will be stuck in the while loop waiting for us to analyse its state. So this is what we do.

1. We first look at the internal processor registers which look something like this (In CodeWarrior this is opened using the menu“View | Registers”):

(http://www.utasker.com/Demos/exceptions/ex1.jpg)

The Status Register is indicating 0x2700 where the 0x0700 mask indicates that all interrupts are masked (the exception masks them). The Program Counter is indicating the present code location (in the handing routine undef_int). The Stack Pointer (A7) is indicating the address 0x20007f40, which is in SRAM and is the most important piece of information there.

2. We open a memory window (displaying long words) to see what the stack content is. In CodeWarrior this is performed by clicking on the right mouse button and choosing “View Memory”.

(http://www.utasker.com/Demos/exceptions/ex2.jpg)

0x20007F40 is not of great interest to use, it is the result of the first instruction in the exception routine (link a6, #0) which copies the original content of a6 to the stack (it was 0x20007FBC) and then puts the stack pointer on entry to the routine in a6 before decrementing by 4. (a6 is usually used by sub-routines as a local stack pointer).
Also the following 0x00002000 is a consequence of the handler routine which has performed strldsr  #0x2700 to mask all interrupts (saving the original SR on stack)

The next long word values are much more important:
0x48082000
0x0000df22

This is the exception stack consisting of useful information about the exception – the exception stack is detailed in the Coldfire Core documentation and an overview is to be found in the M5223X users’ manual in chapter 3.3.3.1.

The first long word can be interpreted as follows:
FORMAT mask = 0xf0000000 so the format is = 0x4
STATUS REGISTER mask = 0x0000ffff so the status register was 0x2000
VECTOR mask = 0x03fc0000 so the vector was 0x02 (from the Exception Vector Assignments table 3-5, this is “Access Error”.
FAULT STATUS mask = 0x0c030000 so the fault status was 0b1000 (this is a bit trickier because the bits are spread out and have to be grouped again) and from Fault Status Encodings table 3-7 this is interpreted as “Error on Operand Write”.

The next long word is the address that the PC was at when the fault occurred.

So this tells us that when the PC was ‘just before’ 0x0000df28 when it made an error on Operand write – it was neither from within an interrupt routine nor in a protected code region since the SR doesn’t show any interrupt mask bits set.

3. If you look at the call stack it ‘attempts’ to show the way that the processor got to this location:

(http://www.utasker.com/Demos/exceptions/ex3.jpg)

Sometimes it is very accurate but sometimes it can have problems with exceptions (especially when one exception results in another, which is a more tricky case…). Here is shows that the path was via main(), then uTaskerSchedule() but then is seems to have difficulties with the exact location of the offending instruction.
We do the following to get to the line of code:
Set the value of the PC to 0x0000df28 and display the code in mixed mode (source and assembler) – at the bottom of the editor window of the file it is in, you can choose between ‘source, assembler and mixed’.

(http://www.utasker.com/Demos/exceptions/ex4.jpg)

Now the offending line of code is clear.
0000DF1C: 13C012345678    move.b   d0,0x12345678 (0x12345678)
This is the line which is trying to copy the content of d0 (0x00000055) to the invalid address 0x12345678.


Title: Thanks!!!
Post by: m_mikula on November 21, 2007, 10:16:02 PM
Thanks, your answer help me very much...

You have been right with DMA problem... I added some additional functions to boot loader, so I need three blocks for BL. So I want to ask if value "#0x161" will work with this configuration. Now it seems that everithing work fine, but I want to be sure...

So thanks, now I'm back in the game :)
Title: Re: DMA problem
Post by: mark on November 21, 2007, 11:37:51 PM
Hi

0x121 is the normal FLASHBAR configuration:
    0x100 is write protected (which can not be removed) – 0x020 is CPU space access enabled - 0x001 is Valid

0x161 has an additional otherwise undocumented bit set:
    0x040 - disables "Speculation Address Qualification"

This is best left until your are sure that the chip that you are using is not affected by the "Speculation Address Qualification" error in the first M5223X chips produced. See the latest errata wich explains this and may give details about how to find out whether your chip has the bug or not. Disabling "Speculation Address Qualification" will ensure that there are no problems when code is running from FLASH but can cause the device to run slightly slower (if and how much slower depends on the code itself but Freescale writes that it may be up to 9% slower).

With 0x161 you can not go wrong...

Regards

Mark