How to over come M4 64k image limit when dual core is using in LPC4350

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

How to over come M4 64k image limit when dual core is using in LPC4350

1,888 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by srinu282 on Mon Sep 10 07:31:28 MST 2012

Hi All,

      Am having Hitex4350 development board.using dual core (M4 and M0).Memory map for M4 and M0 as follows.

Region         Core     Address range                   Notes
M4 code region M4 0x1C000000 - 0x1C00FFFF  Includes code and data up to 64K
M0 code region M0 0x1C010000 - 0x10007FFF  Includes code and data up to 32K.
M4 data region M4 0x10000000 - 0x1000FFFF  pre-initialized RW data, ZI data, heap, stack, 64K max
M0 data region M0 0x10001000 - 0x10017FFF  pre-initialized RW data, ZI data, heap, stack, 32K max
Extra IRAM/free   0x10018000 - 0x1001FFFF 
Shared memory region M0/M4 0x10080000 - 0x10083FFF Shared memory region between M0 and M4 core, used for queue.


1.Configured A14 to A22 address lines to access 64k as boot loader will only configure A0 to A13 address lines in start-up file.
2.M4 and M0 images are 64K offset so initially both  core are working fine because M4 code size is less than 64K.                      3.Now my M4 project code size is more than 64K(76262=74-47k). in this case M0 core is not working. i tried to change the 64k offset address in M4 and M0 linker script file. but also M0 core is not working only M4 is running.
linker scripts are attached. how can i over come this limit?
please help me to get out of this problem. Thanks in advance.

by
sreenivas ida
标签 (1)
0 项奖励
回复
7 回复数

1,752 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by srinu282 on Mon Nov 26 07:27:48 MST 2012
Hi gregd,
  
   Thanks for u r reply.Using IPC am downloading M0 image in to 0x10080000.Code as follows
/* specify the filename used for the slave image */
#define SLAVE_IMAGE_FILE "CM0_image.c"
/* used to place the CM0_IMAGE array within the "SLAVE IMAGE" section */
#pragma arm section rodata = "M0_SLAVE_IMAGE"
/* fromelf.exe always generates an unsigned char LR0[] type of array */
const/* DO NOT REMOVE THIS CONST QUALIFIER, IS USED TO PLACE THE IMAGE IN M4 ROM */
#include SLAVE_IMAGE_FILE
#pragma arm section rodata
/* return to default scheme */

M0 core is build for  RAM not for Flash target.

In Main()
{
IPC_haltSlave();
/* setup the queue system */
IPC_masterInitQueue(&_hostCmdBufferData[0], MASTER_CMDBUF_SIZE, &_hostMsgBufferData[0], SLAVE_MSGBUF_SIZE);
/* download the cpu image */
IPC_downloadSlaveImage(SLAVE_ROM_START, &LR0[0], sizeof(LR0));
/* start the remote processor */
IPC_startSlave();
}.

1.Image downloaded in to flash.
2.Started debugging using ULINK2 on HITEX – A4 board.
3.M4 is working fine with FreeRTOS functionality.
4.M0 core is booting but TaskCreation is failing. Task creation function as follows


#define configMINIMAL_STACK_SIZE( ( unsigned short ) 256 )

xTaskCreate( vM0_Task, ( signed char * ) "M0_Task",
(configMINIMAL_STACK_SIZE*5), NULL, (tskIDLE_PRIORITY + 1UL),
( xTaskHandle * ) NULL );
      
5.Linkerscript  and startup file as follows


M0 Linker script

; M0 image uses local addresses
; absolute addresses are used only for shared buffers
LR_IROM1 0x0  0x8000  {    ; load region size_region

  ; physical address 0x10080000 - 0x10088000
; 32K code space
ER_IROM1 0x0 0x8000  { 
  
   *.o (RESET, +First)
   *(InRoot$$Sections)  
   .ANY (+RO)
}

  ; physical address 0x10088000 - 0x1008A000
; 8 K data space
ER_IRAM1 0x8000 0x2000 {
   .ANY (+RW +ZI)
}


; setup a heap using default region name for arm lib "ARM_LIB_HEAP"
    ARM_LIB_HEAP +0 EMPTY 0x400 { 

}

; setup the stack using default region name for arm lib "ARM_LIB_STACK"
; is growing backwards so will overlap is no space is available
ARM_LIB_STACK 0xA000 EMPTY -0x800 {

}

   ; these are specified with the physical address since are system level shared memory
ER_IRAM_BUFFERS 0x20004000 0x4000 {
*.o(lowerCaseString_sec)
*.o(directString_sec)
}

ER_IRAM_MBX 0x2000A000 0x2000 {
   *.o(Slave_mbxTable) ; hold the mailbox system
}
}

