cpu: Add initial Cortex-M3 support.
can be test with targets from LiteX-Boards and Cortex-M3 sources in execution path:
python3 -m litex_boards.targets.digilent_arty --cpu-type=cortex_m3 --sy-clk-freq=50e6 --build --load
__ _ __ _ __
/ / (_) /____ | |/_/
/ /__/ / __/ -_)> <
/____/_/\__/\__/_/|_|
Build your hardware, easily!
(c) Copyright 2012-2022 Enjoy-Digital
(c) Copyright 2007-2015 M-Labs
BIOS built on Apr 22 2022 16:23:30
BIOS CRC passed (b390faf0)
LiteX git sha1: 99a03426
--=============== SoC ==================--
CPU: ARM Cortex-M3 @ 50MHz
BUS: WISHBONE 32-bit @ 4GiB
CSR: 32-bit data
ROM: 128KiB
SRAM: 8KiB
L2: 8KiB
SDRAM: 262144KiB 16-bit @ 400MT/s (CL-7 CWL-5)
--========== Initialization ============--
Initializing SDRAM @0x10000000...
Switching SDRAM to software control.
Read leveling:
m0, b00: |00000000000000000000000000000000| delays: -
m0, b01: |11111111111111111111111111100000| delays: 13+-13
m0, b02: |00000000000000000000000000001111| delays: 30+-02
m0, b03: |00000000000000000000000000000000| delays: -
m0, b04: |00000000000000000000000000000000| delays: -
m0, b05: |00000000000000000000000000000000| delays: -
m0, b06: |00000000000000000000000000000000| delays: -
m0, b07: |00000000000000000000000000000000| delays: -
best: m0, b01 delays: 13+-13
m1, b00: |00000000000000000000000000000000| delays: -
m1, b01: |11111111111111111111111111000000| delays: 13+-13
m1, b02: |00000000000000000000000000000111| delays: 31+-02
m1, b03: |00000000000000000000000000000000| delays: -
m1, b04: |00000000000000000000000000000000| delays: -
m1, b05: |00000000000000000000000000000000| delays: -
m1, b06: |00000000000000000000000000000000| delays: -
m1, b07: |00000000000000000000000000000000| delays: -
best: m1, b01 delays: 13+-13
Switching SDRAM to hardware control.
Memtest at 0x10000000 (2.0MiB)...
Write: 0x10000000-0x10200000 2.0MiB
Read: 0x10000000-0x10200000 2.0MiB
Memtest OK
Memspeed at 0x10000000 (Sequential, 2.0MiB)...
Write speed: 9.7MiB/s
Read speed: 12.6MiB/s
--============== Boot ==================--
Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
Timeout
No boot medium found
--============= Console ================--
litex>
This commit is contained in:
parent
99a034268d
commit
1211cb6ab5
|
@ -0,0 +1 @@
|
||||||
|
from litex.soc.cores.cpu.cortex_m3.core import CortexM3
|
|
@ -0,0 +1,5 @@
|
||||||
|
void boot_helper(unsigned long r1, unsigned long r2, unsigned long r3, unsigned long addr);
|
||||||
|
|
||||||
|
void boot_helper(unsigned long r1, unsigned long r2, unsigned long r3, unsigned long addr) {
|
||||||
|
goto *addr;
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
#
|
||||||
|
# This file is part of LiteX.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2022 Ilia Sergachev <ilia@sergachev.ch>
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
import os
|
||||||
|
from migen import *
|
||||||
|
from litex.soc.interconnect import wishbone
|
||||||
|
from litex.soc.cores.cpu import CPU
|
||||||
|
from litex.soc.interconnect import axi
|
||||||
|
|
||||||
|
|
||||||
|
class CortexM3(CPU):
|
||||||
|
variants = ["standard"]
|
||||||
|
family = "arm"
|
||||||
|
name = "cortex_m3"
|
||||||
|
human_name = "ARM Cortex-M3"
|
||||||
|
data_width = 32
|
||||||
|
endianness = "little"
|
||||||
|
reset_address = 0x0000_0000
|
||||||
|
gcc_triple = "arm-none-eabi"
|
||||||
|
gcc_flags = "-march=armv7-m -mthumb"
|
||||||
|
linker_output_format = "elf32-littlearm"
|
||||||
|
nop = "nop"
|
||||||
|
io_regions = {0x4000_0000: 0x2000_0000,
|
||||||
|
0xA000_0000: 0x6000_0000
|
||||||
|
} # Origin, Length.
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mem_map(self):
|
||||||
|
return {
|
||||||
|
"rom": 0x0000_0000,
|
||||||
|
"main_ram": 0x1000_0000,
|
||||||
|
"sram": 0x2000_0000,
|
||||||
|
"csr": 0xA000_0000
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, platform, variant, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.platform = platform
|
||||||
|
self.reset = Signal()
|
||||||
|
self.interrupt = Signal(2)
|
||||||
|
pbus = wishbone.Interface(data_width=32, adr_width=30)
|
||||||
|
ibus = wishbone.Interface(data_width=32, adr_width=30)
|
||||||
|
self.periph_buses = [pbus, ibus]
|
||||||
|
self.memory_buses = []
|
||||||
|
|
||||||
|
def _mem_size(x):
|
||||||
|
return log2_int(x // 512)
|
||||||
|
|
||||||
|
self.cpu_params = dict(
|
||||||
|
i_HCLK = ClockSignal("sys"),
|
||||||
|
i_SYSRESETn = ~(ResetSignal() | self.reset),
|
||||||
|
p_NUM_IRQ = len(self.interrupt),
|
||||||
|
i_IRQ = self.interrupt,
|
||||||
|
i_DBGRESETn = ~(ResetSignal() | self.reset),
|
||||||
|
p_MPU_PRESENT = 0,
|
||||||
|
p_ITCM_SIZE = _mem_size(0 * 1024), # embedded ROM
|
||||||
|
p_DTCM_SIZE = _mem_size(0 * 1024), # embedded RAM
|
||||||
|
p_TRACE_LVL = 0,
|
||||||
|
p_DEBUG_LVL = 2,
|
||||||
|
i_CFGITCMEN = 0, # 1 = alias ITCM at 0x0
|
||||||
|
)
|
||||||
|
|
||||||
|
def connect_axi(axi_bus, suffix):
|
||||||
|
layout = axi_bus.layout_flat()
|
||||||
|
dir_map = {DIR_M_TO_S: 'o', DIR_S_TO_M: 'i'}
|
||||||
|
for group, signal, direction in layout:
|
||||||
|
if signal in ['id', 'qos', 'first']:
|
||||||
|
continue
|
||||||
|
if signal == 'last':
|
||||||
|
if group in ['b', 'a', 'ar', 'aw']:
|
||||||
|
continue
|
||||||
|
prefix = 'H' if signal == 'data' else ''
|
||||||
|
direction = dir_map[direction]
|
||||||
|
self.cpu_params[f'{direction}_{prefix}{group.upper()}{signal.upper()}{suffix}'] = \
|
||||||
|
getattr(getattr(axi_bus, group), signal)
|
||||||
|
|
||||||
|
ibus_axi = axi.AXIInterface(data_width=self.data_width, address_width=32)
|
||||||
|
ibus_a2w = axi.AXI2Wishbone(ibus_axi, ibus, base_address=0)
|
||||||
|
self.submodules += ibus_a2w
|
||||||
|
connect_axi(ibus_axi, 'C')
|
||||||
|
|
||||||
|
pbus_axi = axi.AXIInterface(data_width=self.data_width, address_width=32)
|
||||||
|
pbus_a2w = axi.AXI2Wishbone(pbus_axi, pbus, base_address=0)
|
||||||
|
self.submodules += pbus_a2w
|
||||||
|
connect_axi(pbus_axi, 'S')
|
||||||
|
|
||||||
|
platform.add_source_dir("AT426-BU-98000-r0p1-00rel0/vivado/Arm_ipi_repository/CM3DbgAXI/rtl")
|
||||||
|
|
||||||
|
def connect_jtag(self, pads):
|
||||||
|
self.cpu_params.update(
|
||||||
|
p_JTAG_PRESENT = 1,
|
||||||
|
i_SWDITMS = pads.tms,
|
||||||
|
i_TDI = pads.tdi,
|
||||||
|
o_TDO = pads.tdo,
|
||||||
|
o_nTDOEN = Signal(),
|
||||||
|
i_nTRST = pads.ntrst,
|
||||||
|
i_SWCLKTCK = pads.tck,
|
||||||
|
o_JTAGNSW = Signal(), # Indicates debug mode, JTAG or SWD
|
||||||
|
o_JTAGTOP = Signal(), # ?
|
||||||
|
o_SWDO = Signal(), # TODO
|
||||||
|
o_SWDOEN = Signal(), # TODO
|
||||||
|
)
|
||||||
|
|
||||||
|
def do_finalize(self):
|
||||||
|
self.specials += Instance("CortexM3DbgAXI", **self.cpu_params)
|
|
@ -0,0 +1,107 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "system.h"
|
||||||
|
#include "generated/soc.h"
|
||||||
|
|
||||||
|
extern uint32_t _fdata_rom, _fdata, _edata, _fbss, _ebss, _fstack;
|
||||||
|
extern void isr(void);
|
||||||
|
|
||||||
|
void _start(void);
|
||||||
|
void default_handler(void);
|
||||||
|
void uart_handler_proxy(void);
|
||||||
|
|
||||||
|
volatile unsigned int irqs_enabled;
|
||||||
|
|
||||||
|
void _start(void) {
|
||||||
|
__asm__(
|
||||||
|
"mov r0, %0\n"
|
||||||
|
"mov sp, r0\n" : : "r" (&_fstack)
|
||||||
|
);
|
||||||
|
uint32_t *y = &_fdata_rom;
|
||||||
|
for (uint32_t *x = &_fdata; x < &_edata; x ++)
|
||||||
|
*x = *y ++;
|
||||||
|
|
||||||
|
for (uint32_t *x = &_fbss; x < &_ebss; x ++)
|
||||||
|
*x = 0;
|
||||||
|
|
||||||
|
__asm__("bl main");
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void default_handler(void) {
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void uart_handler_proxy(void) {
|
||||||
|
NVIC->ISPR[0] = (1 << UART_INTERRUPT);
|
||||||
|
isr();
|
||||||
|
NVIC->ICPR[0] = (1 << UART_INTERRUPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const void* isr_vector[] __attribute__((__used__)) __attribute__((section(".isr_vector"))) = {
|
||||||
|
&_fstack,
|
||||||
|
_start, // reset
|
||||||
|
default_handler, // nmi
|
||||||
|
default_handler, // hard fault
|
||||||
|
default_handler, // mem manage
|
||||||
|
default_handler, // bus fault
|
||||||
|
default_handler, // usage fault
|
||||||
|
(void *) 0x55, // reserved
|
||||||
|
0, // reserved
|
||||||
|
0, // reserved
|
||||||
|
0, // reserved
|
||||||
|
default_handler, // svc
|
||||||
|
default_handler, // debug mon
|
||||||
|
0, // reserved
|
||||||
|
default_handler, // pend sv
|
||||||
|
default_handler, // systick
|
||||||
|
// external
|
||||||
|
uart_handler_proxy,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
default_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
__asm__ (
|
||||||
|
"__gnu_thumb1_case_uhi:\n"
|
||||||
|
"push {r0, r1}\n"
|
||||||
|
"mov r1, lr\n"
|
||||||
|
"lsrs r1, r1, #1\n"
|
||||||
|
"lsls r0, r0, #1\n"
|
||||||
|
"lsls r1, r1, #1\n"
|
||||||
|
"ldrh r1, [r1, r0]\n"
|
||||||
|
"lsls r1, r1, #1\n"
|
||||||
|
"add lr, lr, r1\n"
|
||||||
|
"pop {r0, r1}\n"
|
||||||
|
"bx lr\n"
|
||||||
|
);
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef __IRQ_H
|
||||||
|
#define __IRQ_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "system.h"
|
||||||
|
#include "generated/soc.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern volatile unsigned int irqs_enabled;
|
||||||
|
|
||||||
|
static inline unsigned int irq_getie(void)
|
||||||
|
{
|
||||||
|
return irqs_enabled; /* FIXME */
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void irq_setie(unsigned int ie)
|
||||||
|
{
|
||||||
|
if (ie)
|
||||||
|
__asm__ volatile ("cpsie i" : : : "memory");
|
||||||
|
else
|
||||||
|
__asm__ volatile ("cpsid i" : : : "memory");
|
||||||
|
irqs_enabled = ie;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int irq_getmask(void)
|
||||||
|
{
|
||||||
|
return (1 << UART_INTERRUPT); // FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void irq_setmask(unsigned int mask)
|
||||||
|
{
|
||||||
|
// fixme: there are more interrupts
|
||||||
|
NVIC->ISER[0] = mask;
|
||||||
|
NVIC->ICER[0] = ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int irq_pending(void)
|
||||||
|
{
|
||||||
|
// fixme: there are more interrupts
|
||||||
|
return NVIC->ISPR[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __IRQ_H */
|
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef __SYSTEM_H
|
||||||
|
#define __SYSTEM_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define UART_POLLING
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
volatile uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
|
||||||
|
uint32_t RESERVED0[24];
|
||||||
|
volatile uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
|
||||||
|
uint32_t RSERVED1[24];
|
||||||
|
volatile uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
|
||||||
|
uint32_t RESERVED2[24];
|
||||||
|
volatile uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
|
||||||
|
uint32_t RESERVED3[24];
|
||||||
|
volatile uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
|
||||||
|
uint32_t RESERVED4[56];
|
||||||
|
volatile uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
|
||||||
|
uint32_t RESERVED5[644];
|
||||||
|
volatile uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
|
||||||
|
} NVIC_Type;
|
||||||
|
|
||||||
|
#define SCS_BASE (0xE000E000UL)
|
||||||
|
#define NVIC_BASE (SCS_BASE + 0x0100UL)
|
||||||
|
#define NVIC ((NVIC_Type *) NVIC_BASE)
|
||||||
|
|
||||||
|
__attribute__((unused)) static void flush_cpu_icache(void){}; /* No instruction cache */
|
||||||
|
__attribute__((unused)) static void flush_cpu_dcache(void){}; /* No instruction cache */
|
||||||
|
void flush_l2_cache(void);
|
||||||
|
|
||||||
|
void busy_wait(unsigned int ms);
|
||||||
|
void busy_wait_us(unsigned int us);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __SYSTEM_H */
|
Loading…
Reference in New Issue