Statistics
| Branch: | Revision:

root / hw / armv7m.c @ b7169916

History | View | Annotate | Download (5.8 kB)

1 9ee6e8bb pbrook
/*
2 9ee6e8bb pbrook
 * ARMV7M System emulation.
3 9ee6e8bb pbrook
 *
4 9ee6e8bb pbrook
 * Copyright (c) 2006-2007 CodeSourcery.
5 9ee6e8bb pbrook
 * Written by Paul Brook
6 9ee6e8bb pbrook
 *
7 9ee6e8bb pbrook
 * This code is licenced under the GPL.
8 9ee6e8bb pbrook
 */
9 9ee6e8bb pbrook
10 87ecb68b pbrook
#include "hw.h"
11 87ecb68b pbrook
#include "arm-misc.h"
12 87ecb68b pbrook
#include "sysemu.h"
13 9ee6e8bb pbrook
14 9ee6e8bb pbrook
/* Bitbanded IO.  Each word corresponds to a single bit.  */
15 9ee6e8bb pbrook
16 9ee6e8bb pbrook
/* Get the byte address of the real memory for a bitband acess.  */
17 8da3ff18 pbrook
static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
18 9ee6e8bb pbrook
{
19 9ee6e8bb pbrook
    uint32_t res;
20 9ee6e8bb pbrook
21 8da3ff18 pbrook
    res = *(uint32_t *)opaque;
22 9ee6e8bb pbrook
    res |= (addr & 0x1ffffff) >> 5;
23 9ee6e8bb pbrook
    return res;
24 9ee6e8bb pbrook
25 9ee6e8bb pbrook
}
26 9ee6e8bb pbrook
27 9ee6e8bb pbrook
static uint32_t bitband_readb(void *opaque, target_phys_addr_t offset)
28 9ee6e8bb pbrook
{
29 9ee6e8bb pbrook
    uint8_t v;
30 8da3ff18 pbrook
    cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
31 9ee6e8bb pbrook
    return (v & (1 << ((offset >> 2) & 7))) != 0;
32 9ee6e8bb pbrook
}
33 9ee6e8bb pbrook
34 9ee6e8bb pbrook
static void bitband_writeb(void *opaque, target_phys_addr_t offset,
35 9ee6e8bb pbrook
                           uint32_t value)
36 9ee6e8bb pbrook
{
37 9ee6e8bb pbrook
    uint32_t addr;
38 9ee6e8bb pbrook
    uint8_t mask;
39 9ee6e8bb pbrook
    uint8_t v;
40 8da3ff18 pbrook
    addr = bitband_addr(opaque, offset);
41 9ee6e8bb pbrook
    mask = (1 << ((offset >> 2) & 7));
42 9ee6e8bb pbrook
    cpu_physical_memory_read(addr, &v, 1);
43 9ee6e8bb pbrook
    if (value & 1)
44 9ee6e8bb pbrook
        v |= mask;
45 9ee6e8bb pbrook
    else
46 9ee6e8bb pbrook
        v &= ~mask;
47 9ee6e8bb pbrook
    cpu_physical_memory_write(addr, &v, 1);
48 9ee6e8bb pbrook
}
49 9ee6e8bb pbrook
50 9ee6e8bb pbrook
static uint32_t bitband_readw(void *opaque, target_phys_addr_t offset)
51 9ee6e8bb pbrook
{
52 9ee6e8bb pbrook
    uint32_t addr;
53 9ee6e8bb pbrook
    uint16_t mask;
54 9ee6e8bb pbrook
    uint16_t v;
55 8da3ff18 pbrook
    addr = bitband_addr(opaque, offset) & ~1;
56 9ee6e8bb pbrook
    mask = (1 << ((offset >> 2) & 15));
57 9ee6e8bb pbrook
    mask = tswap16(mask);
58 9ee6e8bb pbrook
    cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
59 9ee6e8bb pbrook
    return (v & mask) != 0;
60 9ee6e8bb pbrook
}
61 9ee6e8bb pbrook
62 9ee6e8bb pbrook
static void bitband_writew(void *opaque, target_phys_addr_t offset,
63 9ee6e8bb pbrook
                           uint32_t value)
