You have to set the configuration bits. Near the end of the device's header file (line 5880 for dsPIC30F4013) is a listing of all the device's configuration bits that need to be set or cleared to ensure proper operation of the device, as well as code comments for how to do it.
For example:
_FOSC( XT & CSW_FSCM_OFF ) // Configure for external XT crystal oscillator, turn off clock switching and monitoring
The oscillator and watchdog timer configurations are very important.
EDIT: In your edited post you tried using the phase-locked loop option for the oscillator. You have to add the following code in your main routine in order to use an external oscillator + PLL:
/*
* Set up the PLL for full 60 MIPS operation (dsPIC33EP512MU810)
*
* Fcy = Fin*K/2 --> 60MHz = 8MHz*K/2 --> K = 15
* K = M/(N2*N1) --> 15 = M/(N2*N1) --> N2 = 2, N1 = 2, M = 60
* Fcy = 8MHz*15/2 = 60MHz
*
* p. 164-171 datasheet
*/
void configPLL()
{
PLLFBDbits.PLLDIV = 58; // M = 60
CLKDIVbits.PLLPOST = 0; // N1 = 2
CLKDIVbits.PLLPRE = 0; // N2 = 2
OSCTUN = 0;
// Writing to the OSCCON register requires a special unlock sequence
// Using a compiler built-in write instruction to handle this
__builtin_write_OSCCONH(0x03); // Select primary oscillator with PLL
__builtin_write_OSCCONL(0x01); // Request oscillator switch
while (OSCCONbits.COSC != 0x3); // Wait for the PLL to lock
}
This can be done using directives in both the assembler source and in the linker script. When you use the udata
primitive, the label becomes the section name.
Consider the following example source files similar to what you have provided:
file1.asm
SomeSection udata
register1 res 1
register2 res 1
SomeOtherSection udata
register5 res 1
end
file2.asm
SomeSection udata
register3 res 1
register4 res 1
end
In file1.asm, there will be two output sections generated by the assembler named SomeSection
and SomeOtherSection
. You can verify this by turning on the output map file and looking at the listed section names.
The next step is to tell the link where those sections should be placed in memory, this requires a change to the default linker script.
Locate and copy the default linker script for your device (16f627a_g.lnk
) to your project directory and add it in the Linker Script
project settings.
At the bottom of the linker script you'll notice a set of SECTION
specifiers like this:
SECTION NAME=PROG ROM=page // ROM code space
SECTION NAME=IDLOCS ROM=.idlocs // ID locations
SECTION NAME=DEVICEID ROM=.device_id // Device ID
SECTION NAME=DEEPROM ROM=eedata // Data EEPROM
Add your own section names here and the destination RAM bank.
SECTION NAME=SomeSection RAM=gpr0
SECTION NAME=SomeOtherSection RAM=gpr2
You can verify in the map output file that your variables have been placed in the correct location. From the example above, registers1-4 go into gpr0, register5 goes into gpr2.
Best Answer
I sortof remember that the ICD2 uses a few bytes of RAM and a few words of code space on that chip. It would be helpful if you look up what resources the ICD2 requires and post it so that we can give explicit examples how to deal with it.
One method is to modify the linker script, as you said. You simply shrink the effected memory regions to not cover the ICD2 areas. As far as the linker is concerned, that memory doesn't exists, so it won't place your code or variables there.
Another way is to deliberately reserve space in those regions at the appropriate fixed addresses in the source code, but then not use that space. By providing a address parameter to the CODE and UDATA directives, it makes the resulting sections fixed so the linker has no choice about where to place it. Since the dummy sections will be forced over the ICD areas, the linker won't place your code there. No linker files need be changed.
Yet another way is to use the new Microchip linker files which contain conditionals that automatically shrink some of the memory regions when a debug switch is set. I don't remember what exactly that switch is, but it shouldn't be hard to figure out by looking at the linker file.