Startup file
/*****************************************************************************/
/* M0 Core */
/*****************************************************************************/
#if defined(CORE_M0)

/* External functions */
extern int __main (void);

/* Default interrupt service routines.
* Defined as weak symbols. Can be redefined in the application.
*/
#define ALIAS(def) __attribute__((weak,alias(#def)))

void Default_IRQHandler (void);

void Reset_Handler (void);
void NMI_Handler (void);
void HardFault_Handler (void);
void BusFault_Handler (void);
void UsageFault_Handler (void);
void Sign_Value (void);
void DebugMon_Handler (void);

void SVC_Handler (void) ALIAS(Default_IRQHandler);
void PendSV_Handler (void) ALIAS(Default_IRQHandler);
void SysTick_Handler (void) ALIAS(Default_IRQHandler);

/* freeRTOS versions of the OS calls */
void vPortSVCHandler (void) ALIAS(Default_IRQHandler);
void xPortPendSVHandler (void) ALIAS(Default_IRQHandler);
void xPortSysTickHandler (void) ALIAS(Default_IRQHandler);

/* hook for the IPC interrupt routine */
void IPC_Master2Slave_IRQHandler(void) ALIAS(Default_IRQHandler);

extern void Image$$ARM_LIB_STACK$$ZI$$Limit;

void DAC_IRQHandler (void) ALIAS(Default_IRQHandler);
void M4_IRQHandler (void) ALIAS(Default_IRQHandler);
void DMA_IRQHandler (void) ALIAS(Default_IRQHandler);
void FLASH_EEPROM_IRQHandler (void) ALIAS(Default_IRQHandler);
void ETH_IRQHandler (void) ALIAS(Default_IRQHandler);
void SDIO_IRQHandler (void) ALIAS(Default_IRQHandler);
void LCD_IRQHandler (void) ALIAS(Default_IRQHandler);
void USB0_IRQHandler (void) ALIAS(Default_IRQHandler);
void USB1_IRQHandler (void) ALIAS(Default_IRQHandler);
void SCT_IRQHandler (void) ALIAS(Default_IRQHandler);
void M0_RIT_OR_WWDT_IRQHandler (void) ALIAS(Default_IRQHandler);
void TIMER0_IRQHandler (void) ALIAS(Default_IRQHandler);
void TIMER1_IRQHandler (void) ALIAS(Default_IRQHandler);
void TIMER2_IRQHandler (void) ALIAS(Default_IRQHandler);
void TIMER3_IRQHandler (void) ALIAS(Default_IRQHandler);
void MCPWM_IRQHandler (void) ALIAS(Default_IRQHandler);
void ADC0_IRQHandler (void) ALIAS(Default_IRQHandler);
void I2C0_IRQHandler (void) ALIAS(Default_IRQHandler);
void I2C1_IRQHandler (void) ALIAS(Default_IRQHandler);
void SPI_IRQHandler (void) ALIAS(Default_IRQHandler);
void ADC1_IRQHandler (void) ALIAS(Default_IRQHandler);
void SSP0_IRQHandler (void) ALIAS(Default_IRQHandler);
void SSP1_IRQHandler (void) ALIAS(Default_IRQHandler);
void UART0_IRQHandler (void) ALIAS(Default_IRQHandler);
void UART1_IRQHandler (void) ALIAS(Default_IRQHandler);
void UART2_IRQHandler (void) ALIAS(Default_IRQHandler);
void UART3_IRQHandler (void) ALIAS(Default_IRQHandler);
void I2S0_IRQHandler (void) ALIAS(Default_IRQHandler);
void I2S1_IRQHandler (void) ALIAS(Default_IRQHandler);
void SPIFI_IRQHandler (void) ALIAS(Default_IRQHandler);
void SGPIO_IRQHandler (void) ALIAS(Default_IRQHandler);
void GPIO0_IRQHandler (void) ALIAS(Default_IRQHandler);
void GPIO1_IRQHandler (void) ALIAS(Default_IRQHandler);
void GPIO2_IRQHandler (void) ALIAS(Default_IRQHandler);
void GPIO3_IRQHandler (void) ALIAS(Default_IRQHandler);
void GPIO4_IRQHandler (void) ALIAS(Default_IRQHandler);
void GPIO5_IRQHandler (void) ALIAS(Default_IRQHandler);
void GPIO6_IRQHandler (void) ALIAS(Default_IRQHandler);
void GPIO7_IRQHandler (void) ALIAS(Default_IRQHandler);
void GINT0_IRQHandler (void) ALIAS(Default_IRQHandler);
void GINT1_IRQHandler (void) ALIAS(Default_IRQHandler);
void EVRT_IRQHandler (void) ALIAS(Default_IRQHandler);
void CAN1_IRQHandler (void) ALIAS(Default_IRQHandler);
void VADC_IRQHandler (void) ALIAS(Default_IRQHandler);
void ATIMER_IRQHandler (void) ALIAS(Default_IRQHandler);
void RTC_IRQHandler (void) ALIAS(Default_IRQHandler);
void WDT_IRQHandler (void) ALIAS(Default_IRQHandler);
void CAN0_IRQHandler (void) ALIAS(Default_IRQHandler);
void QEI_IRQHandler (void) ALIAS(Default_IRQHandler);