64 9ee6e8bb pbrook
{
65 9ee6e8bb pbrook
    uint32_t addr;
66 9ee6e8bb pbrook
    uint16_t mask;
67 9ee6e8bb pbrook
    uint16_t v;
68 8da3ff18 pbrook
    addr = bitband_addr(opaque, offset) & ~1;
69 9ee6e8bb pbrook
    mask = (1 << ((offset >> 2) & 15));
70 9ee6e8bb pbrook
    mask = tswap16(mask);
71 9ee6e8bb pbrook
    cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
72 9ee6e8bb pbrook
    if (value & 1)
73 9ee6e8bb pbrook
        v |= mask;
74 9ee6e8bb pbrook
    else
75 9ee6e8bb pbrook
        v &= ~mask;
76 9ee6e8bb pbrook
    cpu_physical_memory_write(addr, (uint8_t *)&v, 2);
77 9ee6e8bb pbrook
}
78 9ee6e8bb pbrook
79 9ee6e8bb pbrook
static uint32_t bitband_readl(void *opaque, target_phys_addr_t offset)
80 9ee6e8bb pbrook
{
81 9ee6e8bb pbrook
    uint32_t addr;
82 9ee6e8bb pbrook
    uint32_t mask;
83 9ee6e8bb pbrook
    uint32_t v;
84 8da3ff18 pbrook
    addr = bitband_addr(opaque, offset) & ~3;
85 9ee6e8bb pbrook
    mask = (1 << ((offset >> 2) & 31));
86 9ee6e8bb pbrook
    mask = tswap32(mask);
87 9ee6e8bb pbrook
    cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
88 9ee6e8bb pbrook
    return (v & mask) != 0;
89 9ee6e8bb pbrook
}
90 9ee6e8bb pbrook
91 9ee6e8bb pbrook
static void bitband_writel(void *opaque, target_phys_addr_t offset,
92 9ee6e8bb pbrook
                           uint32_t value)
93 9ee6e8bb pbrook
{
94 9ee6e8bb pbrook
    uint32_t addr;
95 9ee6e8bb pbrook
    uint32_t mask;
96 9ee6e8bb pbrook
    uint32_t v;
97 8da3ff18 pbrook
    addr = bitband_addr(opaque, offset) & ~3;
98 9ee6e8bb pbrook
    mask = (1 << ((offset >> 2) & 31));
99 9ee6e8bb pbrook
    mask = tswap32(mask);
100 9ee6e8bb pbrook
    cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
101 9ee6e8bb pbrook
    if (value & 1)
102 9ee6e8bb pbrook
        v |= mask;
103 9ee6e8bb pbrook
    else
104 9ee6e8bb pbrook
        v &= ~mask;
105 9ee6e8bb pbrook
    cpu_physical_memory_write(addr, (uint8_t *)&v, 4);
106 9ee6e8bb pbrook
}
107 9ee6e8bb pbrook
108 9ee6e8bb pbrook
static CPUReadMemoryFunc *bitband_readfn[] = {
109 9ee6e8bb pbrook
   bitband_readb,
110 9ee6e8bb pbrook
   bitband_readw,
111 9ee6e8bb pbrook
   bitband_readl
112 9ee6e8bb pbrook
};
113 9ee6e8bb pbrook
114 9ee6e8bb pbrook
static CPUWriteMemoryFunc *bitband_writefn[] = {
115 9ee6e8bb pbrook
   bitband_writeb,
116 9ee6e8bb pbrook
   bitband_writew,
117 9ee6e8bb pbrook
   bitband_writel
118 9ee6e8bb pbrook
};
119 9ee6e8bb pbrook
120 9ee6e8bb pbrook
static void armv7m_bitband_init(void)
121 9ee6e8bb pbrook
{
122 9ee6e8bb pbrook
    int iomemtype;
123 8da3ff18 pbrook
    static uint32_t bitband1_offset = 0x20000000;
124 8da3ff18 pbrook
    static uint32_t bitband2_offset = 0x40000000;
125 9ee6e8bb pbrook
126 9ee6e8bb pbrook
    iomemtype = cpu_register_io_memory(0, bitband_readfn, bitband_writefn,
127 8da3ff18 pbrook
                                       &bitband1_offset);
128 9ee6e8bb pbrook
    cpu_register_physical_memory(0x22000000, 0x02000000, iomemtype);
129 8da3ff18 pbrook
    iomemtype = cpu_register_io_memory(0, bitband_readfn, bitband_writefn,
130 8da3ff18 pbrook
                                       &bitband2_offset);
131 9ee6e8bb pbrook
    cpu_register_physical_memory(0x42000000, 0x02000000, iomemtype);
132 9ee6e8bb pbrook
}
133 9ee6e8bb pbrook
134 9ee6e8bb pbrook
/* Board init.  */
135 9ee6e8bb pbrook
/* Init CPU and memory for a v7-M based board.
136 9ee6e8bb pbrook
   flash_size and sram_size are in kb.
137 9ee6e8bb pbrook
   Returns the NVIC array.  */
138 9ee6e8bb pbrook
139 9ee6e8bb pbrook
qemu_irq *armv7m_init(int flash_size, int sram_size,
140 9ee6e8bb pbrook
                      const char *kernel_filename, const char *cpu_model)
