Hello all!!
I'm facing a CPU interrupt every-time the initialization code created by Processor Expert is run on a KL04Z8 processor.
The function where I get the interrupt is called from the
void __thumb_startup(void)
{
// Setup registers
__init_registers();
// setup hardware
__init_hardware();
// zero-fill the .bss section
zero_fill_bss();
}
zero_fill_bss is the function where the uC gets the CPU interrupt.
Does anyone know what might be the causes for that?
If I force the CPU with something like asm("b main") from within the Fault Interrupt routine, it apprently works. But it doesn't loook good.
I appreciate your help!!
Many thanks
Hi Luiz Martins,
Where did the bss section locate in your project? The zero_fill_bss is the function to write zero to bss section, so if bss resides in some nonwritable space like flash , it would cause fault interrupt as your case. Would you please help to clarify? Thanks for your patience!
Have a great day,
Kan
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Kan,
thanks for your quick answer!!
My project is still the unmodified version of the generated code by the Processor Expert.
The lines of code in asm are those below. The interruption comes from a line "bold" at the end of the code. Please take a look.
But before i copied the zero_fill_bss function:
223 | zero_fill_bss(); |
000007c0: bl zero_fill_bss (0x794) ; 0x00000794
zero_fill_bss: | |
131 | { |
00000794: push {r7,lr}
00000796: add r7,sp,#0
139 | memset(__START_BSS, 0, (__END_BSS - __START_BSS)); |
00000798: ldr r2,[pc,#20]
0000079a: ldr r3,[pc,#24]
0000079c: subs r3,r2,r3
0000079e: ldr r2,[pc,#20]
000007a0: mov r0,r2
000007a2: movs r1,#0
000007a4: mov r2,r3
000007a6: bl memset (0x840) | ; 0x00000840 |
141 | } |
000007aa: cpy sp,r7
000007ac: pop {r7,pc}
000007ae: nop
000007b0: .short 0xfe541fff
000007b4: .short 0xfe001fff
The code where the error/interruption is called is below.
__fill_mem: //declared as void _EWL_CDECL __fill_mem(void * dst, int_t val, uint32_t n) | |
67 | { |
000016c4: push {r4-r5,lr}
134 | } |
000016c6: uxtb r1,r1
68 | uchar_t *cpd = ((uchar_t *) dst); |
000016c8: mov r3,r0
73 | if (n >= 32UL) { |
000016ca: cmp r2,#31
000016cc: bls __fill_mem+0x6e (0x1732); 0x00001732
76 | i = (uint32_t)(-(int32_t) dst) & 3UL; |
000016ce: neg r4,r0
000016d0: movs r3,#3
000016d2: ands r3,r4
77 | if :smileyinfo: { |
000016d4: beq __fill_mem+0x1e (0x16e2); 0x000016e2
78 | n -= i; |
000016d6: subs r2,r2,r3
27 | void _EWL_CDECL __fill_mem | (void * dst, int val, unsigned long n) _EWL_CANT_THROW; |
000016d8: adds r5,r0,r3
82 | deref_auto_inc(cpd) = (uchar_t)v; |
000016da: strb r1,[r0,#0]
000016dc: adds r0,#1
83 | } while (--i); |
000016de: cmp r0,r5
000016e0: bne __fill_mem+0x16 (0x16da); 0x000016da
86 if (v) {
000016e2: cmp r1,#0
000016e4: beq __fill_mem+0x2e (0x16f2); 0x000016f2
87 v |= (v << 24) | (v << 16) | (v << 8);
000016e6: lsls r5,r1,#24
000016e8: lsls r4,r1,#16
000016ea: orrs r4,r5
000016ec: lsls r3,r1,#8
000016ee: orrs r1,r4
000016f0: orrs r1,r3
97 i = n >> 5;
000016f2: lsrs r4,r2,#5
90 lpd = (uint32_t *)cpd;
000016f4: mov r3,r0
99 if ( i) {
000016f6: cmp r4,#0
000016f8: beq __fill_mem+0x54 (0x1718); 0x00001718
000016fa: mov r5,r4
111 while (--i);
000016fc: subs r5,#1
102 deref_auto_inc(lpd) = v; //This is the line where it jumps back to the interruption
000016fe: str r1,[r3,#0]
103 deref_auto_inc(lpd) = v;
00001700: str r1,[r3,#4]
104 deref_auto_inc(lpd) = v;
00001702: str r1,[r3,#8]
105 deref_auto_inc(lpd) = v;
00001704: str r1,[r3,#12]
106 deref_auto_inc(lpd) = v;
00001706: str r1,[r3,#16]
107 deref_auto_inc(lpd) = v;
00001708: str r1,[r3,#20]
108 deref_auto_inc(lpd) = v;
0000170a: str r1,[r3,#24]
109 deref_auto_inc(lpd) = v;
0000170c: str r1,[r3,#28]
Please feel free to ask any other detail or information. I appreciate it.
Many thanks again.
Do you know which interrupt you get?
(see Oh my! An Interrupt… | MCU on Eclipse and enable 'own Handler for every').
I think two things could happen:
- normal reset: then it is probably the watchdog. Is it disabled?
- hard fault (see Debugging Hard Faults on ARM Cortex-M | MCU on Eclipse and A Processor Expert Component to Help with Hard Faults | MCU on Eclipse), then it could be that you access memory out of range (wrong linker file?). I have pasted below the linker file I get with KDS V1.1.1. Do you have the same memory map (RAM/FLASH)?
MEMORY {
m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x000000C0
m_text (RX) : ORIGIN = 0x00000410, LENGTH = 0x00001BF0
m_data (RW) : ORIGIN = 0x1FFFFE00, LENGTH = 0x00000500
m_cfmprotrom (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010
}
Erich
/* ################################################################### */
/*##
/*## This component module is generated by Processor Expert. Do not modify it. */
/*## */
/*## Filename : ProcessorExpert.ld */
/*## */
/*## Project : kl04z8 */
/*## */
/*## Processor : MKL04Z8VFM4 */
/*## */
/*## Compiler : GNU C Compiler */
/*## */
/*## Date/Time : 2014-09-17, 20:54, # CodeGen: 0 */
/*## */
/*## Abstract : */
/*## */
/*## This file is used by the linker. It describes files to be linked, */
/*## memory ranges, stack size, etc. For detailed description about linker */
/*## command files see compiler documentation. This file is generated by default. */
/*## You can switch off generation by setting the property "Generate linker file = no" */
/*## in the "Build options" tab of the CPU component and then modify this file as needed. */
/*##
/*## */
/*## ###################################################################*/
/* Entry Point */
ENTRY(__thumb_startup)
/* Highest address of the user mode stack */
_estack = 0x20000300; /* end of m_data */
__SP_INIT = _estack;
/* Generate a link error if heap and stack don't fit into RAM */
__heap_size = 0x50; /* required amount of heap */
__stack_size = 0x50; /* required amount of stack */
MEMORY {
m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x000000C0
m_text (RX) : ORIGIN = 0x00000410, LENGTH = 0x00001BF0
m_data (RW) : ORIGIN = 0x1FFFFE00, LENGTH = 0x00000500
m_cfmprotrom (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into INTERNAL_FLASH */
.interrupts :
{
__vector_table = .;
. = ALIGN(4);
KEEP(*(.vectortable)) /* Startup code */
. = ALIGN(4);
} > m_interrupts
.cfmprotect :
{
. = ALIGN(4);
KEEP(*(.cfmconfig)) /* Flash Configuration Field (FCF) */
. = ALIGN(4);
} > m_cfmprotrom
/* The program code and other data goes into INTERNAL_FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} > m_text
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } > m_text
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} > m_text
.ctors :
{
__CTOR_LIST__ = .;
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
} > m_text
.dtors :
{
__DTOR_LIST__ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
} > m_text
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} > m_text
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} > m_text
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
___ROM_AT = .;
} > m_text
/* reserve MTB memory at the beginning of m_data */
.mtb : /* MTB buffer address as defined by the hardware */
{
. = ALIGN(8);
_mtb_start = .;
KEEP(*(.mtb_buf)) /* need to KEEP Micro Trace Buffer as not referenced by application */
. = ALIGN(8);
_mtb_end = .;
} > m_data
/* Initialized data sections goes into RAM, load LMA copy after code */
.data : AT(___ROM_AT)
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} > m_data
___data_size = _edata - _sdata;
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss section */
__START_BSS = .;
PROVIDE ( __bss_start__ = __START_BSS );
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
__END_BSS = .;
PROVIDE ( __bss_end__ = __END_BSS );
} > m_data
_romp_at = ___ROM_AT + SIZEOF(.data);
.romp : AT(_romp_at)
{
__S_romp = _romp_at;
LONG(___ROM_AT);
LONG(_sdata);
LONG(___data_size);
LONG(0);
LONG(0);
LONG(0);
} > m_data
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
__heap_addr = .;
__HeapBase = .;
. = . + __heap_size;
__HeapLimit = .;
. = . + __stack_size;
. = ALIGN(4);
} > m_data
.ARM.attributes 0 : { *(.ARM.attributes) }
}
Erich,
You were on the right path. Here is what I discovered:
There is a error with the MEMORY map at the m_data area. This below is the correct configuration:
MEMORY {
m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x000000C0
m_text (RX) : ORIGIN = 0x00000410, LENGTH = 0x00001BF0
m_data (RW) : ORIGIN = 0x1FFFFF00, LENGTH = 0x00000400
m_cfmprotrom (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010
}
I hope Freescale sees it and correct it ASAP.
Many thanks again for your support.
Luiz
Hi Luiz,
indeed, that linker file and memory map is wrong :-(
I have submitted a ticket (Reference KDS-171) to have this fixed asap.
Many thanks,
Erich