35 #include <avr/pgmspace.h>
36 #include <avr/interrupt.h>
43 #define R_AVR_7_PCREL 2
44 #define R_AVR_13_PCREL 3
47 #define R_AVR_LO8_LDI 6
48 #define R_AVR_HI8_LDI 7
49 #define R_AVR_HH8_LDI 8
50 #define R_AVR_LO8_LDI_NEG 9
51 #define R_AVR_HI8_LDI_NEG 10
52 #define R_AVR_HH8_LDI_NEG 11
53 #define R_AVR_LO8_LDI_PM 12
54 #define R_AVR_HI8_LDI_PM 13
55 #define R_AVR_HH8_LDI_PM 14
56 #define R_AVR_LO8_LDI_PM_NEG 15
57 #define R_AVR_HI8_LDI_PM_NEG 16
58 #define R_AVR_HH8_LDI_PM_NEG 17
61 #define ELF32_R_TYPE(info) ((unsigned char)(info))
65 #include <avr/pgmspace.h>
66 #define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
71 static struct mmem module_heap;
87 return (
char*)
MMEM_PTR(&module_heap);
97 return (
void *)0x8000;
102 #define INCLUDE_APPLICATE_SOURCE 1
104 #if (FLASHEND > USHRT_MAX) && (__SIZEOF_POINTER__ <= 2)
105 #undef INCLUDE_APPLICATE_SOURCE
106 #define INCLUDE_APPLICATE_SOURCE 0
108 #if (__SIZEOF_POINTER__ > 2)
109 #define INCLUDE_32BIT_CODE 1
112 #if INCLUDE_APPLICATE_SOURCE
114 BOOTLOADER_SECTION
void
117 unsigned char buf[SPM_PAGESIZE];
118 unsigned short* flashptr = (
unsigned short *) mem;
129 for (flashptr=(
unsigned short *)mem; flashptr < (
unsigned short *) mem + size; flashptr += SPM_PAGESIZE) {
130 memset (buf, 0, SPM_PAGESIZE);
131 cfs_read(fd, buf, SPM_PAGESIZE);
139 boot_page_erase (flashptr);
140 boot_spm_busy_wait ();
142 unsigned short *origptr = flashptr;
146 for(i = 0; i < SPM_PAGESIZE; i+=2) {
147 boot_page_fill (flashptr, (uint16_t)((buf[i+1] << 8) | buf[i]));
153 boot_page_write (origptr);
154 boot_spm_busy_wait();
158 boot_spm_busy_wait ();
168 write_ldi(
int fd,
unsigned char *instr,
unsigned char byte)
170 instr[0] = (instr[0] & 0xf0) | (byte & 0x0f);
171 instr[1] = (instr[1] & 0xf0) | (byte >> 4);
172 cfs_write (fd, instr, 2);
179 struct elf32_rela *rela,
char *addr)
182 unsigned char instr[4];
185 cfs_read(fd, instr, 4);
188 type = ELF32_R_TYPE(rela->r_info);
190 addr += rela->r_addend;
195 PRINTF(PSTR (
"elfloader-avr.c: unsupported relocation type: "));
196 PRINTF(
"%d\n", type);
199 case R_AVR_7_PCREL: {
205 int16_t a = (((int)addr - rela->r_offset -2) / 2);
206 instr[0] |= (a << 3) & 0xf8;
207 instr[1] |= (a >> 5) & 0x03;
208 cfs_write(fd, instr, 2);
211 case R_AVR_13_PCREL: {
216 int16_t a = (int)addr / 2;
217 a -= rela->r_offset / 2;
219 instr[0] |= a & 0xff;
220 instr[1] |= (a >> 8) & 0x0f;
221 cfs_write(fd, instr, 2);
226 instr[0] = (int)addr & 0xff;
227 instr[1] = ((int)addr >> 8) & 0xff;
229 cfs_write(fd, instr, 2);
233 addr = (
char *)((
int)addr >> 1);
234 instr[0] = (int)addr & 0xff;
235 instr[1] = ((int)addr >> 8) & 0xff;
237 cfs_write(fd, instr, 2);
241 write_ldi(fd, instr, (
int)addr);
244 write_ldi(fd, instr, (
int)addr >> 8);
247 #if INCLUDE_32BIT_CODE
249 write_ldi(fd, instr, (
int)addr >> 16);
253 case R_AVR_LO8_LDI_NEG:
254 addr = (
char *) (0 - (
int)addr);
255 write_ldi(fd, instr, (
int)addr);
257 case R_AVR_HI8_LDI_NEG:
258 addr = (
char *) (0 - (
int)addr);
259 write_ldi(fd, instr, (
int)addr >> 8);
262 #if INCLUDE_32BIT_CODE
263 case R_AVR_HH8_LDI_NEG:
264 addr = (
char *)(0 - (
int)addr);
265 write_ldi(fd, instr, (
int)addr >> 16);
269 case R_AVR_LO8_LDI_PM:
270 write_ldi(fd, instr, (
int)addr >> 1);
272 case R_AVR_HI8_LDI_PM:
273 write_ldi(fd, instr, (
int)addr >> 9);
276 #if INCLUDE_32BIT_CODE
277 case R_AVR_HH8_LDI_PM:
278 write_ldi(fd, instr, (
int)addr >> 17);
282 case R_AVR_LO8_LDI_PM_NEG:
283 addr = (
char *) (0 - (
int)addr);
284 write_ldi(fd, instr, (
int)addr >> 1);
286 case R_AVR_HI8_LDI_PM_NEG:
287 addr = (
char *) (0 - (
int)addr);
288 write_ldi(fd, instr, (
int)addr >> 9);
291 #if INCLUDE_32BIT_CODE
292 case R_AVR_HH8_LDI_PM_NEG:
293 addr = (
char *) (0 - (
int)addr);
294 write_ldi(fd, instr, (
int)addr >> 17);
306 instr[2] = (uint8_t) ((
int)addr) & 0xff;
307 instr[3] = ((int)addr) >> 8;
308 cfs_write(fd, instr, 4);
312 PRINTF(PSTR (
"Unknown relocation type!\n"));
318 elfloader_unload(
void) {
void elfloader_arch_relocate(int fd, unsigned int sectionoffset, char *sectionaddr, struct elf32_rela *rela, char *addr)
Perform a relocation.
cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence)
Seek to a specified position in an open file.
Header file for the managed memory allocator
Header file for the architecture specific parts of the Contiki ELF loader.
#define PORTB
Peripheral PORTB base pointer.
#define NULL
The null pointer.
void * elfloader_arch_allocate_ram(int size)
Allocate RAM for a new module.
#define MMEM_PTR(m)
Get a pointer to the managed memory.
int mmem_alloc(struct mmem *m, unsigned int size)
Allocate a managed memory block.
void mmem_free(struct mmem *m)
Deallocate a managed memory block.
void * elfloader_arch_allocate_rom(int size)
Allocate program memory for a new module.
#define CFS_SEEK_SET
Specify that cfs_seek() should compute the offset from the beginning of the file. ...
void elfloader_arch_write_rom(int fd, unsigned short textoff, unsigned int size, char *mem)
Write to read-only memory (for example the text segment).