The Cortex-M3 will reset into Thread mode, executing as privileged. Handler mode (always privileged) is automatically entered when handling any exceptions which occur. Since PIC does not support more multiple operating modes and has no concept of privilege, leaving the Cortex-M3 in this configuration is the simplest option and is often sufficient.
In order to take advantage of the protection offered by the privileged execution Thread mode can be configured to be unprivileged by setting CONTROL. Unprivileged execution is prohibited from carrying out some system operations, e.g. masking interrupts.
On PIC devices, the return stack is automatically initialized and is not accessible to the application software. If an application stack is required (and it almost always will be when programming in C) it is initialized via a STACK directive in the linker control script. Allocating a stack region of up to 256 bytes is simple since it can be located within a single bank of memory. C18 supports stacks larger than this by combining more than one contiguous memory bank into a single region. However, this can mean that space available for data variables is limited.
The Cortex-M3 takes the initial value for the Main Stack Pointer (SP_main) from the first word in the vector table. This must be initialized to an area of RAM. Ideally this should be internal SRAM for best performance. Unless configured otherwise (see below) the Cortex-M3 will use this single stack pointer in both Thread and Handler modes. This is the simplest configuration to use when migrating from the 8051 which only supports a single stack pointer.
For applications which require an OS, the Cortex-M3 can be configured to use the separate Process Stack Pointer (SP_process) when in Thread Mode. This is done by writing to the CONTROL bit. Setting this configuration allows separate stacks to be used for normal execution and exception handling. This would normally be handled by an OS kernel – in most simple applications, there is no need to use the PSP.
Since the Cortex-M3 is programmed entirely in C, stack usage is likely to be much higher than for the same program running on PIC. Sufficient stack space must therefore be provided. When allocating stack space, ensure that you take account of any usage required by exceptions.
4.1.3 Memory map
Unless an MPU is present and enabled, the default memory map described above is used. When migrating an application from PIC it is not usually necessary to implement any memory map configuration. In this case the MPU can be safely left disabled.
Microcontrollers using a Cortex-M3 processor can be built with many different memory devices. Usually, there will be some internal Flash or ROM (mapped to the CODE region) and internal SRAM (in the SRAM region). Any peripherals will normally be mapped to the Peripheral region. There may also be some external RAM.
Consult the manual for your chosen device to determine exactly what memories have been implemented and how they are mapped.
In any event, the system control registers and standard core peripherals (such as the SysTick timer etc) will be located in the standard location.
4.1.4 Code and data placement
When coding for PIC devices, it is common to write non-relocatable code. Indeed, the assembler produces absolute executable files by default (ARM compilers and assemblers do not do this – a link stage is always required). Directives in C and assembly language source files fix the placement in memory at compile-time. This is extremely rare when coding for Cortex-M3 devices. Essentially, all code and object files are relocatable and the placement of code and data is decided at link time.
Both linkers take a list of object files and a script which controls the code and data placement.
Since PIC devices differ considerably in the amount and type of memory which they support and also the location of special registers, the PIC linker (MPLINK) control scripts are different for every PIC device. The generic script then needs to be modified by the developer to add application-specific placement rules.
When writing code containing GOTO or CALL instructions, unless page selection instructions are also included in the source, it will be necessary to split these up so that the maximum range of the instructions is not exceeded. This is not necessary when coding for ARM since the linker will automatically add long-branch support code where necessary.
The ARM linker takes its control input from a “scatter control file” – this can be generated automatically from project setting if using the Keil-MDK development tools. Specifying explicit sections is not usually necessary when linking for Cortex-M3 devices. Providing information about available ROM sections is often sufficient to allow the linker to place all objects. Code is normally placed in the Code region and this is normally populated with non-volatile memory of some kind e.g. flash. It is possible to place code in the SRAM region at run-time but performance will be slightly degraded as the core is optimized to fetch instructions using the ICODE bus from the Code region.
Data memory in PIC devices is divided into banks. It is difficult, therefore, to create data segments which are larger than a single bank.
The PIC linker tries to place all variables in a single 256-byte section. Arrays larger than 256 bytes need special sections creating in the linker script.
There are no such restrictions when coding for Cortex-M3 devices. The only restriction is the absolute size of the RAM devices available.
All PIC peripherals which are included in the device are accessed and controller via SFRs in fixed locations (though the location and layout may vary from device to device). Additional memory-mapped peripherals may only be used with larger devices which support external memory interfaces. are not generally used so do not need locations defining at link time. The locations of these registers are generally supplied via included header files when coding in assembly or C and mirrored in the standard linker configuration script for the target device.