Commit 5202dd9b authored by Angus Ainslie's avatar Angus Ainslie

Initial commit of iMX8 Cortex M4 code

** need to add licensing information
parents
*.elf
*.bin
*.o
*.map
CC = arm-none-eabi-gcc
OBJCOPY = arm-none-eabi-objcopy
# AFLAGS = -nostdinc -nostdlib
# CFLAGS = -nostdinc -nostdlib -W -Wall
# CFLAGS += -O2
CFLAGS += -march=armv7e-m -mthumb
AFLAGS += -march=armv7e-m -mthumb
#CFLAGS = -nostartfiles
#arm-none-eabi-gcc $(CXXFLAGS) -o $(TARGET) $(SOURCES) $(LIBS) -fno-zero-initialized-in-bss -mcpu=cortex-m4 -mfloat-abi=softfp -mthumb -mlittle-endian -T cortex_m4.ld -nostartfiles -Wl,-Map,test.map,--cref,-n
# arm-none-eabi-objcopy -O binary test.out test_m4.bin
all: m4.bin
m4.bin: m4.elf
${OBJCOPY} -O binary m4.elf m4.bin
m4.elf: m4_start.o m4_main.o iomux-v3.o
#${CC} ${CFLAGS} -Wl,-Ttext,0x00180000 -Wl,-T ldscript -Wl,-Map -Wl,m4.map -nostdlib --o $@ $?
${CC} $(CXXFLAGS) -o $@ $^ -fno-zero-initialized-in-bss -mcpu=cortex-m4 -mfloat-abi=softfp -mthumb -mlittle-endian -T ldscript -nostartfiles -Wl,-Map,m4.map,--cref,-n
#${CC} $(CXXFLAGS) -o $@ $^ -fno-zero-initialized-in-bss -mcpu=cortex-m4 -mfloat-abi=softfp -mthumb -mlittle-endian -Wl,-Ttext,0x007e0000 -T ldscript -nostartfiles -Wl,-Map,m4.map,--cref,-n
clean:
rm -f *.o m4.bin m4.elf m4.map
/*
based on code from here
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/include/asm/io.h?h=v4.16-rc5
*/
#ifndef __IO_H__
#define __IO_H_
#include <inttypes.h>
#define REG(base,reg) ((volatile unsigned int *)((char *)base + reg))
static inline void __raw_writel(uint32_t val, volatile void *addr)
{
asm volatile("str %1, %0"
: "+Qo" (*(volatile uint32_t *)addr)
: "r" (val));
}
static inline uint32_t __raw_readl(const volatile void *addr)
{
uint32_t val;
asm volatile("ldr %1, %0"
: "+Qo" (*(volatile uint32_t *)addr),
"=r"
(val));
return val;
}
#endif
#define MX8MQ_PAD_GPIO5_IO22__UART1_RXD \
IOMUX_PAD(0x049c, 0x0234, 0, 0, 0, NO_PAD_CTRL)
#define MX8MQ_PAD_GPIO5_IO23__UART1_TXD \
IOMUX_PAD(0x04a0, 0x0238, 0, 0, 0, NO_PAD_CTRL)
#define MX8MQ_PAD_GPIO5_IO24__UART2_RXD \
IOMUX_PAD(0x04a4, 0x023c, 0, 0, 0, NO_PAD_CTRL)
#define MX8MQ_PAD_GPIO5_IO25__UART2_TXD \
IOMUX_PAD(0x04a8, 0x0240, 0, 0, 0, NO_PAD_CTRL)
/*
#define IOMUX_PAD(pad_ctrl_ofs, mux_ctrl_ofs, mux_mode, sel_input_ofs, \
sel_input, pad_ctrl) \
(((uint64_t)(mux_ctrl_ofs) << MUX_CTRL_OFS_SHIFT) | \
((uint64_t)(mux_mode) << MUX_MODE_SHIFT) | \
((uint64_t)(pad_ctrl_ofs) << MUX_PAD_CTRL_OFS_SHIFT) | \
((uint64_t)(pad_ctrl) << MUX_PAD_CTRL_SHIFT) | \
((uint64_t)(sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT) | \
((uint64_t)(sel_input) << MUX_SEL_INPUT_SHIFT))
#define MX8MQ_IOMUXC_UART1_RXD_GPIO5_IO22 0x234 0x49C 0x000 0x5 0x0
#define MX8MQ_IOMUXC_UART1_TXD_GPIO5_IO23 0x238 0x4A0 0x000 0x5 0x0
#define MX8MQ_IOMUXC_UART2_RXD_GPIO5_IO24 0x23C 0x4A4 0x000 0x5 0x0
#define MX8MQ_IOMUXC_UART2_TXD_GPIO5_IO25 0x240 0x4A8 0x000 0x5 0x0
*/
/*
* Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
* Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
* <armlinux@phytec.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mach-imx?h=v4.16-rc5
*
*/
//#include <stdio.h>
#include <inttypes.h>
#include "io.h"
#include "iomux-v3.h"
//static uint32_t base = 0x420E0000;
static void *base = 0x30330000;
int32_t iomux_v3_setup_pad(uint64_t pad)
{
uint32_t mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT;
uint32_t mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT;
uint32_t sel_input_ofs = (pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT;
uint32_t sel_input = (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT;
uint32_t pad_ctrl_ofs = (pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT;
uint32_t pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT;
if (mux_ctrl_ofs)
__raw_writel(mux_mode, base + mux_ctrl_ofs);
if (sel_input_ofs)
__raw_writel(sel_input, base + sel_input_ofs);
if (!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs)
__raw_writel(pad_ctrl, base + pad_ctrl_ofs);
return 0;
}
int32_t iomux_v3_setup_multiple_pads(uint64_t const *pad_list, uint32_t count)
{
uint64_t const *p = pad_list;
int32_t i;
int32_t ret;
for (i = 0; i < count; i++) {
ret = iomux_v3_setup_pad(*p);
if (ret)
return ret;
p++;
}
return 0;
}
/*
* Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
* <armlinux@phytec.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mach-imx?h=v4.16-rc5
*/
#ifndef _IOMUX_V3_H
#define _IOMUX_V3_H
#define PAD_CTL_HYS (1 << 16)
#define PAD_CTL_PUS_100K_DOWN (0 << 14)
#define PAD_CTL_PUS_47K_UP (1 << 14)
#define PAD_CTL_PUS_100K_UP (2 << 14)
#define PAD_CTL_PUS_22K_UP (3 << 14)
#define PAD_CTL_PUE (1 << 13)
#define PAD_CTL_PKE (1 << 12)
#define PAD_CTL_ODE (1 << 11)
#define PAD_CTL_SPEED_LOW (1 << 6)
#define PAD_CTL_SPEED_MED (2 << 6)
#define PAD_CTL_SPEED_HIGH (3 << 6)
#define PAD_CTL_DSE_DISABLE (0 << 3)
#define PAD_CTL_DSE_240ohm (1 << 3)
#define PAD_CTL_DSE_120ohm (2 << 3)
#define PAD_CTL_DSE_80ohm (3 << 3)
#define PAD_CTL_DSE_60ohm (4 << 3)
#define PAD_CTL_DSE_40ohm (5 << 3)
#define PAD_CTL_DSE_34ohm (6 << 3)
#define PAD_CTL_SRE_FAST (1 << 0)
#define PAD_CTL_SRE_SLOW (0 << 0)
#define MUX_CTRL_OFS_SHIFT 0
#define MUX_CTRL_OFS_MASK ((uint64_t)0xfff << MUX_CTRL_OFS_SHIFT)
#define MUX_PAD_CTRL_OFS_SHIFT 12
#define MUX_PAD_CTRL_OFS_MASK ((uint64_t)0xfff << MUX_PAD_CTRL_OFS_SHIFT)
#define MUX_SEL_INPUT_OFS_SHIFT 24
#define MUX_SEL_INPUT_OFS_MASK ((uint64_t)0xfff << MUX_SEL_INPUT_OFS_SHIFT)
#define MUX_MODE_SHIFT 36
#define MUX_MODE_MASK ((uint64_t)0x1f << MUX_MODE_SHIFT)
#define MUX_PAD_CTRL_SHIFT 41
#define MUX_PAD_CTRL_MASK ((uint64_t)0x3ffff << MUX_PAD_CTRL_SHIFT)
#define MUX_SEL_INPUT_SHIFT 59
#define MUX_SEL_INPUT_MASK ((uint64_t)0xf << MUX_SEL_INPUT_SHIFT)
#define NO_PAD_CTRL (1 << 17)
#define MUX_PAD_CTRL(x) ((uint64_t)(x) << MUX_PAD_CTRL_SHIFT)
#define IOMUX_PAD(pad_ctrl_ofs, mux_ctrl_ofs, mux_mode, sel_input_ofs, \
sel_input, pad_ctrl) \
(((uint64_t)(mux_ctrl_ofs) << MUX_CTRL_OFS_SHIFT) | \
((uint64_t)(mux_mode) << MUX_MODE_SHIFT) | \
((uint64_t)(pad_ctrl_ofs) << MUX_PAD_CTRL_OFS_SHIFT) | \
((uint64_t)(pad_ctrl) << MUX_PAD_CTRL_SHIFT) | \
((uint64_t)(sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT) | \
((uint64_t)(sel_input) << MUX_SEL_INPUT_SHIFT))
int32_t iomux_v3_setup_pad(uint64_t pad);
int32_t iomux_v3_setup_multiple_pads(uint64_t const *pad_list, uint32_t count);
#endif
OUTPUT_ARCH(arm)
SECTIONS
{
.text :
{
*(.text)
*(.text.*)
}
. = ALIGN(32);
.data :
{
}
. = ALIGN(32);
.sbss :
{
}
. = ALIGN(32);
.bss :
{
}
}
/*
based on code found here
https://github.com/ryo/netbsdimx7_m4loader
*/
#include <inttypes.h>
#include "io.h"
#include "iomux-v3.h"
#include "iomux-mx8mq.h"
#define CONADDR1 0x30860000 // UART1
#define CONADDR2 0x30890000 // UART2
#define IMX_UTXD 0x40 /* w */ /* UART Transmitter Reg */
#define IMX_UCR1 0x80 /* rw */ /* UART Control Reg 1 */
#define IMX_UCR2 0x84 /* rw */ /* UART Control Reg 2 */
#define IMX_UCR3 0x88 /* rw */ /* UART Control Reg 3 */
#define IMX_UCR4 0x8c /* rw */ /* UART Control Reg 4 */
#define IMX_UFCR 0x90 /* rw */ /* UART FIFO Control Reg */
#define IMX_USR1 0x94 /* rw */ /* UART Status Reg 1 */
#define IMX_USR2 0x98 /* rw */ /* UART Status Reg 2 */
#define IMX_USR2_TXDC (1<<3)
#define IMX_UCR2_TXEN (1<<2)
#define IMX_UCR2_RXEN (1<<1)
#define IMX_UCR2_WS (1<<5)
#define IMX_UCR2_IRTS (1<<14)
#define IMX_UCR1_UARTEN (1)
static void
xputc(char c, int console)
{
volatile unsigned int *tcmh = (int *)0x20008000; // debug
unsigned int x = 0x100; // debug
uint32_t console_addr;
if( console == 1 )
console_addr = CONADDR1;
else
console_addr - CONADDR2;
*tcmh = __LINE__; // debug
while ((__raw_readl((void *)console_addr + IMX_USR2) & IMX_USR2_TXDC) == 0) {
*tcmh = x++; // debug
}
__raw_writel(c, (void *)console_addr + IMX_UTXD);
}
static void
xputs(char *s)
{
volatile unsigned int *tcmh = (int *)0x20009000; // debug
while (*s)
{
xputc(*s++, 1);
xputc(*s++, 2);
*tcmh++ = *s;
}
}
static void
setup_uart(int uart)
{
uint32_t console_addr;
uint32_t reg_val;
if( uart == 1 )
console_addr = CONADDR1;
else
console_addr - CONADDR2;
/*
while ((__raw_readl((void *)console_addr + IMX_USR2) & IMX_USR2_TXDC) == 0) {
// wait for send to finish
}
*/
reg_val = IMX_UCR2_TXEN | IMX_UCR2_RXEN | IMX_UCR2_WS | IMX_UCR2_IRTS;
__raw_writel(reg_val, (void *)console_addr + IMX_UCR2);
reg_val = IMX_UCR1_UARTEN;
__raw_writel(reg_val, (void *)console_addr + IMX_UCR1);
}
void
cortexM4_main(void)
{
volatile unsigned int *tcmh = (int *)0x2000a000; // debug
*tcmh = 0xa5a5; // debug
//iomux_v3_setup_pad(MX8MQ_PAD_GPIO5_IO22__UART1_RXD);
//iomux_v3_setup_pad(MX8MQ_PAD_GPIO5_IO23__UART1_TXD);
//iomux_v3_setup_pad(MX8MQ_PAD_GPIO5_IO24__UART2_RXD);
//iomux_v3_setup_pad(MX8MQ_PAD_GPIO5_IO25__UART2_TXD);
setup_uart(2);
xputs("Hello CortexM4\r\n");
for (;;)
asm("wfi");
}
/*
based on code found here
https://github.com/ryo/netbsdimx7_m4loader
*/
.arch armv7e-m
.thumb
cortexM4_vector_table:
.long cortexM4_stack // initail SP value
.long cortexM4_reset+1 // Reset
.long cortexM4_nmi+1 // NMI
.long cortexM4_hardfault+1 // Hard fault
.long cortexM4_mmufault+1 // Memory management fault
.long cortexM4_busfault+1 // Bus fault
.long cortexM4_usagefault+1 // Usage fault
.long 0 // Reserved
.long 0 // Reserved
.long 0 // Reserved
.long 0 // Reserved
.long cortexM4_svc+1 // SVCall
.long cortexM4_debug+1 // Reserved for Debug
.long 0 // Reserved
.long cortexM4_pendsv+1 // PendSV
.long cortexM4_systick+1 // Systick
#define NIRQ 256
.space 4 * NIRQ // IRQ 0...N-1
.space 1024
cortexM4_stack:
/* XXX */
cortexM4_nmi:
cortexM4_hardfault:
cortexM4_mmufault:
cortexM4_busfault:
cortexM4_usagefault:
cortexM4_svc:
cortexM4_debug:
cortexM4_pendsv:
cortexM4_systick:
nop
#1: wfi
1: nop
b 1b
cortexM4_reset:
cpsid i
b cortexM4_main
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment