jaseurq wrote on Monday, August 27, 2012:
You understand perfectly!
I have one copy of the task. When the main reinitializes everything and starts the scheduler, that task resumes from where it left off which is right before I do my jump to reinitialize everything.
Using Heap_3
I disable the tick interrupt (all interrupts for that matter) before i restart.
I am not 100% sure that the linker is performing a C flush. I will have to experiment with that to be sure what I think is happening is actually happening.
Below is the linker script. I am leaving a section of calibration request data present so my bootloader can pick it up, but that should be it.
OUTPUT_FORMAT("elf32-tradlittlemips")
OUTPUT_ARCH(pic32mx)
ENTRY(_reset)
EXTERN (_min_stack_size _min_heap_size)
PROVIDE(_min_stack_size = 0x400) ;
PROVIDE(_min_heap_size = 0) ;
INPUT("processor.o")
PROVIDE(_vector_spacing = 0x00000001);
_ebase_address = 0x9D00C000;
_ORIGINAL_RESET_ADDR = 0xBFC00000;
_RESET_ADDR = 0x9D00B000;
_BEV_EXCPT_ADDR = 0x9D00B380;
_DBG_EXCPT_ADDR = 0x9D00B480;
_DBG_CODE_ADDR = 0xBFC02000;
_GEN_EXCPT_ADDR = _ebase_address + 0x180;
MEMORY
{
startup_without_bootloader : ORIGIN = 0xBFC00000, LENGTH = 0x8
kseg0_program_mem (rx) : ORIGIN = 0x9D00D000, LENGTH = 0x72000
kseg0_boot_mem : ORIGIN = 0x9D00B490, LENGTH = 0x970
exception_mem : ORIGIN = 0x9D00C000, LENGTH = 0x1000
kseg1_boot_mem : ORIGIN = 0x9D00B000, LENGTH = 0x490
debug_exec_mem : ORIGIN = 0xBFC02000, LENGTH = 0xFF0
upgradeword : ORIGIN = 0x9D07FFF8, LENGTH = 0x04
checkword : ORIGIN = 0x9D07FFFC, LENGTH = 0x04
config3 : ORIGIN = 0xBFC02FF0, LENGTH = 0x4
config2 : ORIGIN = 0xBFC02FF4, LENGTH = 0x4
config1 : ORIGIN = 0xBFC02FF8, LENGTH = 0x4
config0 : ORIGIN = 0xBFC02FFC, LENGTH = 0x4
kseg1_data_mem (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x18000
reset_safe_area (w!x) : ORIGIN = 0xA0018000, LENGTH = 0x7FF0
calibration_request (w!x) : ORIGIN = 0xA001FFF0, LENGTH = 0x10
sfrs : ORIGIN = 0xBF800000, LENGTH = 0x100000
configsfrs : ORIGIN = 0xBFC02FF0, LENGTH = 0x10
}
SECTIONS
{
.config_BFC02FF0 : {
KEEP(*(.config_BFC02FF0))
} > config3
.config_BFC02FF4 : {
KEEP(*(.config_BFC02FF4))
} > config2
.config_BFC02FF8 : {
KEEP(*(.config_BFC02FF8))
} > config1
.config_BFC02FFC : {
KEEP(*(.config_BFC02FFC))
} > config0
}
SECTIONS
{
.upgradeword :
{
LONG(0x0091A000);
} >upgradeword
.checkword :
{
LONG(0x02B3C000);
} >checkword
.startup_without_bootloader _ORIGINAL_RESET_ADDR :
{
/* creates a “j _reset” instruction at address _ORIGINAL_RESET_ADDR
_reset must be within the same 256MB boundary as the original reset
vector in order for this to work do to the limitations of the ‘j’ instruction.
*/
LONG( ((_reset >> 2) & 0x03FFFFFF) | 0x08000000);
LONG(0);
} > startup_without_bootloader
/* Boot Sections */
.reset _RESET_ADDR :
{
KEEP(*(.reset))
/*KEEP(*(.reset.startup))*/
} > kseg1_boot_mem
.bev_excpt _BEV_EXCPT_ADDR :
{
KEEP(*(.bev_handler))
} > kseg1_boot_mem
.dbg_excpt _DBG_EXCPT_ADDR (NOLOAD) :
{
. += (DEFINED (_DEBUGGER) ? 0x8 : 0x0);
} > kseg1_boot_mem
.dbg_code _DBG_CODE_ADDR (NOLOAD) :
{
. += (DEFINED (_DEBUGGER) ? 0xFF0 : 0x0);
} > debug_exec_mem
.app_excpt _GEN_EXCPT_ADDR :
{
KEEP(*(.gen_handler))
} > exception_mem
.vector_0 _ebase_address + 0x200 :
{
KEEP(*(.vector_0))
} > exception_mem
ASSERT (_vector_spacing == 0 || SIZEOF(.vector_0) <= (_vector_spacing << 5), "function at exception vector 0 too large")
.vector_1 _ebase_address + 0x200 + (_vector_spacing << 5) * 1 :
{
KEEP(*(.vector_1))
} > exception_mem
ASSERT (_vector_spacing == 0 || SIZEOF(.vector_1) <= (_vector_spacing << 5), "function at exception vector 1 too large")
.vector_2 _ebase_address + 0x200 + (_vector_spacing << 5) * 2 :
{
KEEP(*(.vector_2))
} > exception_mem
cut the rest of the vectors off
.startup ORIGIN(kseg0_boot_mem) :
{
KEEP(*(.startup))
} > kseg0_boot_mem
/* Code Sections */
.text ORIGIN(kseg0_program_mem) :
{
_text_begin = . ;
*(.text .stub .text.* .gnu.linkonce.t.*)
KEEP (*(.text.*personality*))
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.mips16.fn.*)
*(.mips16.call.*)
_text_end = . ;
} >kseg0_program_mem =0
/* Read-only sections */
.rodata :
{
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.rodata1)
. = ALIGN(4) ;
} >kseg0_program_mem
/*
* Small initialized constant global and static data can be placed in the
* .sdata2 section. This is different from .sdata, which contains small
* initialized non-constant global and static data.
*/
.sdata2 ALIGN(4) :
{
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
. = ALIGN(4) ;
} >kseg0_program_mem
/*
* Uninitialized constant global and static data (i.e., variables which will
* always be zero). Again, this is different from .sbss, which contains
* small non-initialized, non-constant global and static data.
*/
.sbss2 ALIGN(4) :
{
*(.sbss2 .sbss2.* .gnu.linkonce.sb2.*)
. = ALIGN(4) ;
} >kseg0_program_mem
.eh_frame_hdr : { *(.eh_frame_hdr) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
.dbg_data (NOLOAD) :
{
. += (DEFINED (_DEBUGGER) ? 0x200 : 0x0);
} >kseg1_data_mem
/* Persistent data */
.persist :
{
_persist_begin = .;
*(.persist .persist.*)
_persist_end = .;
} >kseg1_data_mem
.data :
{
_data_begin = . ;
*(.data .data.* .gnu.linkonce.d.*)
KEEP (*(.gnu.linkonce.d.*personality*))
*(.data1)
} >kseg1_data_mem AT>kseg0_program_mem
_data_image_begin = LOADADDR(.data) ;
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
. = .;
_gp = ALIGN(16) + 0x7ff0;
.got ALIGN(4) :
{
*(.got.plt) *(.got)
} >kseg1_data_mem AT>kseg0_program_mem
/*
* We want the small data sections together, so single-instruction offsets
* can access them all, and initialized data all before uninitialized, so
* we can shorten the on-disk segment size.
*/
.sdata ALIGN(4) :
{
_sdata_begin = . ;
*(.sdata .sdata.* .gnu.linkonce.s.*)
_sdata_end = . ;
} >kseg1_data_mem AT>kseg0_program_mem
.lit8 :
{
*(.lit8)
} >kseg1_data_mem AT>kseg0_program_mem
.lit4 :
{
*(.lit4)
} >kseg1_data_mem AT>kseg0_program_mem
. = ALIGN (4) ;
_data_end = . ;
_bss_begin = . ;
.sbss ALIGN(4) :
{
_sbss_begin = . ;
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
_sbss_end = . ;
} >kseg1_data_mem
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/*
* Align here to ensure that the .bss section occupies space up to
* _end. Align after .bss to ensure correct alignment even if the
* .bss section disappears because there are no input sections.
*/
. = ALIGN(4) ;
} >kseg1_data_mem
. = ALIGN(4) ;
_end = . ;
_bss_end = . ;
/* Heap allocating takes a chunk of memory following BSS */
.heap ALIGN(8) :
{
_heap = . ;
. += _min_heap_size ;
. = ALIGN(8);
} >kseg1_data_mem
/* Stack allocation follows the heap */
.stack ALIGN(8) :
{
_splim = . ;
_SPLIM = . ;
. += _min_stack_size ;
. = ALIGN(8);
} >kseg1_data_mem
/*
* RAM functions go at the end of our stack and heap allocation.
* Alignment of 2K required by the boundary register (BMXDKPBA).
*/
.ramfunc ALIGN(2K) :
{
_ramfunc_begin = . ;
*(.ramfunc .ramfunc.*)
. = ALIGN(4) ;
_ramfunc_end = . ;
} >kseg1_data_mem AT>kseg0_program_mem
_ramfunc_image_begin = LOADADDR(.ramfunc) ;
_ramfunc_length = SIZEOF(.ramfunc) ;
_bmxdkpba_address = _ramfunc_begin - ORIGIN(kseg1_data_mem) ;
_bmxdudba_address = LENGTH(kseg1_data_mem) ;
_bmxdupba_address = LENGTH(kseg1_data_mem) ;
/* RESET SAFE SECTION TO BE LOCATED AT */
.reset_safe():
{
KEEP(*(.reset_safe))
} >reset_safe_area
.calib_request():
{
KEEP(*(.calib_request))
} >calibration_request
/*
* The actual top of stack should include the gap between the stack
* section and the beginning of the .ramfunc section caused by the
* alignment of the .ramfunc section minus 1 word. If RAM functions
* do not exist, then the top of the stack should point to the end of
* the data memory.
*/
_stack = (_ramfunc_length > 0)
? _ramfunc_begin - 4
: ORIGIN(kseg1_data_mem) + LENGTH(kseg1_data_mem) ;
ASSERT((_min_stack_size + _min_heap_size) <= (_stack - _heap),
"Not enough space to allocate both stack and heap. Reduce heap and/or stack size.")
/* The .pdr section belongs in the absolute section */
/DISCARD/ : { *(.pdr) }
/* We don't load .reginfo onto the target, so don't locate it
* in real memory
*/
/DISCARD/ : { *(.reginfo) }
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/DISCARD/ : { *(.rel.dyn) }
/DISCARD/ : { *(.note.GNU-stack) }
}