#define SIGN_VALUE      0x5A5A5A5A

/** Vector table. Placed in section called RESET
*/
void (* const vector_table[])(void) __attribute__ ((section("RESET"), used)) =
{
    (void(*)(void)) &Image$$ARM_LIB_STACK$$ZI$$Limit,
    Reset_Handler,
    NMI_Handler,
    HardFault_Handler,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    SVC_Handler,
    DebugMon_Handler,
    0,
    PendSV_Handler,
    SysTick_Handler,

    RTC_IRQHandler,
    IPC_Master2Slave_IRQHandler,
    DMA_IRQHandler,
    0,
    0,
    ETH_IRQHandler,                         /* 21 Ethernet */
    SDIO_IRQHandler,                        /* 22 SD/MMC */
    LCD_IRQHandler,                         /* 23 LCD */
    USB0_IRQHandler,                        /* 24 USB0 */
    USB1_IRQHandler,                        /* 25 USB1 */
    SCT_IRQHandler,                         /* 26 State Configurable Timer */
    M0_RIT_OR_WWDT_IRQHandler,              /* 27 Repetitive Interrupt Timer - WWDT timer */
    TIMER0_IRQHandler,                      /* 28 Timer0 */
    GINT1_IRQHandler,
    TIMER3_IRQHandler,
    0,
    0,
    MCPWM_IRQHandler,                       /* 32 Motor Control PWM */
    ADC0_IRQHandler,                        /* 33 A/D Converter 0 */
    I2C0_IRQHandler,                        /* 34 I2C0 */ //TODO Optional I2C1
    SGPIO_IRQHandler,                       /* 47 SGPIO */
    SPI_IRQHandler,                         /* 36 SPI */ //optional DAC
    ADC1_IRQHandler,                        /* 37 A/D Converter 1 */
    SSP0_IRQHandler,                        /* 38 SSP0 */ //TODO optional SSP1
    EVRT_IRQHandler,                        /* 58 Event Router */
    UART0_IRQHandler,                       /* 40 UART0 */
    UART2_IRQHandler,                       /* 42 UART2 */ //TODO optinbal CAN1
    UART3_IRQHandler,
    I2S0_IRQHandler,                        /* 44 I2S0 */ //TODO optional I2S1 or QEI
    CAN0_IRQHandler,
};


void Reset_Handler (void) {

    /* Jump to the library entry point __main() */
    __main();

    /* Loop here forever, in case main() ever returns. */
    while (1) {
    }
}
Please help me to get out of TaskCreation problem








   

0 项奖励
回复

1,752 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by khfreiberg on Fri Oct 26 12:43:54 MST 2012
Hi,
I do not care about performance at this point (16bit, 10wait, must be poor). I am targeting the 4337 and want to stay close to my final design during I'm waiting for my hardware. Debugging is a little easier.
0 项奖励
回复

1,752 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by PhilYoung on Sat Oct 20 15:54:08 MST 2012
it's difficult to picture the layout, a map file would be more useful, but I noticed a comment that you align the m0 image on a 4K boundary, this requires the M0 image to be less than 4K otherwise it will fail.
the image remap is an exor function so the alignment determines the maximum size of image that can be addressed without the address becoming scrambled.
This is an undocumented feature!!.
0 项奖励
回复

1,752 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gregd on Thu Oct 18 07:07:57 MST 2012
Are you are running code directly from the external EMC CS0 (0x1C...) memory bank from both the M4 and M0?  Are you not copying the M0 code to internal ram before running?  How bad is the performance hit doing this? 
0 项奖励
回复

1,752 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by srinu282 on Thu Oct 18 06:32:21 MST 2012
Hi PhilYoung,
      Thanks for u r POST. i did the following steps