141 9ee6e8bb pbrook
{
142 9ee6e8bb pbrook
    CPUState *env;
143 9ee6e8bb pbrook
    qemu_irq *pic;
144 9ee6e8bb pbrook
    uint32_t pc;
145 9ee6e8bb pbrook
    int image_size;
146 9ee6e8bb pbrook
    uint64_t entry;
147 9ee6e8bb pbrook
    uint64_t lowaddr;
148 9ee6e8bb pbrook
149 9ee6e8bb pbrook
    flash_size *= 1024;
150 9ee6e8bb pbrook
    sram_size *= 1024;
151 9ee6e8bb pbrook
152 9ee6e8bb pbrook
    if (!cpu_model)
153 9ee6e8bb pbrook
        cpu_model = "cortex-m3";
154 9ee6e8bb pbrook
    env = cpu_init(cpu_model);
155 9ee6e8bb pbrook
    if (!env) {
156 9ee6e8bb pbrook
        fprintf(stderr, "Unable to find CPU definition\n");
157 9ee6e8bb pbrook
        exit(1);
158 9ee6e8bb pbrook
    }
159 9ee6e8bb pbrook
160 9ee6e8bb pbrook
#if 0
161 9ee6e8bb pbrook
    /* > 32Mb SRAM gets complicated because it overlaps the bitband area.
162 9ee6e8bb pbrook
       We don't have proper commandline options, so allocate half of memory
163 9ee6e8bb pbrook
       as SRAM, up to a maximum of 32Mb, and the rest as code.  */
164 9ee6e8bb pbrook
    if (ram_size > (512 + 32) * 1024 * 1024)
165 9ee6e8bb pbrook
        ram_size = (512 + 32) * 1024 * 1024;
166 9ee6e8bb pbrook
    sram_size = (ram_size / 2) & TARGET_PAGE_MASK;
167 9ee6e8bb pbrook
    if (sram_size > 32 * 1024 * 1024)
168 9ee6e8bb pbrook
        sram_size = 32 * 1024 * 1024;
169 9ee6e8bb pbrook
    code_size = ram_size - sram_size;
170 9ee6e8bb pbrook
#endif
171 9ee6e8bb pbrook
172 9ee6e8bb pbrook
    /* Flash programming is done via the SCU, so pretend it is ROM.  */
173 9ee6e8bb pbrook
    cpu_register_physical_memory(0, flash_size, IO_MEM_ROM);
174 9ee6e8bb pbrook
    cpu_register_physical_memory(0x20000000, sram_size,
175 9ee6e8bb pbrook
                                 flash_size + IO_MEM_RAM);
176 9ee6e8bb pbrook
    armv7m_bitband_init();
177 9ee6e8bb pbrook
178 9ee6e8bb pbrook
    pic = armv7m_nvic_init(env);
179 9ee6e8bb pbrook
180 9ee6e8bb pbrook
    image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL);
181 9ee6e8bb pbrook
    if (image_size < 0) {
182 9ee6e8bb pbrook
        image_size = load_image(kernel_filename, phys_ram_base);
183 9ee6e8bb pbrook
        lowaddr = 0;
184 9ee6e8bb pbrook
    }
185 9ee6e8bb pbrook
    if (image_size < 0) {
186 9ee6e8bb pbrook
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
187 9ee6e8bb pbrook
                kernel_filename);
188 9ee6e8bb pbrook
        exit(1);
189 9ee6e8bb pbrook
    }
190 9ee6e8bb pbrook
191 9ee6e8bb pbrook
    /* If the image was loaded at address zero then assume it is a
192 9ee6e8bb pbrook
       regular ROM image and perform the normal CPU reset sequence.
193 9ee6e8bb pbrook
       Otherwise jump directly to the entry point.  */
194 9ee6e8bb pbrook
    if (lowaddr == 0) {
195 9ee6e8bb pbrook
        env->regs[13] = tswap32(*(uint32_t *)phys_ram_base);
196 9ee6e8bb pbrook
        pc = tswap32(*(uint32_t *)(phys_ram_base + 4));
197 9ee6e8bb pbrook
    } else {
198 9ee6e8bb pbrook
        pc = entry;
199 9ee6e8bb pbrook
    }
200 9ee6e8bb pbrook
    env->thumb = pc & 1;
201 9ee6e8bb pbrook
    env->regs[15] = pc & ~1;
202 9ee6e8bb pbrook
203 9ee6e8bb pbrook
    /* Hack to map an additional page of ram at the top of the address
204 9ee6e8bb pbrook
       space.  This stops qemu complaining about executing code outside RAM
205 9ee6e8bb pbrook
       when returning from an exception.  */
206 9ee6e8bb pbrook
    cpu_register_physical_memory(0xfffff000, 0x1000, IO_MEM_RAM + ram_size);
207 9ee6e8bb pbrook
208 9ee6e8bb pbrook
    return pic;
209 9ee6e8bb pbrook
}