H/W Borad :Hitex4350-A4.
/**********************/
M0: Code compiled for RAM variant.
/******************Script file************************/
; M0 image uses local addresses
; absolute addresses are used only for shared buffers
LR_IROM1 0x0  0x8000  {    ; load region size_region

  ; physical address 0x10080000 - 0x10088000
; 32K code space
ER_IROM1 0x0 0x8000  { 
  
   *.o (RESET, +First)
   *(InRoot$$Sections)  
   .ANY (+RO)
}

  ; physical address 0x10088000 - 0x1008A000
; 8 K data space
ER_IRAM1 0x8000 0x2000 {
   .ANY (+RW +ZI)
}


; setup a heap using default region name for arm lib "ARM_LIB_HEAP"
ARM_LIB_HEAP +0 EMPTY 0x400 { 

}

; setup the stack using default region name for arm lib "ARM_LIB_STACK"
; is growing backwards so will overlap is no space is available
ARM_LIB_STACK 0xA000 EMPTY -0x800 {

}

   ; these are specified with the physical address since are system level shared memory
ER_IRAM_BUFFERS 0x20004000 0x4000 {
*.o(lowerCaseString_sec)
*.o(directString_sec)
}

ER_IRAM_MBX 0x2000A000 0x2000 {
   *.o(Slave_mbxTable) ; hold the mailbox system
}
}
M0 build output create an CM0_image.c file in M0_image folder which contains hex values.
CM0_image.c file size is 22KB

M4: Code compiled for FLASH variant.
/*****************Script file for M4*****************************/
; this is the 16 Kbyte sector initialized by the boot loader when booting from EMC
; it has just A0-A13 address lines configured after reset
LR_NORFLASH_16K 0x1C000000 0x4000  {   
  ; the table of reset vectors goes here
ER_FLASH_ROM_RESET_VECTOR_TABLE 0x1C000000 { 
   *.o (RESET, +FIRST)
}

; this holds all code which needs to be available at boot
ER_FLASH_ROM_RESET_VECTOR +0 {
 
; used as an alias for the ARM library functions
; (__main, __scatter, __dc, __*region$$Table etc)
*(InRoot$$Sections)

; system reset vectors
*.o(SYSTEM_RESET_VECTORS)

; the cmsis system init function
*.o(CMSIS_SYSTEM_INIT)

; scu is used for pinmux
lpc43xx_scu.o (+RO)

; enable the fpu as soon as possible if present
fpu_enable.o(+RO)

; platform initialization function
platform_init.o(+RO)

; this code copies the initialization routines in ram
; these are needed to change the PLL settings, the EMC settings
; are executed from ER_IRAM_SYSTEM_CODE, ER_IRAM_BOOT_CODE
*.o(INIT_CODE_COPY)

; routine for reallocating vector table (not used for ram project)
   *.o(VECTOR_TABLE_COPY)


  }

  ; this region includes just the relocated vector table, if used
  ; 68 interrupt vectors @ 4 bytes each
; note: the vector table always needs to be aligned-up to a power of two
; for LPC4350 is 512 bytes
; 53 user + 16 system = 69 int vectors, 69 * 4 = 276 bytes > round up to 512
  ER_IRAM_VECTOR_TABLE 0x10000000 UNINIT  {
    ; reserved for the relocated irq vector table
    *.o(IRAM_ISR_TABLE)
  }

; these are the runtime locations for the initialization routines
; which need to be executed from ram
IRAM_SYSTEM_CODE +0 {

   ; platform initialization routines which need to run from ram
*.o(IRAM_INIT_CODE)

; cgu related functions
lpc43xx_cgu.o (+RO)

}

ER_IRAM_DATA_REST +0 {

   ; any other data
   .ANY(+RW)
   .ANY(+ZI)
}

; "SystemData_noInit" section 
; this section is marked as UNINIT to avoid uLib re-initializing it
; during the __main() library call
; the global initialized and zero-initialized variables are configured by
; the application code
IRAM_SYSTEM_DATA +0 UNINIT {
 
*.o(IRAM_SYSTEM_DATA)
}

}

; rest of the parallel flash above 16 K up to 4 Mbytes
LR_NORFLASH_REST 0x1C004000 0x3FC000 {

ER_M0_SLAVE_IMAGE 0x1C004000 {

*(M0_SLAVE_IMAGE) ; place M0 image here
;CM0_image.o(+RO, OVERALIGN 0x10000)
}

; anything else read only
ER_FLASH_REST +0 {

.ANY (+RO)
}

; any RW data after first 16K
;RW_IRAM_REST 0x10004000 { 
RW_IRAM_REST 0x10009f44 { 

.ANY (+RW +ZI)

  }

; setup a heap using default region name for arm lib "ARM_LIB_HEAP"
;ARM_LIB_HEAP +0 EMPTY 0x200 { 
ARM_LIB_HEAP +0 EMPTY 0x9800 {

}

; setup the stack using default region name for arm lib "ARM_LIB_STACK"
; is growing backwards so will overlap if no space is available
ARM_LIB_STACK 0x10019000 EMPTY -0x800 {

}

; #define M4_BUF_START0x20000000
; #define M4_BUF_LEN0x4000
  RW_IRAM_BUFFERS 0x20000000 0x4000 { ; rw buffers
*.o(lowerToUpper_sec)
*.o(reversed_sec)
*.o(power3_sec)
  }

  ; #define HOST_CMD_BLOCK_START0x20008000
  RW_IRAM_HOST_CMD 0x20008000 0x2000  {
   ;ipc_cmd_buffer.o (cmdBuffer_section, +First)
  }

  ;#define HOST_MSG_BLOCK_START0x2000A000
  RW_IRAM_HOST_MSG 0x2000A000 0x2000  {
   ;ipc_msg_buffer.o (msgBuffer_section, +First)  
  }

}
M4 : main.c added following lines
/* used to place the CM0_IMAGE array within the "SLAVE IMAGE" section */
#pragma arm section rodata = "M0_SLAVE_IMAGE"
/* fromelf.exe always generates an unsigned char LR0[] type of array */
const/* DO NOT REMOVE THIS CONST QUALIFIER, IS USED TO PLACE THE IMAGE IN M4 ROM */

/* specify the filename used for the slave image */
#define SLAVE_IMAGE_FILE "CM0_image.c"

#include SLAVE_IMAGE_FILE

#pragma arm section rodata
/* return to default scheme */

And  calling lpc43xx_m0_boot function from main.
lpc43xx_m0_boot function as follows
void lpc43xx_m0_boot(void)
{
/* Make sure the M0 core is being held in reset via the RGU */
LPC_RGU->RESET_CTRL1 = (1 << 24);

/* Enable system clocking for the M0 core via the CGU. The CPU is
   clocked at the M4 clock rate. (Wow!) */
* (uint32_t *) 0x40051490 = 0x1;

/* Keep in mind the M0 image must be aligned on a 4K boundary */
LPC_CREG->M0APPMEMMAP = (uint32_t)&LR0 + LPC_CREG->M4MEMMAP;
//LPC_CREG->M0APPMEMMAP = (uint32_t)&LR0; // Tried this stmt also

/* Boot the M0 core by clearing the reset status */
LPC_RGU->RESET_CTRL1 = 0;

   /* Enable M0->M4 interrupt and set priority/preemption */
NVIC_SetPriority(M0CORE_IRQn, ((0x01 << 3) | 0x01));
    NVIC_EnableIRQ(M0CORE_IRQn);
}

After doing all these changes also M0 core is not booting. only M4 core is booting. can u guide me how to get out of this problem. Thanks in advance ….



















0 项奖励
回复

1,752 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by khfreiberg on Mon Sep 24 19:29:54 MST 2012
Hi,
I do not see a 64k limit (Hitex4350-A4). I have the M0 code at 0x1C3... and it works fine.
But I have two scatter files for M0 and M4 and I do two separate downloads instead of creating an M0 image that is downloaded with the M4. I hope for my system that the M0 code once ready will stay as is and I only need to maintain the M4 code.

Greetings
0 项奖励
回复

1,752 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by PhilYoung on Tue Sep 11 03:10:48 MST 2012
see my post shadow memory area bug?

There is a bug in the LPC43xx shadow area mapping which may cause problems.
The LSB of the shadow address register effectively determines the maximum usable memory area as they seem to have implemented shadow offsets as an XOR function.

here is what I do


build M0 image as a bootable image, at 0x0
generate hex file from M0 image

compile M0 into M4 image in a special section

I use a CM0Image.cpp file to cast it to const so I don't have to keep editing the hex file

extern const
#include "REV3LR0.h" // fil generated by M0 build process


in the linker script I use

CM0_image.o(+RO, OVERALIGN 0x10000)

this aligns the image to 64K, place the image in a root section as you don't want it copying to RAM

in the main code I use

LPC_CREG->M0APPMEMMAP = (uint32_t)&LR0 + LPC_CREG->M4MEMMAP;
where LR0 is the hex table in the hex file.
This ensures that wherever I place the M4 image the M0 image shadow register is set correctly

Note that I use an image manager so there may be multiple M4 images in the flash, hence reading M4MEMMAP which is the
region the current M4 image is based at, this ensures that the correct M0 image is loaded.
If you have just 1 image it will still work.

0 项奖励
回复