1
0
mirror of https://github.com/mist-devel/mist-firmware.git synced 2026-01-11 23:43:04 +00:00

Move HW specific parts to hw/

This commit is contained in:
Gyorgy Szombathelyi 2021-07-15 19:18:15 +02:00
parent 9ce37feebf
commit 9193f06134
46 changed files with 2670 additions and 635 deletions

View File

@ -9,9 +9,8 @@
#include "ff.h" /* Obtains integer types */
#include "diskio.h" /* Declarations of disk functions */
#include "usb.h"
#include "usbrtc.h"
#include "../mmc.h"
#include "hardware.h"
#include "mmc.h"
/* Definitions of physical drive number for each drive */
#define DEV_MMC 0
@ -213,7 +212,7 @@ DWORD get_fattime()
uint8_t date[7]; //year,month,date,hour,min,sec,day
DWORD fattime = ((DWORD)(FF_NORTC_YEAR - 1980) << 25 | (DWORD)FF_NORTC_MON << 21 | (DWORD)FF_NORTC_MDAY << 16);
if (usb_rtc_get_time((uint8_t*)&date)) {
if (GetRTC((uint8_t*)&date)) {
fattime = ((date[0] - 80) << 25) |
((date[1] & 0x0f) << 21) |
((date[2] & 0x1f) << 16) |

View File

@ -10,25 +10,25 @@ DUMP = $(BASE)-objdump
TODAY = `date +"%m/%d/%y"`
PRJ = firmware
SRC = Cstartup_SAM7.c fdd.c firmware.c fpga.c hardware.c spi.c hdd.c main.c menu.c mmc.c osd.c state.c syscalls.c user_io.c data_io.c boot.c idxfile.c config.c tos.c ikbd.c xmodem.c ini_parser.c cue_parser.c mist_cfg.c archie.c pcecd.c arc_file.c font.c utils.c
SRC = hw/AT91SAM/Cstartup_SAM7.c hw/AT91SAM/hardware.c hw/AT91SAM/spi.c hw/AT91SAM/mmc.c hw/AT91SAM/cdc_enumerate.c
SRC += fdd.c firmware.c fpga.c hdd.c main.c menu.c osd.c state.c syscalls.c user_io.c data_io.c boot.c idxfile.c config.c tos.c ikbd.c xmodem.c ini_parser.c cue_parser.c mist_cfg.c archie.c pcecd.c arc_file.c font.c utils.c
SRC += usb/max3421e.c usb/usb.c usb/hub.c usb/hid.c usb/hidparser.c usb/timer.c usb/asix.c usb/pl2303.c usb/usbrtc.c usb/joymapping.c
SRC += fat_compat.c
SRC += FatFs/diskio.c FatFs/ff.c FatFs/ffunicode.c
# SRC += usb/storage.c
SRC += cdc_enumerate.c cdc_control.c
SRC += cdc_control.c
OBJ = $(SRC:.c=.o)
DEP = $(SRC:.c=.d)
LINKMAP = AT91SAM7S256-ROM.ld
LINKMAP = hw/AT91SAM/AT91SAM7S256-ROM.ld
LIBDIR =
# Commandline options for each tool.
# for ESA11 add -DEMIST
DFLAGS = -I. -Iusb -DMIST
CFLAGS = $(DFLAGS) -c -mthumb -fno-common -O2 --std=gnu99 -fsigned-char -DVDATE=\"`date +"%y%m%d"`\"
DFLAGS = -I. -Iusb -Iarch/ -Ihw/AT91SAM -DMIST -DCONFIG_ARCH_ARMV4TE -DCONFIG_ARCH_ARM
CFLAGS = $(DFLAGS) -c -march=armv4t -mtune=arm7tdmi -mthumb -fno-common -O2 --std=gnu99 -fsigned-char -DVDATE=\"`date +"%y%m%d"`\"
CFLAGS-firmware.o += -marm
CFLAGS-spi.o += -marm
CFLAGS += $(CFLAGS-$@)
AFLAGS = -ahls -mapcs-32
LFLAGS = -mthumb -nostartfiles -Wl,-Map,$(PRJ).map -T$(LINKMAP) $(LIBDIR)
@ -43,7 +43,7 @@ LIBS =
all: $(PRJ).hex $(PRJ).upg
clean:
rm -f *.d *.o *.hex *.elf *.map *.lst core *~ */*.d */*.o $(MKUPG) *.bin *.upg *.exe
rm -f *.d *.o *.hex *.elf *.map *.lst core *~ */*.d */*.o */*/*.d */*/*.o $(MKUPG) *.bin *.upg *.exe
INTERFACE=interface/ftdi/olimex-arm-usb-tiny-h.cfg
#INTERFACE=interface/busblaster.cfg
@ -51,13 +51,17 @@ INTERFACE=interface/ftdi/olimex-arm-usb-tiny-h.cfg
ADAPTER_KHZ=10000
reset:
openocd -f $(INTERFACE) -f target/at91sam7sx.cfg --command "adapter_khz $(ADAPTER_KHZ); init; reset init; resume; shutdown"
openocd -f $(INTERFACE) -f target/at91sam7sx.cfg --command "adapter speed $(ADAPTER_KHZ); init; reset init; resume; shutdown"
$(MKUPG): $(MKUPG).c
gcc -o $@ $<
debug: $(PRJ).hex $(PRJ).upg $(PRJ).bin
openocd -f $(INTERFACE) -f target/at91sam7sx.cfg --command 'adapter speed $(ADAPTER_KHZ); init; reset init; resume; \
echo "*********************"; echo "Start GDB debug session with:"; echo "> gdb $(PRJ).elf"; echo "(gdb) target ext:3333"; echo "*********************"'
flash: $(PRJ).hex $(PRJ).upg $(PRJ).bin
openocd -f $(INTERFACE) -f target/at91sam7sx.cfg --command "adapter_khz $(ADAPTER_KHZ); init; reset init; flash protect 0 0 7 off; sleep 1; arm7_9 fast_memory_access enable; flash write_bank 0 $(PRJ).bin 0x0; resume; shutdown"
openocd -f $(INTERFACE) -f target/at91sam7sx.cfg --command "adapter speed $(ADAPTER_KHZ); init; reset init; flash protect 0 0 7 off; sleep 1; arm7_9 fast_memory_access enable; flash write_bank 0 $(PRJ).bin 0x0; resume; shutdown"
flash_sam: $(PRJ).hex
Sam_I_Am -x flash_sam_i_am
@ -78,7 +82,7 @@ $(PRJ).upg: $(PRJ).bin $(MKUPG)
./$(MKUPG) $< $@ `date +"%y%m%d"`
# Compile the C runtime.
crt.o: Cstartup.S
crt.o: hw/AT91SAM/Cstartup.S
$(AS) $(AFLAGS) -o $@ $< > crt.lst
%.o: %.c

73
arch/arm/barriers.h Normal file
View File

@ -0,0 +1,73 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef ARM_BARRIERS_H_
#define ARM_BARRIERS_H_
/*----------------------------------------------------------------------------
* Public functions
*----------------------------------------------------------------------------*/
#if defined(CONFIG_ARCH_ARMV5TE)
static inline void dmb(void)
{
asm("" ::: "memory");
}
static inline void dsb(void)
{
asm("mcr p15, 0, %0, c7, c10, 4" :: "r"(0) : "memory");
}
static inline void isb(void)
{
asm("" ::: "memory");
}
#elif defined(CONFIG_ARCH_ARMV7A) || defined(CONFIG_ARCH_ARMV7M)
static inline void dmb(void)
{
asm("dmb" ::: "memory");
}
static inline void dsb(void)
{
asm("dsb" ::: "memory");
}
static inline void isb(void)
{
asm("isb" ::: "memory");
}
#endif
#endif /* ARM_BARRIERS_H_ */

222
arch/arm/cp15.h Normal file
View File

@ -0,0 +1,222 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef CP15_H_
#define CP15_H_
#include <stdint.h>
/*----------------------------------------------------------------------------
* Definitions
*----------------------------------------------------------------------------*/
/* SCTLR: I - I-cache enable/disable
* 0 = I-cache disabled
* 1 = I-cache enabled
*/
#define CP15_SCTLR_I (1u << 12)
/* SCTLR: C - D-cache enable/disable
* 0 = D-cache disabled
* 1 = D-cache enabled
*/
#define CP15_SCTLR_C (1u << 2)
/* SCTLR: A - Alignment fault enable/disable
* 0 = Data address alignment fault checking disabled
* 1 = Data address alignment fault checking enabled
*/
#define CP15_SCTLR_A (1u << 1)
/* SCTLR: M - MMU enable/disable
* 0 = disabled
* 1 = enabled
*/
#define CP15_SCTLR_M (1u << 0)
/* ACTLR: EXCL - Exclusive L1/L2 cache control.
* 0 = non-exclusive
* 1 = exclusive
*/
#define CP15_ACTLR_EXCL (1u << 7)
/* No access: Any access generates a domain fault. */
#define CP15_DACR_NO_ACCESS(x) (0u << (2 * ((x) & 15)))
/* Client: Accesses are checked against the access permission bits in the
* section or page descriptor. */
#define CP15_DACR_CLIENT_ACCESS(x) (1u << (2 * ((x) & 15)))
/* Manager: Accesses are not checked against the access permission bits so a
* permission fault cannot be generated. */
#define CP15_DACR_MANAGER_ACCESS(x) (3u << (2 * ((x) & 15)))
/*------------------------------------------------------------------------------ */
/* Exported functions */
/*------------------------------------------------------------------------------ */
/**
* \brief Read the System Control Register (SCTLR).
* \return register contents
*/
static inline uint32_t cp15_read_sctlr(void)
{
uint32_t sctlr;
asm("mrc p15, 0, %0, c1, c0, 0" : "=r"(sctlr));
return sctlr;
}
/**
* \brief Modify the System Control Register (SCTLR).
* \param value new value for SCTLR
*/
static inline void cp15_write_sctlr(uint32_t value)
{
asm("mcr p15, 0, %0, c1, c0, 0" :: "r"(value));
}
/**
* \brief Read the Auxiliary Control Register (ACTLR).
* \return register contents
*/
static inline uint32_t cp15_read_actlr(void)
{
uint32_t actlr;
asm("mrc p15, 0, %0, c1, c0, 1" : "=r"(actlr));
return actlr;
}
/**
* \brief Modify the Auxiliary Control Register (ACTLR).
* \param value new value for ACTLR
*/
static inline void cp15_write_actlr(uint32_t value)
{
asm("mcr p15, 0, %0, c1, c0, 1" :: "r"(value));
}
/**
* \brief Read the Translation Table Base Register 0 (TTBR0).
* \return register contents
*/
static inline uint32_t cp15_read_ttbr0(uint32_t value)
{
uint32_t ttbr0;
asm("mrc p15, 0, %0, c2, c0, 0" : "=r"(ttbr0));
return ttbr0;
}
/**
* \brief Write the Translation Table Base Register 0 (TTBR0).
* \param value new value for TTBR0
*/
static inline void cp15_write_ttbr0(uint32_t value)
{
/* write TTBR */
asm("mcr p15, 0, %0, c2, c0, 0" :: "r"(value));
}
/**
* \brief Read the Domain Access Control Register (DACR).
* \return register contents
*/
static inline uint32_t cp15_read_dacr(void)
{
uint32_t dacr;
asm("mrc p15, 0, %0, c3, c0, 0" : "=r"(dacr));
return dacr;
}
/**
* \brief Modify the Domain Access Control Register (DACR).
* \param value new value for DACR
*/
static inline void cp15_write_dacr(uint32_t value)
{
/* write DACR */
asm("mcr p15, 0, %0, c3, c0, 0" :: "r"(value));
}
/**
* \brief ICIALLU: Invalidate I-cache
*/
static inline void cp15_icache_invalidate(void)
{
asm("mcr p15, 0, %0, c7, c5, 0" :: "r"(0));
}
/**
* \brief DCISW - Invalidate DCache single entry (Set/Way)
*/
static inline void cp15_dcache_invalidate_setway(uint32_t setway)
{
asm("mcr p15, 0, %0, c7, c6, 2" :: "r"(setway));
}
/**
* \brief DCCSW: Clean DCache single entry (Set/Way)
*/
static inline void cp15_dcache_clean_setway(uint32_t setway)
{
asm("mcr p15, 0, %0, c7, c10, 2" :: "r"(setway));
}
/**
* \brief DCCISW - Clean and invalidate DCache entry (Set/Way)
*/
static inline void cp15_dcache_clean_invalidate_setway(uint32_t setway)
{
asm("mcr p15, 0, %0, c7, c14, 2" :: "r"(setway));
}
/**
* \brief DCIMVAC - Invalidate DCache single entry (MVA)
*/
static inline void cp15_dcache_invalidate_mva(uint32_t mva)
{
asm("mcr p15, 0, %0, c7, c6, 1" :: "r"(mva));
}
/**
* \brief DCCMVAC - Clean DCache single entry (MVA)
*/
static inline void cp15_dcache_clean_mva(uint32_t mva)
{
asm("mcr p15, 0, %0, c7, c10, 1" :: "r"(mva));
}
/**
* \brief DCCIMVAC - Clean and invalidate DCache entry (MVA)
*/
static inline void cp15_dcache_clean_invalidate_mva(uint32_t mva)
{
asm("mcr p15, 0, %0, c7, c14, 1" :: "r"(mva));
}
#endif /* CP15_H_ */

64
arch/arm/cpuidle.h Normal file
View File

@ -0,0 +1,64 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef ARM_CPUIDLE_H_
#define ARM_CPUIDLE_H_
/*----------------------------------------------------------------------------
* Public functions
*----------------------------------------------------------------------------*/
#if defined(CONFIG_ARCH_ARMV5TE)
static inline void cpu_idle(void)
{
/* drain write buffer */
asm("mcr p15, 0, %0, c7, c10, 4" :: "r"(0) : "memory");
/* wait for interrupt */
asm("mcr p15, 0, %0, c7, c0, 4" :: "r"(0) : "memory");
}
#elif defined(CONFIG_ARCH_ARMV7A)
static inline void cpu_idle(void)
{
asm("dsb" ::: "memory");
asm("wfi" ::: "memory");
}
#elif defined(CONFIG_ARCH_ARMV7M)
static inline void cpu_idle(void)
{
asm("wfi" ::: "memory");
}
#endif
#endif /* ARM_CPUIDLE_H_ */

195
arch/arm/fault_handlers.c Normal file
View File

@ -0,0 +1,195 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2015, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "arm/fault_handlers.h"
#include <stdio.h>
#include <stdint.h>
/*----------------------------------------------------------------------------
* Constants
*----------------------------------------------------------------------------*/
#ifdef CONFIG_HAVE_FAULT_DEBUG
/* IFSR status */
static const char* _prefetch_abort_status[32] = {
NULL,
NULL,
"debug event",
"access flag fault, section",
NULL,
"translation fault, section",
"access flag fault, page",
"translation fault, page",
"synchronous external abort",
"domain fault, section",
NULL,
"domain fault, page",
"L1 translation, synchronous external abort",
"permission fault, section",
"L2 translation, synchronous external abort",
"permission fault, page",
};
/* DFSR status */
static const char* _data_abort_status[32] = {
NULL,
"alignment fault",
"debug event",
"access flag fault, section",
"instruction cache maintenance fault",
"translation fault, section",
"access flag fault, page",
"translation fault, page",
"synchronous external abort, nontranslation",
"domain fault, section",
NULL,
"domain fault, page",
"1st level translation, synchronous external abort",
"permission fault, section",
"2nd level translation, synchronous external abort",
"permission fault, page",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
"asynchronous external abort"
};
#endif /* CONFIG_HAVE_FAULT_DEBUG */
/*----------------------------------------------------------------------------
* Functions
*----------------------------------------------------------------------------*/
/**
* \brief Default handler for "Undefined Instruction" exception
*/
void undefined_instruction_irq_handler(void)
{
#ifdef CONFIG_HAVE_FAULT_DEBUG
printf("\r\n");
printf("#####################\r\n");
printf("Undefined Instruction\r\n");
printf("#####################\r\n");
#endif
#ifdef NDEBUG
asm("bkpt #1");
#endif
while(1);
}
/**
* \brief Default handler for "Software Interrupt" exception
*/
void software_interrupt_irq_handler(void)
{
#ifdef CONFIG_HAVE_FAULT_DEBUG
printf("\r\n");
printf("##################\r\n");
printf("Software Interrupt\r\n");
printf("##################\r\n");
#endif
#ifdef NDEBUG
asm("bkpt #2");
#endif
while(1);
}
/**
* \brief Default handler for "Data Abort" exception
*/
void data_abort_irq_handler(void)
{
#ifdef CONFIG_HAVE_FAULT_DEBUG
uint32_t v1, v2, dfsr;
asm("mrc p15, 0, %0, c5, c0, 0" : "=r"(v1));
asm("mrc p15, 0, %0, c6, c0, 0" : "=r"(v2));
printf("\r\n");
printf("####################\r\n");
dfsr = ((v1 >> 4) & 0x0F);
printf("Data Fault occured in %x domain\r\n", (unsigned int)dfsr);
dfsr = (((v1 & 0x400) >> 6) | (v1 & 0x0F));
if (_data_abort_status[dfsr])
printf("Data Fault reason is: %s\r\n", _data_abort_status[dfsr]);
else
printf("Data Fault reason is unknown\r\n");
printf("Data Fault occured at address: 0x%08x\r\n", (unsigned int)v2);
printf("Data Fault status register value: 0x%x\r\n", (unsigned int)v1);
printf("####################\n\r");
#endif
#ifdef NDEBUG
asm("bkpt #4");
#endif
#ifdef CONFIG_HAVE_FAULT_DEBUG
while(1);
#endif
}
/**
* \brief Default handler for "Prefetch Abort" exception
*/
void prefetch_abort_irq_handler(void)
{
#ifdef CONFIG_HAVE_FAULT_DEBUG
uint32_t v1, v2, ifsr;
asm("mrc p15, 0, %0, c5, c0, 1" : "=r"(v1));
asm("mrc p15, 0, %0, c6, c0, 2" : "=r"(v2));
printf("\r\n");
printf("####################\r\n");
ifsr = (((v1 & 0x400) >> 6) | (v1 & 0x0F));
if (_prefetch_abort_status[ifsr])
printf("Prefetch Fault reason is: %s\r\n", _prefetch_abort_status[ifsr]);
else
printf("Prefetch Fault reason is unknown\r\n");
printf("prefetch Fault occured at address: 0x%08x\r\n", (unsigned int)v2);
printf("Prefetch Fault status register value: 0x%x\r\n", (unsigned int)v1);
printf("####################\n\r");
#endif
#ifdef NDEBUG
asm("bkpt #3");
#endif
while(1);
}

49
arch/arm/fault_handlers.h Normal file
View File

@ -0,0 +1,49 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2015, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* ARM core interrupt handlers
*
*/
#ifndef ARM_FAULT_HANDLERS_H
#define ARM_FAULT_HANDLERS_H
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
extern void undefined_instruction_irq_handler(void);
extern void software_interrupt_irq_handler(void);
extern void prefetch_abort_irq_handler(void);
extern void data_abort_irq_handler(void);
#endif /* ARM_FAULT_HANDLERS_H */

85
arch/arm/irqflags.h Normal file
View File

@ -0,0 +1,85 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef ARM_IRQFLAGS_H_
#define ARM_IRQFLAGS_H_
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include <stdint.h>
/*----------------------------------------------------------------------------
* Public functions
*----------------------------------------------------------------------------*/
#if defined(CONFIG_ARCH_ARMV5TE) || defined(CONFIG_ARCH_ARMV4TE)
static inline void arch_irq_enable(void)
{
uint32_t cpsr;
asm("mrs %0, cpsr" : "=r"(cpsr));
asm("msr cpsr_c, %0" :: "r"(cpsr & ~0x80));
}
static inline void arch_irq_disable(void)
{
uint32_t cpsr;
asm("mrs %0, cpsr" : "=r"(cpsr));
asm("msr cpsr_c, %0" :: "r"(cpsr | 0x80));
}
#elif defined(CONFIG_ARCH_ARMV7A)
static inline void arch_irq_enable(void)
{
asm("cpsie if");
}
static inline void arch_irq_disable(void)
{
asm("cpsid if");
}
#elif defined(CONFIG_ARCH_ARMV7M)
static inline void arch_irq_enable(void)
{
asm("cpsie i");
}
static inline void arch_irq_disable(void)
{
asm("cpsid i");
}
#endif
#endif /* ARM_IRQFLAGS_H_ */

187
arch/arm/l1cache_cp15.c Normal file
View File

@ -0,0 +1,187 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2015-2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
* L1 Cache functions implementation for ARMv5-TE and ARMv7-A
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include "barriers.h"
#include "arm/cp15.h"
#include "l1cache.h"
#include <assert.h>
/*----------------------------------------------------------------------------
* Global functions
*----------------------------------------------------------------------------*/
void icache_invalidate(void)
{
cp15_icache_invalidate();
isb();
}
bool icache_is_enabled(void)
{
return (cp15_read_sctlr() & CP15_SCTLR_I) != 0;
}
void icache_enable(void)
{
uint32_t sctlr = cp15_read_sctlr();
if ((sctlr & CP15_SCTLR_I) == 0) {
icache_invalidate();
cp15_write_sctlr(sctlr | CP15_SCTLR_I);
}
}
void icache_disable(void)
{
uint32_t sctlr = cp15_read_sctlr();
if (sctlr & CP15_SCTLR_I) {
cp15_write_sctlr(sctlr & ~CP15_SCTLR_I);
icache_invalidate();
}
}
bool dcache_is_enabled(void)
{
return (cp15_read_sctlr() & (CP15_SCTLR_C | CP15_SCTLR_M)) ==
(CP15_SCTLR_C | CP15_SCTLR_M);
}
void dcache_enable(void)
{
uint32_t sctlr = cp15_read_sctlr();
if ((sctlr & CP15_SCTLR_C) == 0) {
assert(sctlr & CP15_SCTLR_M);
dcache_invalidate();
cp15_write_sctlr(sctlr | CP15_SCTLR_C);
}
}
void dcache_disable(void)
{
uint32_t sctlr = cp15_read_sctlr();
if (sctlr & CP15_SCTLR_C) {
dcache_clean();
cp15_write_sctlr(sctlr & ~CP15_SCTLR_C);
dcache_invalidate();
}
}
void dcache_invalidate(void)
{
uint32_t set, way;
for (way = 0; way < L1_CACHE_WAYS; way++)
for (set = 0; set < L1_CACHE_SETS; set++)
cp15_dcache_invalidate_setway(L1_CACHE_SETWAY(set, way));
dsb();
}
void dcache_clean(void)
{
uint32_t set, way;
for (way = 0; way < L1_CACHE_WAYS; way++)
for (set = 0; set < L1_CACHE_SETS; set++)
cp15_dcache_clean_setway(L1_CACHE_SETWAY(set, way));
dsb();
}
void dcache_clean_invalidate(void)
{
uint32_t set, way;
for (way = 0; way < L1_CACHE_WAYS; way++)
for (set = 0; set < L1_CACHE_SETS; set++)
cp15_dcache_clean_invalidate_setway(L1_CACHE_SETWAY(set, way));
dsb();
}
void dcache_invalidate_region(uint32_t start, uint32_t end)
{
uint32_t mva;
assert(start < end);
for (mva = start & ~(L1_CACHE_BYTES - 1); mva < end; mva += L1_CACHE_BYTES)
cp15_dcache_invalidate_mva(mva);
dsb();
}
void dcache_clean_region(uint32_t start, uint32_t end)
{
uint32_t mva;
assert(start < end);
for (mva = start & ~(L1_CACHE_BYTES - 1); mva < end; mva += L1_CACHE_BYTES)
cp15_dcache_clean_mva(mva);
dsb();
}
void dcache_clean_invalidate_region(uint32_t start, uint32_t end)
{
uint32_t mva;
assert(start < end);
for (mva = start & ~(L1_CACHE_BYTES - 1); mva < end; mva += L1_CACHE_BYTES)
cp15_dcache_clean_invalidate_mva(mva);
dsb();
}
void dcache_set_exclusive(void)
{
uint32_t actlr = cp15_read_actlr();
actlr |= CP15_ACTLR_EXCL;
cp15_write_actlr(actlr);
}
void dcache_set_non_exclusive(void)
{
uint32_t actlr = cp15_read_actlr();
actlr &= ~CP15_ACTLR_EXCL;
cp15_write_actlr(actlr);
}

190
arch/arm/l1cache_scb.c Normal file
View File

@ -0,0 +1,190 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2015-2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
* L1 Cache functions implementation for ARMv7-M
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include "barriers.h"
#include "l1cache.h"
#include <assert.h>
/*----------------------------------------------------------------------------
* Global functions
*----------------------------------------------------------------------------*/
void icache_invalidate(void)
{
dsb();
isb();
SCB->SCB_ICIALLU = 0;
dsb();
isb();
}
bool icache_is_enabled(void)
{
return (SCB->SCB_CCR & SCB_CCR_IC) != 0;
}
void icache_enable(void)
{
if (!icache_is_enabled()) {
icache_invalidate();
SCB->SCB_CCR |= SCB_CCR_IC;
dsb();
isb();
}
}
void icache_disable(void)
{
if (icache_is_enabled()) {
dsb();
isb();
SCB->SCB_CCR &= ~SCB_CCR_IC;
icache_invalidate();
}
}
bool dcache_is_enabled(void)
{
return (SCB->SCB_CCR & SCB_CCR_DC) != 0;
}
void dcache_enable(void)
{
if (!dcache_is_enabled()) {
dcache_invalidate();
SCB->SCB_CCR |= SCB_CCR_DC;
dsb();
isb();
}
}
void dcache_disable(void)
{
if (dcache_is_enabled()) {
dsb();
SCB->SCB_CCR &= ~SCB_CCR_DC;
dcache_clean_invalidate();
}
}
void dcache_invalidate(void)
{
uint32_t set, way;
for (way = 0; way < L1_CACHE_WAYS; way++)
for (set = 0; set < L1_CACHE_SETS; set++)
SCB->SCB_DCISW = L1_CACHE_SETWAY(set, way);
dsb();
isb();
}
void dcache_clean(void)
{
uint32_t set, way;
for (way = 0; way < L1_CACHE_WAYS; way++)
for (set = 0; set < L1_CACHE_SETS; set++)
SCB->SCB_DCCSW = L1_CACHE_SETWAY(set, way);
dsb();
isb();
}
void dcache_clean_invalidate(void)
{
uint32_t set, way;
for (way = 0; way < L1_CACHE_WAYS; way++)
for (set = 0; set < L1_CACHE_SETS; set++)
SCB->SCB_DCCISW = L1_CACHE_SETWAY(set, way);
dsb();
isb();
}
void dcache_invalidate_region(uint32_t start, uint32_t end)
{
uint32_t mva;
assert(start < end);
for (mva = start & ~(L1_CACHE_BYTES - 1); mva < end; mva += L1_CACHE_BYTES)
SCB->SCB_DCIMVAC = mva;
dsb();
isb();
}
void dcache_clean_region(uint32_t start, uint32_t end)
{
uint32_t mva;
assert(start < end);
for (mva = start & ~(L1_CACHE_BYTES - 1); mva < end; mva += L1_CACHE_BYTES)
SCB->SCB_DCCMVAC = mva;
dsb();
isb();
}
void dcache_clean_invalidate_region(uint32_t start, uint32_t end)
{
uint32_t mva;
assert(start < end);
for (mva = start & ~(L1_CACHE_BYTES - 1); mva < end; mva += L1_CACHE_BYTES)
SCB->SCB_DCCIMVAC = mva;
dsb();
isb();
}
void dcache_set_exclusive(void)
{
/* Not implemented */
}
void dcache_set_non_exclusive(void)
{
/* Not implemented */
}

89
arch/arm/mmu_cp15.c Normal file
View File

@ -0,0 +1,89 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2015, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------ */
/* Headers */
/*------------------------------------------------------------------------------ */
#include "compiler.h"
#include "barriers.h"
#include "arm/cp15.h"
#include "arm/mmu_cp15.h"
#include "mm/l1cache.h"
#include "mm/mmu.h"
#include <assert.h>
/*------------------------------------------------------------------------------ */
/* Exported functions */
/*------------------------------------------------------------------------------ */
void mmu_configure(void *tlb)
{
assert(!mmu_is_enabled());
/* Translation Table Base Register 0 */
cp15_write_ttbr0((unsigned int)tlb);
/* Domain Access Register */
/* only domain 15: access are not checked */
cp15_write_dacr(0xC0000000);
dsb();
isb();
}
bool mmu_is_enabled(void)
{
return (cp15_read_sctlr() & CP15_SCTLR_M) != 0;
}
void mmu_enable(void)
{
uint32_t control;
control = cp15_read_sctlr();
if ((control & CP15_SCTLR_M) == 0)
cp15_write_sctlr(control | CP15_SCTLR_M);
}
void mmu_disable(void)
{
uint32_t control;
control = cp15_read_sctlr();
if (control & CP15_SCTLR_M) {
dcache_clean();
control &= ~(CP15_SCTLR_M | CP15_SCTLR_C);
cp15_write_sctlr(control);
dcache_invalidate();
}
}

93
arch/arm/mmu_cp15.h Normal file
View File

@ -0,0 +1,93 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2015, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef MMU_CP15_H_
#define MMU_CP15_H_
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdint.h>
#include "mm/mmu.h"
/*----------------------------------------------------------------------------
* Exported definitions
*----------------------------------------------------------------------------*/
/* TTB descriptor type for Section descriptor */
#define TTB_TYPE_SECT (2 << 0)
/* TTB Section Descriptor: Buffered/Non-Buffered (B) */
#define TTB_SECT_WRITE_THROUGH (0 << 2)
#define TTB_SECT_WRITE_BACK (1 << 2)
/* TTB Section Descriptor: Cacheable/Non-Cacheable (C) */
#define TTB_SECT_NON_CACHEABLE (0 << 3)
#define TTB_SECT_CACHEABLE (1 << 3)
#define TTB_SECT_STRONGLY_ORDERED (TTB_SECT_NON_CACHEABLE | TTB_SECT_WRITE_THROUGH)
#define TTB_SECT_SHAREABLE_DEVICE (TTB_SECT_NON_CACHEABLE | TTB_SECT_WRITE_BACK)
#define TTB_SECT_CACHEABLE_WT (TTB_SECT_CACHEABLE | TTB_SECT_WRITE_THROUGH)
#define TTB_SECT_CACHEABLE_WB (TTB_SECT_CACHEABLE | TTB_SECT_WRITE_BACK)
/* TTB Section Descriptor: Domain */
#define TTB_SECT_DOMAIN(x) (((x) & 15) << 5)
#if defined(CONFIG_ARCH_ARMV5TE)
/* TTB Section Descriptor: Should-Be-One (SBO) */
#define TTB_SECT_SBO (1 << 4)
/* TTB Section Descriptor: Access Privilege (AP) */
#define TTB_SECT_AP_PRIV_ONLY (1 << 10)
#define TTB_SECT_AP_NO_USER_WRITE (2 << 10)
#define TTB_SECT_AP_FULL_ACCESS (3 << 10)
#elif defined(CONFIG_ARCH_ARMV7A)
/* TTB Section Descriptor: Execute/Execute-Never (XN) */
#define TTB_SECT_EXEC (0 << 4)
#define TTB_SECT_EXEC_NEVER (1 << 4)
/* TTB Section Descriptor: Access Privilege (AP) */
#define TTB_SECT_AP_PRIV_ONLY ((0 << 15) | (1 << 10))
#define TTB_SECT_AP_NO_USER_WRITE ((0 << 15) | (2 << 10))
#define TTB_SECT_AP_FULL_ACCESS ((0 << 15) | (3 << 10))
#define TTB_SECT_AP_PRIV_READ_ONLY ((1 << 15) | (1 << 10))
#define TTB_SECT_AP_READ_ONLY ((1 << 15) | (2 << 10))
#endif /* CONFIG_ARCH_* */
/* TTB Section Descriptor: Section Base Address */
#define TTB_SECT_ADDR(x) ((x) & 0xFFF00000)
#endif /* MMU_CP15_H_ */

77
arch/arm/mpu_armv7m.c Normal file
View File

@ -0,0 +1,77 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*------------------------------------------------------------------------------ */
/* Headers */
/*------------------------------------------------------------------------------ */
#include "chip.h"
#include "barriers.h"
#include "arm/mpu_armv7m.h"
#include <assert.h>
/*------------------------------------------------------------------------------ */
/* Exported functions */
/*------------------------------------------------------------------------------ */
void mpu_configure(const void* config)
{
uint32_t* values = (uint32_t*)config;
while (*values != 0) {
MPU->MPU_REGION[0].MPU_RBAR = *values++;
MPU->MPU_REGION[0].MPU_RASR = *values++;
}
}
bool mpu_is_enabled(void)
{
return (MPU->MPU_CTRL & MPU_CTRL_ENABLE) != 0;
}
void mpu_enable(void)
{
/* Activate MemFault, BusFault & UsageFault exceptions */
SCB->SCB_SHCSR |= (SCB_SHCSR_MEMFAULTENA |
SCB_SHCSR_BUSFAULTENA |
SCB_SHCSR_USGFAULTENA);
/* Enable the MPU without the background region */
MPU->MPU_CTRL = MPU_CTRL_ENABLE;
dsb();
isb();
}
void mpu_disable(void)
{
MPU->MPU_CTRL = 0;
}

102
arch/arm/mpu_armv7m.h Normal file
View File

@ -0,0 +1,102 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef MPU_ARMV7M_H_
#define MPU_ARMV7M_H_
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdint.h>
#include "mm/mpu.h"
/*----------------------------------------------------------------------------
* Exported definitions
*----------------------------------------------------------------------------*/
/* Region Address and Index */
#define MPU_REGION(region, addr) (((addr) & MPU_RBAR_ADDR_Msk) |\
MPU_RBAR_REGION(region) | MPU_RBAR_VALID)
/* Region Sizes: region size is 2^(value+1)*/
#define MPU_REGION_SIZE(value) (MPU_RASR_SIZE(value))
/* Bitfield to disable some subregions
* (1 bit for each 1/8 of region, region must be bigger than 128 bytes) */
#define MPU_SUBREGION_DISABLE(value) (MPU_RASR_SRD(value))
/* --- Access Privilege constants --- */
/* Access Privilege: no access for all */
#define MPU_AP_NOACCESS (MPU_RASR_AP(0))
/* Access Privilege: no access for unprivileged, readonly for privileged */
#define MPU_AP_NOACCESS_PRIV_READONLY (MPU_RASR_AP(5))
/* Access Privilege: no access for unprivileged, read/write for privileged */
#define MPU_AP_NOACCESS_PRIV_READWRITE (MPU_RASR_AP(1))
/* Access Privilege: readonly for all */
#define MPU_AP_READONLY (MPU_RASR_AP(7))
/* Access Privilege: readonly for unprivileged, read/write for privileged */
#define MPU_AP_READONLY_PRIV_READWRITE (MPU_RASR_AP(2))
/* Access Privilege: read/write for all */
#define MPU_AP_READWRITE (MPU_RASR_AP(3))
/* --- Memory Types Attributes --- */
/* Strongly-Ordered Shareable */
#define MPU_ATTR_STRONGLY_ORDERED (MPU_RASR_TEX(0))
/* Device Shareable */
#define MPU_ATTR_DEVICE (MPU_RASR_TEX(0) | MPU_RASR_B)
/* Normal, Write-Through Read Allocate */
#define MPU_ATTR_NORMAL_WT (MPU_RASR_TEX(0) | MPU_RASR_C)
/* Normal, Write-Back Read Allocate */
#define MPU_ATTR_NORMAL_WB (MPU_RASR_TEX(0) | MPU_RASR_C | MPU_RASR_B)
/* Normal, Write-Back Read/Write Allocate */
#define MPU_ATTR_NORMAL_WB_WA (MPU_RASR_TEX(1) | MPU_RASR_C | MPU_RASR_B)
/* Normal, Non-cacheable */
#define MPU_ATTR_NORMAL (MPU_RASR_TEX(1))
/* Other Attributes */
#define MPU_ATTR_SHAREABLE (MPU_RASR_S)
#define MPU_ATTR_EXECUTE_NEVER (MPU_RASR_XN)
#define MPU_ATTR_ENABLE (MPU_RASR_ENABLE)
#endif /* MPU_ARMV7M_H_ */

88
arch/arm/mutex.c Normal file
View File

@ -0,0 +1,88 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2015, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#include "barriers.h"
#include "chip.h"
#include "mutex.h"
#include "cpuidle.h"
#include <stdint.h>
#include <stdbool.h>
#define MUTEX_LOCKED 1
#define MUTEX_UNLOCKED 0
void mutex_lock(mutex_t* mutex)
{
while (!mutex_try_lock(mutex)) {
cpu_idle();
}
}
#if defined(CONFIG_ARCH_ARMV7A) || defined(CONFIG_ARCH_ARMV7M)
bool mutex_try_lock(mutex_t* mutex)
{
uint32_t value;
while (true)
{
// Read the current mutex value and tag the mutex address for exclusive access by the executing processor
__asm volatile("ldrex %0, [%1]" : "=r"(value) : "r"(mutex));
if (value != MUTEX_UNLOCKED)
return false;
// Provided the executing processor still has exclusive access to the mutex address, lock it now
__asm volatile("strex %0, %1, [%2]" : "=&r"(value) : "r"(MUTEX_LOCKED), "r"(mutex));
if (value == 0) /* Check if strex was ok */
break;
}
dmb();
return true;
}
#elif defined(CONFIG_ARCH_ARMV5TE)
bool mutex_try_lock(mutex_t* mutex)
{
uint32_t value;
asm("swp %0, %1, [%2]" : "=&r"(value) : "r"(MUTEX_LOCKED), "r"(mutex));
return value == MUTEX_UNLOCKED;
}
#endif
void mutex_unlock(mutex_t* mutex)
{
dmb();
*mutex = MUTEX_UNLOCKED;
}
bool mutex_is_locked(const mutex_t* mutex)
{
return *mutex != MUTEX_UNLOCKED;
}

107
arch/arm/swab.h Normal file
View File

@ -0,0 +1,107 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef ARM_SWAB_H_
#define ARM_SWAB_H_
/*----------------------------------------------------------------------------
* Public functions
*----------------------------------------------------------------------------*/
#if defined(CONFIG_ARCH_ARMV4TE)
static inline uint16_t swab16(uint16_t value)
{
uint32_t result;
result = ((value & 0xff00) >> 8) |
((value & 0x00ff) << 8);
return result;
}
static inline uint32_t swab32(uint32_t value)
{
uint32_t result;
result = ((value & 0x000000ff)<<24) |
((value & 0x0000ff00)<<8) |
((value & 0x00ff0000)>>8) |
((value & 0xff000000)>>24);
return result;
}
#elif defined(CONFIG_ARCH_ARMV5TE)
static inline uint16_t swab16(uint16_t value)
{
uint32_t result;
result = ((value & 0xff00) >> 8) |
((value & 0x00ff) << 8);
return result;
}
static inline uint32_t swab32(uint32_t value)
{
uint32_t result;
// ARMv5TE does not support the "rev" instruction
asm("eor r3, %1, %1, ror #16\n"
"bic r3, r3, #0xff0000\n"
"mov %0, %1, ror #8\n"
"eor %0, %0, r3, lsr #8" : "=r"(result) : "0"(value) : "r3","cc");
return result;
}
#elif defined(CONFIG_ARCH_ARMV7A) ||\
defined(CONFIG_ARCH_ARMV7M)
static inline uint16_t swab16(uint16_t value)
{
uint32_t result;
asm("rev16 %0, %1" : "=r"(result) : "r"(value));
return result;
}
static inline uint32_t swab32(uint32_t value)
{
uint32_t result;
asm("rev %0, %1" : "=r"(result) : "r"(value));
return result;
}
#endif
#endif /* ARM_SWAB_H_ */

39
arch/barriers.h Normal file
View File

@ -0,0 +1,39 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef BARRIERS_H_
#define BARRIERS_H_
#if defined(CONFIG_ARCH_ARM)
#include "arm/barriers.h"
#else
#error Unsupported architecture!
#endif
#endif /* BARRIERS_H_ */

39
arch/cpuidle.h Normal file
View File

@ -0,0 +1,39 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef CPUIDLE_H_
#define CPUIDLE_H_
#if defined(CONFIG_ARCH_ARM)
#include "arm/cpuidle.h"
#else
#error Unsupported architecture!
#endif
#endif /* CPUIDLE_H_ */

39
arch/irqflags.h Normal file
View File

@ -0,0 +1,39 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef IRQFLAGS_H_
#define IRQFLAGS_H_
#if defined(CONFIG_ARCH_ARM)
#include "arm/irqflags.h"
#else
#error Unsupported architecture!
#endif
#endif /* IRQFLAGS_H_ */

138
arch/l1cache.h Normal file
View File

@ -0,0 +1,138 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2015, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef L1CACHE_H_
#define L1CACHE_H_
/*
* Functions related to L1 cache maintenance (I-Cache and D-Cache).
*
* Actual implementation is located in arch/ since L1 is part of the CPU core.
*/
#ifdef CONFIG_HAVE_L1CACHE
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
/*------------------------------------------------------------------------------
* Exported functions
*------------------------------------------------------------------------------*/
/**
* \brief Invalidate all instruction cache.
*/
extern void icache_invalidate(void);
/**
* \brief Check if instruction cache is enabled.
*/
extern bool icache_is_enabled(void);
/**
* \brief Enable instruction cache.
*/
extern void icache_enable(void);
/**
* \brief Disable instruction cache.
*/
extern void icache_disable(void);
/**
* \brief Check if data cache is enabled.
*/
extern bool dcache_is_enabled(void);
/**
* \brief Enable data cache.
*/
extern void dcache_enable(void);
/**
* \brief Disable the data cache.
*/
extern void dcache_disable(void);
/**
* \brief Clean the data cache.
*/
extern void dcache_clean(void);
/**
* \brief Invalidate the data cache.
*/
extern void dcache_invalidate(void);
/**
* \brief Clean & Invalidate the data cache.
*/
extern void dcache_clean_invalidate(void);
/**
* \brief Invalidate the data cache within the specified region
* \param start virtual start address of region
* \param end virtual end address of region
*/
extern void dcache_invalidate_region(uint32_t start, uint32_t end);
/**
* \brief Clean the data cache within the specified region.
* \param start virtual start address of region
* \param end virtual end address of region
*/
extern void dcache_clean_region(uint32_t start, uint32_t end);
/**
* \brief Clean and invalidate the data cache within the specified region.
* \param start virtual start address of region
* \param end virtual end address of region
*/
extern void dcache_clean_invalidate_region(uint32_t start, uint32_t end);
/**
* \brief Enable exclusive caching for the L1 cache.
*
* The L2 cache must also be configured in exclusive mode.
*/
extern void dcache_set_exclusive(void);
/**
* \brief Allow data to reside in the L1 and L2 caches at the same time.
*/
extern void dcache_set_non_exclusive(void);
#endif /* CONFIG_HAVE_L1CACHE */
#endif /* L1CACHE_H_ */

55
arch/mutex.h Normal file
View File

@ -0,0 +1,55 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2015, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef MUTEX_H_
#define MUTEX_H_
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include <stdbool.h>
/*------------------------------------------------------------------------------
* Types
*------------------------------------------------------------------------------*/
/* Instances of mutex_t should be word-aligned (ALIGNED(4)) */
typedef volatile int mutex_t;
/*------------------------------------------------------------------------------
* Exported functions
*------------------------------------------------------------------------------*/
extern bool mutex_try_lock(mutex_t* mutex);
extern void mutex_lock(mutex_t* mutex);
extern void mutex_unlock(mutex_t* mutex);
extern bool mutex_is_locked(const mutex_t* mutex);
#endif /* MUTEX_H_ */

39
arch/swab.h Normal file
View File

@ -0,0 +1,39 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2016, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef SWAB_H_
#define SWAB_H_
#if defined(CONFIG_ARCH_ARM)
#include "arm/swab.h"
#else
#error Unsupported architecture!
#endif
#endif /* SWAB_H_ */

View File

@ -17,11 +17,11 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AT91SAM7S256.h"
#include "stdio.h"
#include "string.h"
#include "errors.h"
#include "hardware.h"
#include "irqflags.h"
#include "fat_compat.h"
#include "firmware.h"
@ -156,26 +156,19 @@ RAMFUNC void WriteFirmware(char *name)
}
size = f_size(&file) - sizeof(UPGRADE);
// All interrupts have to be disabled.
asm volatile ("mrs r12, CPSR; orr r12, r12, #0xC0; msr CPSR_c, r12"
: /* No outputs */
: /* No inputs */
: "r12", "cc");
arch_irq_disable();
// asm volatile ("mrs r12, CPSR; orr r12, r12, #0xC0; msr CPSR_c, r12"
// : /* No outputs */
// : /* No inputs */
// : "r12", "cc");
// Hack to foul FatFs to not handle a final partial sector (to avoid a memcpy)
file.obj.objsize = (file.obj.objsize + 511) & 0xfffffe00;
page = 0;
pDst = 0;
*AT91C_MC_FMR = 48 << 16 | FWS << 8; // MCLK cycles in 1us
for (i = 0; i < 16; i++)
if (*AT91C_MC_FSR & 1 << 16 + i)
{ // page is locked
while (!(*AT91C_MC_FSR & AT91C_MC_FRDY)); // wait for ready
*AT91C_MC_FCR = 0x5A << 24 | i << 6 + 8 | AT91C_MC_FCMD_UNLOCK; // unlock page
while (!(*AT91C_MC_FSR & AT91C_MC_FRDY)); // wait for ready
}
*AT91C_MC_FMR = 72 << 16 | FWS << 8; // MCLK cycles in 1.5us
UnlockFlash();
while (size)
{
@ -198,18 +191,18 @@ RAMFUNC void WriteFirmware(char *name)
// programming time: 13.2 ms per disk sector (512B)
pSrc = (unsigned long*)sector_buffer;
k = 2;
k = 512/FLASH_PAGESIZE;
while (k--)
{
if(size & 2048) DISKLED_ON
else DISKLED_OFF;
#ifndef GCC_OPTIMZES_TOO_MUCH // the latest gcc 4.8.0 calls memcpy for this
i = 256 / 4;
i = FLASH_PAGESIZE / 4;
while (i--)
*pDst++ = *pSrc++;
#else
i = 256 / 8;
i = FLASH_PAGESIZE / 8;
while (i--) {
*pDst++ = *pSrc++;
*pDst++ = *pSrc++;
@ -217,9 +210,7 @@ RAMFUNC void WriteFirmware(char *name)
#endif
while (!(*AT91C_MC_FSR & AT91C_MC_FRDY)); // wait for ready
*AT91C_MC_FCR = 0x5A << 24 | page << 8 | AT91C_MC_FCMD_START_PROG; // key: 0x5A
while (!(*AT91C_MC_FSR & AT91C_MC_FRDY)); // wait for ready
WriteFlash(page);
page++;
}
@ -227,7 +218,7 @@ RAMFUNC void WriteFirmware(char *name)
}
DISKLED_OFF;
*AT91C_RSTC_RCR = 0xA5 << 24 | AT91C_RSTC_PERRST | AT91C_RSTC_PROCRST; // restart
MCUReset(); // restart
for(;;);
}
#pragma section_no_code_init

View File

@ -15,9 +15,6 @@ typedef struct
unsigned long crc;
} UPGRADE;
#define true -1
#define false 0
unsigned long CalculateCRC32(unsigned long crc, unsigned char *pBuffer, unsigned long nSize);
unsigned char CheckFirmware(char *name);
void WriteFirmware(char *name) RAMFUNC;

41
fpga.c
View File

@ -22,10 +22,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// 2009-12-10 - changed command header id
// 2010-04-14 - changed command header id
#ifdef __GNUC__
#include "AT91SAM7S256.h"
#endif
#include "stdio.h"
#include "string.h"
#include "errors.h"
@ -39,6 +35,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "tos.h"
#include "mist_cfg.h"
uint8_t rstval = 0;
#define CMD_HDRID 0xAACA
// TODO!
@ -238,9 +236,10 @@ static inline void ShiftFpga(unsigned char data)
for ( i = 0; i < 8; i++ )
{
/* Dump to DATA0 and insert a positive edge pulse at the same time */
*AT91C_PIOA_CODR = ALTERA_DATA0 | ALTERA_DCLK;
if((data >> i) & 1) *AT91C_PIOA_SODR = ALTERA_DATA0;
*AT91C_PIOA_SODR = ALTERA_DCLK;
FPGA_DATA0_CODR = ALTERA_DATA0;
FPGA_CODR = ALTERA_DCLK;
if((data >> i) & 1) FPGA_DATA0_SODR = ALTERA_DATA0;
FPGA_SODR = ALTERA_DCLK;
}
}
@ -253,9 +252,8 @@ unsigned char ConfigureFpga(char *name)
UINT br;
// set outputs
*AT91C_PIOA_SODR = ALTERA_DCLK | ALTERA_DATA0 | ALTERA_NCONFIG;
// enable outputs
*AT91C_PIOA_OER = ALTERA_DCLK | ALTERA_DATA0 | ALTERA_NCONFIG;
FPGA_SODR = ALTERA_DCLK | ALTERA_NCONFIG;
FPGA_DATA0_SODR = ALTERA_DATA0;
if(!name)
name = "CORE.RBF";
@ -275,14 +273,14 @@ unsigned char ConfigureFpga(char *name)
/* Drive a transition of 0 to 1 to NCONFIG to indicate start of configuration */
for(i=0;i<10;i++)
*AT91C_PIOA_CODR = ALTERA_NCONFIG; // must be low for at least 500ns
FPGA_CODR = ALTERA_NCONFIG; // must be low for at least 500ns
*AT91C_PIOA_SODR = ALTERA_NCONFIG;
FPGA_SODR = ALTERA_NCONFIG;
// now wait for NSTATUS to go high
// specs: max 800us
i = 1000000;
while (!(*AT91C_PIOA_PDSR & ALTERA_NSTATUS))
while (!(FPGA_PDSR & ALTERA_NSTATUS))
{
if (--i == 0)
{
@ -328,7 +326,7 @@ unsigned char ConfigureFpga(char *name)
/* Check for error through NSTATUS for every 10KB programmed and the last byte */
if ( !(i % 10240) || (i == f_size(&file) - 1) ) {
if ( !*AT91C_PIOA_PDSR & ALTERA_NSTATUS ) {
if ( !FPGA_PDSR & ALTERA_NSTATUS ) {
iprintf("FPGA NSTATUS is NOT high!\r");
f_close(&file);
FatalError(5);
@ -343,7 +341,7 @@ unsigned char ConfigureFpga(char *name)
DISKLED_OFF;
// check if DONE is high
if (!(*AT91C_PIOA_PDSR & ALTERA_DONE)) {
if (!(FPGA_DONE_PDSR & ALTERA_DONE)) {
iprintf("FPGA Configuration done but contains error... CONF_DONE is LOW\r");
FatalError(5);
}
@ -361,17 +359,17 @@ unsigned char ConfigureFpga(char *name)
for ( i = 0; i < 50; i++ )
{
*AT91C_PIOA_CODR = ALTERA_DCLK;
*AT91C_PIOA_SODR = ALTERA_DCLK;
FPGA_CODR = ALTERA_DCLK;
FPGA_SODR = ALTERA_DCLK;
}
/* Initialization end */
if ( !(*AT91C_PIOA_PDSR & ALTERA_NSTATUS) ||
!(*AT91C_PIOA_PDSR & ALTERA_DONE)) {
if ( !(FPGA_PDSR & ALTERA_NSTATUS) ||
!(FPGA_DONE_PDSR & ALTERA_DONE)) {
iprintf("FPGA Initialization finish but contains error: NSTATUS is %s and CONF_DONE is %s.\r",
((*AT91C_PIOA_PDSR & ALTERA_NSTATUS)?"HIGH":"LOW"), ((*AT91C_PIOA_PDSR & ALTERA_DONE)?"HIGH":"LOW") );
((FPGA_PDSR & ALTERA_NSTATUS)?"HIGH":"LOW"), ((FPGA_DONE_PDSR & ALTERA_DONE)?"HIGH":"LOW") );
FatalError(5);
}
@ -935,6 +933,7 @@ void fpga_init(char *name) {
user_io_detect_core_type();
mist_ini_parse();
user_io_send_buttons(1);
InitDB9();
if((user_io_core_type() == CORE_TYPE_MINIMIG)||
(user_io_core_type() == CORE_TYPE_MINIMIG2)) {

6
fpga.h
View File

@ -15,5 +15,11 @@ void BootExit(void);
void ClearMemory(unsigned long base, unsigned long size);
unsigned char GetFPGAStatus(void);
// minimig reset stuff
#define SPI_RST_USR 0x1
#define SPI_RST_CPU 0x2
#define SPI_CPU_HLT 0x4
extern uint8_t rstval;
#endif

13
hdd.c
View File

@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdio.h>
#include <string.h>
#include "swab.h"
#include "errors.h"
#include "hardware.h"
#include "fat_compat.h"
@ -36,8 +37,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "debug.h"
#define SWAP(a) ((((a)&0x000000ff)<<24)|(((a)&0x0000ff00)<<8)|(((a)&0x00ff0000)>>8)|(((a)&0xff000000)>>24))
hardfileTYPE *hardfile[HARDFILES];
// hardfile structure
@ -116,10 +115,10 @@ static void FakeRDB(int unit,int block)
strcpy(rdb->rdb_DiskProduct, "repartition!");
// swap byte order of strings to be able to "unswap" them after checksum
unsigned long *p = (unsigned long*)rdb;
for(i=0;i<(8+16)/4;i++) p[40+i] = SWAP(p[40+i]);
for(i=0;i<(8+16)/4;i++) p[40+i] = swab32(p[40+i]);
RDBChecksum((unsigned long *)rdb);
// swap byte order of first 0x40 long values
for(i=0;i<0x40;i++) p[i] = SWAP(p[i]);
for(i=0;i<0x40;i++) p[i] = swab32(p[i]);
break;
}
case 1: {
@ -148,7 +147,7 @@ static void FakeRDB(int unit,int block)
RDBChecksum((unsigned long *)pb);
// swap byte order of first 0x40 entries
unsigned long *p = (unsigned long*)pb;
for(i=0;i<0x40;i++) p[i] = SWAP(p[i]);
for(i=0;i<0x40;i++) p[i] = swab32(p[i]);
break;
}
default: {
@ -411,10 +410,10 @@ static inline void ATA_ReadSectors(unsigned char* tfr, unsigned short sector, un
// adjust checksum by the difference between old and new flag value
struct RigidDiskBlock *rdb = (struct RigidDiskBlock *)sector_buffer;
rdb->rdb_ChkSum = SWAP(SWAP(rdb->rdb_ChkSum) + SWAP(rdb->rdb_Flags) - 0x12);
rdb->rdb_ChkSum = swab32(swab32(rdb->rdb_ChkSum) + swab32(rdb->rdb_Flags) - 0x12);
// adjust flags
rdb->rdb_Flags=SWAP(0x12);
rdb->rdb_Flags=swab32(0x12);
}
EnableFpga();
spi8(CMD_IDE_DATA_WR); // write data command

View File

@ -1,323 +1,460 @@
/*
Copyright 2008, 2009 Jakub Bednarski
This file is part of Minimig
Minimig 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 3 of the License, or
(at your option) any later version.
Minimig 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, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
#include "AT91SAM7S256.h"
#include "stdio.h"
#include "hardware.h"
#include "user_io.h"
#include "xmodem.h"
#include "ikbd.h"
uint8_t rstval = 0;
void __init_hardware(void)
{
*AT91C_WDTC_WDMR = AT91C_WDTC_WDDIS; // disable watchdog
*AT91C_RSTC_RMR = (0xA5 << 24) | AT91C_RSTC_URSTEN; // enable external user reset input
*AT91C_MC_FMR = FWS << 8; // Flash wait states
// configure clock generator
*AT91C_CKGR_MOR = AT91C_CKGR_MOSCEN | (40 << 8);
while (!(*AT91C_PMC_SR & AT91C_PMC_MOSCS));
*AT91C_CKGR_PLLR = AT91C_CKGR_OUT_0 | AT91C_CKGR_USBDIV_1 | (25 << 16) | (40 << 8) | 5; // DIV=5 MUL=26 USBDIV=1 (2) PLLCOUNT=40
while (!(*AT91C_PMC_SR & AT91C_PMC_LOCK));
*AT91C_PMC_MCKR = AT91C_PMC_PRES_CLK_2; // master clock register: clock source selection
while (!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY));
*AT91C_PMC_MCKR = AT91C_PMC_CSS_PLL_CLK | AT91C_PMC_PRES_CLK_2; // master clock register: clock source selection
while (!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY));
*AT91C_PIOA_PER = 0xFFFFFFFF; // enable pio on all pins
*AT91C_PIOA_SODR = DISKLED; // led off
#ifdef USB_PUP
// disable usb d+/d- pullups if present
*AT91C_PIOA_OER = USB_PUP;
*AT91C_PIOA_PPUDR = USB_PUP;
*AT91C_PIOA_SODR = USB_PUP;
#endif
// enable joystick ports
#ifdef JOY0
*AT91C_PIOA_PPUER = JOY0;
#endif
#ifdef JOY1
*AT91C_PIOA_PPUER = JOY1;
#endif
#ifdef SD_WP
// enable SD card signals
*AT91C_PIOA_PPUER = SD_WP | SD_CD;
#endif
*AT91C_PIOA_SODR = MMC_SEL | FPGA0 | FPGA1 | FPGA2; // set output data register
// output enable register
*AT91C_PIOA_OER = DISKLED | MMC_SEL | FPGA0 | FPGA1 | FPGA2;
// pull-up disable register
*AT91C_PIOA_PPUDR = DISKLED | MMC_SEL | FPGA0 | FPGA1 | FPGA2;
#ifdef XILINX_CCLK
// xilinx interface
*AT91C_PIOA_SODR = XILINX_CCLK | XILINX_DIN | XILINX_PROG_B;
*AT91C_PIOA_OER = XILINX_CCLK | XILINX_DIN | XILINX_PROG_B;
*AT91C_PIOA_PPUDR = XILINX_CCLK | XILINX_DIN | XILINX_PROG_B |
XILINX_INIT_B | XILINX_DONE;
#endif
#ifdef ALTERA_DCLK
// altera interface
*AT91C_PIOA_SODR = ALTERA_DCLK | ALTERA_DATA0 | ALTERA_NCONFIG;
*AT91C_PIOA_OER = ALTERA_DCLK | ALTERA_DATA0 | ALTERA_NCONFIG;
*AT91C_PIOA_PPUDR = ALTERA_DCLK | ALTERA_DATA0 | ALTERA_NCONFIG |
ALTERA_NSTATUS | ALTERA_DONE;
#endif
#ifdef MMC_CLKEN
// MMC_CLKEN may be present
// (but is not used anymore, so it's only setup passive)
*AT91C_PIOA_SODR = MMC_CLKEN;
*AT91C_PIOA_PPUDR = MMC_CLKEN;
#endif
#ifdef USB_SEL
*AT91C_PIOA_SODR = USB_SEL;
*AT91C_PIOA_OER = USB_SEL;
*AT91C_PIOA_PPUDR = USB_SEL;
#endif
// Enable peripheral clock in the PMC
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOA;
}
// A buffer of 256 bytes makes index handling pretty trivial
volatile static unsigned char tx_buf[256];
volatile static unsigned char tx_rptr, tx_wptr;
volatile static unsigned char rx_buf[256];
volatile static unsigned char rx_rptr, rx_wptr;
void Usart0IrqHandler(void) {
// Read USART status
unsigned char status = AT91C_BASE_US0->US_CSR;
// received something?
if(status & AT91C_US_RXRDY) {
// read byte from usart
unsigned char c = AT91C_BASE_US0->US_RHR;
// only store byte if rx buffer is not full
if((unsigned char)(rx_wptr + 1) != rx_rptr) {
// there's space in buffer: use it
rx_buf[rx_wptr++] = c;
}
}
// ready to transmit further bytes?
if(status & AT91C_US_TXRDY) {
// further bytes to send in buffer?
if(tx_wptr != tx_rptr)
// yes, simply send it and leave irq enabled
AT91C_BASE_US0->US_THR = tx_buf[tx_rptr++];
else
// nothing else to send, disable interrupt
AT91C_BASE_US0->US_IDR = AT91C_US_TXRDY;
}
}
// check usart rx buffer for data
void USART_Poll(void) {
if(user_io_dip_switch1())
xmodem_poll();
while(rx_wptr != rx_rptr) {
// this can a little be optimized by sending whole buffer parts
// at once and not just single bytes. But that's probably not
// worth the effort.
char chr = rx_buf[rx_rptr++];
if(user_io_dip_switch1()) {
// if in debug mode use xmodem for file reception
xmodem_rx_byte(chr);
} else {
iprintf("USART RX %d (%c)\n", chr, chr);
// data available -> send via user_io to core
user_io_serial_tx(&chr, 1);
}
}
}
void USART_Write(unsigned char c) {
#if 0
while(!(AT91C_BASE_US0->US_CSR & AT91C_US_TXRDY));
AT91C_BASE_US0->US_THR = c;
#else
if((AT91C_BASE_US0->US_CSR & AT91C_US_TXRDY) && (tx_wptr == tx_rptr)) {
// transmitter ready and buffer empty? -> send directly
AT91C_BASE_US0->US_THR = c;
} else {
// transmitter is not ready: block until space in buffer
while((unsigned char)(tx_wptr + 1) == tx_rptr);
// there's space in buffer: use it
tx_buf[tx_wptr++] = c;
}
AT91C_BASE_US0->US_IER = AT91C_US_TXRDY; // enable interrupt
#endif
}
void USART_Init(unsigned long baudrate) {
// Configure PA5 and PA6 for USART0 use
AT91C_BASE_PIOA->PIO_PDR = AT91C_PA5_RXD0 | AT91C_PA6_TXD0;
// Enable the peripheral clock in the PMC
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_US0;
// Reset and disable receiver & transmitter
AT91C_BASE_US0->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS;
// Configure USART0 mode
AT91C_BASE_US0->US_MR = AT91C_US_USMODE_NORMAL | AT91C_US_CLKS_CLOCK | AT91C_US_CHRL_8_BITS |
AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT | AT91C_US_CHMODE_NORMAL;
// Configure USART0 rate
AT91C_BASE_US0->US_BRGR = MCLK / 16 / baudrate;
// Enable receiver & transmitter
AT91C_BASE_US0->US_CR = AT91C_US_RXEN | AT91C_US_TXEN;
// tx buffer is initially empty
tx_rptr = tx_wptr = 0;
// and so is rx buffer
rx_rptr = rx_wptr = 0;
// Set the USART0 IRQ handler address in AIC Source
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_US0] = (unsigned int)Usart0IrqHandler;
AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_US0);
AT91C_BASE_US0->US_IER = AT91C_US_RXRDY; // enable rx interrupt
}
unsigned long CheckButton(void)
{
#ifdef BUTTON
return((~*AT91C_PIOA_PDSR) & BUTTON);
#else
return user_io_menu_button();
#endif
}
void timer0_c_irq_handler(void) {
//* Acknowledge interrupt status
unsigned int dummy = AT91C_BASE_TC0->TC_SR;
ikbd_update_time();
}
void Timer_Init(void) {
unsigned int dummy;
//* Open timer0
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_TC0;
//* Disable the clock and the interrupts
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS ;
AT91C_BASE_TC0->TC_IDR = 0xFFFFFFFF ;
//* Clear status bit
dummy = AT91C_BASE_TC0->TC_SR;
//* Set the Mode of the Timer Counter
AT91C_BASE_TC0->TC_CMR = 0x04; // :1024
//* Enable the clock
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN ;
//* Open Timer 0 interrupt
//* Disable the interrupt on the interrupt controller
AT91C_BASE_AIC->AIC_IDCR = 1 << AT91C_ID_TC0;
//* Save the interrupt handler routine pointer and the interrupt priority
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC0] = (unsigned int)timer0_c_irq_handler;
//* Store the Source Mode Register
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] = 1 | AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL;
//* Clear the interrupt on the interrupt controller
AT91C_BASE_AIC->AIC_ICCR = 1 << AT91C_ID_TC0;
AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS; // IRQ enable CPC
AT91C_BASE_AIC->AIC_IECR = 1 << AT91C_ID_TC0;
//* Start timer0
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG ;
*AT91C_PITC_PIMR = AT91C_PITC_PITEN | ((MCLK / 16 / 1000 - 1) & AT91C_PITC_PIV); // counting period 1ms
}
// 12 bits accuracy at 1ms = 4096 ms
unsigned long GetTimer(unsigned long offset)
{
unsigned long systimer = (*AT91C_PITC_PIIR & AT91C_PITC_PICNT);
systimer += offset << 20;
return (systimer); // valid bits [31:20]
}
unsigned long CheckTimer(unsigned long time)
{
unsigned long systimer = (*AT91C_PITC_PIIR & AT91C_PITC_PICNT);
time -= systimer;
return(time > (1UL << 31));
}
void WaitTimer(unsigned long time)
{
time = GetTimer(time);
while (!CheckTimer(time));
}
void TIMER_wait(unsigned long ms) {
WaitTimer(ms);
}
inline char mmc_inserted() {
return !(*AT91C_PIOA_PDSR & SD_CD);
}
char mmc_write_protected() {
return (*AT91C_PIOA_PDSR & SD_WP);
}
void MCUReset() {
*AT91C_RSTC_RCR = 0xA5 << 24 | AT91C_RSTC_PERRST | AT91C_RSTC_PROCRST | AT91C_RSTC_EXTRST;
}
void InitRTTC() {
// reprogram the realtime timer to run at 1Khz
AT91C_BASE_RTTC->RTTC_RTMR = 0x8000 / 1000;
}
/*
Copyright 2008, 2009 Jakub Bednarski
This file is part of Minimig
Minimig 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 3 of the License, or
(at your option) any later version.
Minimig 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, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
#include <stdio.h>
#include "AT91SAM7S256.h"
#include "attrs.h"
#include "hardware.h"
#include "user_io.h"
#include "xmodem.h"
#include "ikbd.h"
#include "usb.h"
#include "usbrtc.h"
void __init_hardware(void)
{
*AT91C_WDTC_WDMR = AT91C_WDTC_WDDIS; // disable watchdog
*AT91C_RSTC_RMR = (0xA5 << 24) | AT91C_RSTC_URSTEN; // enable external user reset input
*AT91C_MC_FMR = FWS << 8; // Flash wait states
// configure clock generator
*AT91C_CKGR_MOR = AT91C_CKGR_MOSCEN | (40 << 8);
while (!(*AT91C_PMC_SR & AT91C_PMC_MOSCS));
*AT91C_CKGR_PLLR = AT91C_CKGR_OUT_0 | AT91C_CKGR_USBDIV_1 | (25 << 16) | (40 << 8) | 5; // DIV=5 MUL=26 USBDIV=1 (2) PLLCOUNT=40
while (!(*AT91C_PMC_SR & AT91C_PMC_LOCK));
*AT91C_PMC_MCKR = AT91C_PMC_PRES_CLK_2; // master clock register: clock source selection
while (!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY));
*AT91C_PMC_MCKR = AT91C_PMC_CSS_PLL_CLK | AT91C_PMC_PRES_CLK_2; // master clock register: clock source selection
while (!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY));
*AT91C_PIOA_PER = 0xFFFFFFFF; // enable pio on all pins
*AT91C_PIOA_SODR = DISKLED; // led off
#ifdef USB_PUP
// disable usb d+/d- pullups if present
*AT91C_PIOA_OER = USB_PUP;
*AT91C_PIOA_PPUDR = USB_PUP;
*AT91C_PIOA_SODR = USB_PUP;
#endif
// enable joystick ports
#ifdef JOY0
*AT91C_PIOA_PPUER = JOY0;
#endif
#ifdef JOY1
*AT91C_PIOA_PPUER = JOY1;
#endif
#ifdef SD_WP
// enable SD card signals
*AT91C_PIOA_PPUER = SD_WP | SD_CD;
#endif
*AT91C_PIOA_SODR = MMC_SEL | FPGA0 | FPGA1 | FPGA2; // set output data register
// output enable register
*AT91C_PIOA_OER = DISKLED | MMC_SEL | FPGA0 | FPGA1 | FPGA2;
// pull-up disable register
*AT91C_PIOA_PPUDR = DISKLED | MMC_SEL | FPGA0 | FPGA1 | FPGA2;
#ifdef XILINX_CCLK
// xilinx interface
*AT91C_PIOA_SODR = XILINX_CCLK | XILINX_DIN | XILINX_PROG_B;
*AT91C_PIOA_OER = XILINX_CCLK | XILINX_DIN | XILINX_PROG_B;
*AT91C_PIOA_PPUDR = XILINX_CCLK | XILINX_DIN | XILINX_PROG_B |
XILINX_INIT_B | XILINX_DONE;
#endif
#ifdef ALTERA_DCLK
// altera interface
*AT91C_PIOA_SODR = ALTERA_DCLK | ALTERA_DATA0 | ALTERA_NCONFIG;
*AT91C_PIOA_OER = ALTERA_DCLK | ALTERA_DATA0 | ALTERA_NCONFIG;
*AT91C_PIOA_PPUDR = ALTERA_DCLK | ALTERA_DATA0 | ALTERA_NCONFIG |
ALTERA_NSTATUS | ALTERA_DONE;
#endif
#ifdef MMC_CLKEN
// MMC_CLKEN may be present
// (but is not used anymore, so it's only setup passive)
*AT91C_PIOA_SODR = MMC_CLKEN;
*AT91C_PIOA_PPUDR = MMC_CLKEN;
#endif
#ifdef USB_SEL
*AT91C_PIOA_SODR = USB_SEL;
*AT91C_PIOA_OER = USB_SEL;
*AT91C_PIOA_PPUDR = USB_SEL;
#endif
// Enable peripheral clock in the PMC
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOA;
}
// A buffer of 256 bytes makes index handling pretty trivial
volatile static unsigned char tx_buf[256];
volatile static unsigned char tx_rptr, tx_wptr;
volatile static unsigned char rx_buf[256];
volatile static unsigned char rx_rptr, rx_wptr;
void Usart0IrqHandler(void) {
// Read USART status
unsigned char status = AT91C_BASE_US0->US_CSR;
// received something?
if(status & AT91C_US_RXRDY) {
// read byte from usart
unsigned char c = AT91C_BASE_US0->US_RHR;
// only store byte if rx buffer is not full
if((unsigned char)(rx_wptr + 1) != rx_rptr) {
// there's space in buffer: use it
rx_buf[rx_wptr++] = c;
}
}
// ready to transmit further bytes?
if(status & AT91C_US_TXRDY) {
// further bytes to send in buffer?
if(tx_wptr != tx_rptr)
// yes, simply send it and leave irq enabled
AT91C_BASE_US0->US_THR = tx_buf[tx_rptr++];
else
// nothing else to send, disable interrupt
AT91C_BASE_US0->US_IDR = AT91C_US_TXRDY;
}
}
// check usart rx buffer for data
void USART_Poll(void) {
if(Buttons() & 2)
xmodem_poll();
while(rx_wptr != rx_rptr) {
// this can a little be optimized by sending whole buffer parts
// at once and not just single bytes. But that's probably not
// worth the effort.
char chr = rx_buf[rx_rptr++];
if(Buttons() & 2) {
// if in debug mode use xmodem for file reception
xmodem_rx_byte(chr);
} else {
iprintf("USART RX %d (%c)\n", chr, chr);
// data available -> send via user_io to core
user_io_serial_tx(&chr, 1);
}
}
}
void USART_Write(unsigned char c) {
#if 0
while(!(AT91C_BASE_US0->US_CSR & AT91C_US_TXRDY));
AT91C_BASE_US0->US_THR = c;
#else
if((AT91C_BASE_US0->US_CSR & AT91C_US_TXRDY) && (tx_wptr == tx_rptr)) {
// transmitter ready and buffer empty? -> send directly
AT91C_BASE_US0->US_THR = c;
} else {
// transmitter is not ready: block until space in buffer
while((unsigned char)(tx_wptr + 1) == tx_rptr);
// there's space in buffer: use it
tx_buf[tx_wptr++] = c;
}
AT91C_BASE_US0->US_IER = AT91C_US_TXRDY; // enable interrupt
#endif
}
void USART_Init(unsigned long baudrate) {
// Configure PA5 and PA6 for USART0 use
AT91C_BASE_PIOA->PIO_PDR = AT91C_PA5_RXD0 | AT91C_PA6_TXD0;
// Enable the peripheral clock in the PMC
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_US0;
// Reset and disable receiver & transmitter
AT91C_BASE_US0->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS;
// Configure USART0 mode
AT91C_BASE_US0->US_MR = AT91C_US_USMODE_NORMAL | AT91C_US_CLKS_CLOCK | AT91C_US_CHRL_8_BITS |
AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT | AT91C_US_CHMODE_NORMAL;
// Configure USART0 rate
AT91C_BASE_US0->US_BRGR = MCLK / 16 / baudrate;
// Enable receiver & transmitter
AT91C_BASE_US0->US_CR = AT91C_US_RXEN | AT91C_US_TXEN;
// tx buffer is initially empty
tx_rptr = tx_wptr = 0;
// and so is rx buffer
rx_rptr = rx_wptr = 0;
// Set the USART0 IRQ handler address in AIC Source
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_US0] = (unsigned int)Usart0IrqHandler;
AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_US0);
AT91C_BASE_US0->US_IER = AT91C_US_RXRDY; // enable rx interrupt
}
unsigned long CheckButton(void)
{
#ifdef BUTTON
return((~*AT91C_PIOA_PDSR) & BUTTON);
#else
return MenuButton();
#endif
}
void timer0_c_irq_handler(void) {
//* Acknowledge interrupt status
unsigned int dummy = AT91C_BASE_TC0->TC_SR;
ikbd_update_time();
}
void Timer_Init(void) {
unsigned int dummy;
//* Open timer0
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_TC0;
//* Disable the clock and the interrupts
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS ;
AT91C_BASE_TC0->TC_IDR = 0xFFFFFFFF ;
//* Clear status bit
dummy = AT91C_BASE_TC0->TC_SR;
//* Set the Mode of the Timer Counter
AT91C_BASE_TC0->TC_CMR = 0x04; // :1024
//* Enable the clock
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN ;
//* Open Timer 0 interrupt
//* Disable the interrupt on the interrupt controller
AT91C_BASE_AIC->AIC_IDCR = 1 << AT91C_ID_TC0;
//* Save the interrupt handler routine pointer and the interrupt priority
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC0] = (unsigned int)timer0_c_irq_handler;
//* Store the Source Mode Register
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] = 1 | AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL;
//* Clear the interrupt on the interrupt controller
AT91C_BASE_AIC->AIC_ICCR = 1 << AT91C_ID_TC0;
AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS; // IRQ enable CPC
AT91C_BASE_AIC->AIC_IECR = 1 << AT91C_ID_TC0;
//* Start timer0
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG ;
*AT91C_PITC_PIMR = AT91C_PITC_PITEN | ((MCLK / 16 / 1000 - 1) & AT91C_PITC_PIV); // counting period 1ms
}
// 12 bits accuracy at 1ms = 4096 ms
unsigned long GetTimer(unsigned long offset)
{
unsigned long systimer = (*AT91C_PITC_PIIR & AT91C_PITC_PICNT);
systimer += offset << 20;
return (systimer); // valid bits [31:20]
}
unsigned long CheckTimer(unsigned long time)
{
unsigned long systimer = (*AT91C_PITC_PIIR & AT91C_PITC_PICNT);
time -= systimer;
return(time > (1UL << 31));
}
void WaitTimer(unsigned long time)
{
time = GetTimer(time);
while (!CheckTimer(time));
}
void TIMER_wait(unsigned long ms) {
WaitTimer(ms);
}
inline char mmc_inserted() {
return !(*AT91C_PIOA_PDSR & SD_CD);
}
char mmc_write_protected() {
return (*AT91C_PIOA_PDSR & SD_WP);
}
void InitRTTC() {
// reprogram the realtime timer to run at 1Khz
AT91C_BASE_RTTC->RTTC_RTMR = 0x8000 / 1000;
}
int GetSPICLK() {
return (MCLK / ((AT91C_SPI_CSR[0] & AT91C_SPI_SCBR) >> 8) / 1000000);
}
// permanent state of adc inputs used for dip switches
static unsigned char adc_state = 0;
AT91PS_ADC a_pADC = AT91C_BASE_ADC;
AT91PS_PMC a_pPMC = AT91C_BASE_PMC;
static void PollOneADC() {
static unsigned char adc_cnt = 0xff;
// fetch result from previous run
if(adc_cnt != 0xff) {
unsigned int result;
// wait for end of convertion
while(!(AT91C_BASE_ADC->ADC_SR & (1 << (4+adc_cnt))));
switch (adc_cnt) {
case 0: result = AT91C_BASE_ADC->ADC_CDR4; break;
case 1: result = AT91C_BASE_ADC->ADC_CDR5; break;
case 2: result = AT91C_BASE_ADC->ADC_CDR6; break;
case 3: result = AT91C_BASE_ADC->ADC_CDR7; break;
}
if(result < 128) adc_state |= (1<<adc_cnt);
if(result > 128) adc_state &= ~(1<<adc_cnt);
}
adc_cnt = (adc_cnt + 1)&3;
// Enable desired chanel
AT91C_BASE_ADC->ADC_CHER = 1 << (4+adc_cnt);
// Start conversion
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
}
void InitADC(void) {
// Enable clock for interface
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_ADC;
// Reset
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
AT91C_BASE_ADC->ADC_CR = 0x0;
// Set maximum startup time and hold time
AT91C_BASE_ADC->ADC_MR = 0x0F1F0F00 | AT91C_ADC_LOWRES_8_BIT;
// make sure we get the first values immediately
PollOneADC();
PollOneADC();
PollOneADC();
PollOneADC();
}
// poll one adc channel every 25ms
void PollADC() {
static long adc_timer = 0;
if(CheckTimer(adc_timer)) {
adc_timer = GetTimer(25);
PollOneADC();
}
}
// user, menu, DIP1, DIP2
unsigned char Buttons() {
return (adc_state);
}
unsigned char MenuButton() {
return (adc_state & 4);
}
unsigned char UserButton() {
return (adc_state & 8);
}
void InitDB9() {}
// poll db9 joysticks
char GetDB9(char index, unsigned char *joy_map) {
static int joy0_state = JOY0;
static int joy1_state = JOY1;
if (!index) {
if((*AT91C_PIOA_PDSR & JOY0) != joy0_state) {
joy0_state = *AT91C_PIOA_PDSR & JOY0;
*joy_map = 0;
if(!(joy0_state & JOY0_UP)) *joy_map |= JOY_UP;
if(!(joy0_state & JOY0_DOWN)) *joy_map |= JOY_DOWN;
if(!(joy0_state & JOY0_LEFT)) *joy_map |= JOY_LEFT;
if(!(joy0_state & JOY0_RIGHT)) *joy_map |= JOY_RIGHT;
if(!(joy0_state & JOY0_BTN1)) *joy_map |= JOY_BTN1;
if(!(joy0_state & JOY0_BTN2)) *joy_map |= JOY_BTN2;
return 1;
} else
return 0;
} else {
if((*AT91C_PIOA_PDSR & JOY1) != joy1_state) {
joy1_state = *AT91C_PIOA_PDSR & JOY1;
*joy_map = 0;
if(!(joy1_state & JOY1_UP)) *joy_map |= JOY_UP;
if(!(joy1_state & JOY1_DOWN)) *joy_map |= JOY_DOWN;
if(!(joy1_state & JOY1_LEFT)) *joy_map |= JOY_LEFT;
if(!(joy1_state & JOY1_RIGHT)) *joy_map |= JOY_RIGHT;
if(!(joy1_state & JOY1_BTN1)) *joy_map |= JOY_BTN1;
if(!(joy1_state & JOY1_BTN2)) *joy_map |= JOY_BTN2;
return 1;
} else
return 0;
}
}
char GetRTC(unsigned char *d) {
return usb_rtc_get_time(d);
}
char SetRTC(unsigned char *d) {
return usb_rtc_set_time(d);
}
void RAMFUNC UnlockFlash() {
*AT91C_MC_FMR = 48 << 16 | FWS << 8; // MCLK cycles in 1us
for (int i = 0; i < 16; i++)
if (*AT91C_MC_FSR & 1 << 16 + i)
{ // page is locked
while (!(*AT91C_MC_FSR & AT91C_MC_FRDY)); // wait for ready
*AT91C_MC_FCR = 0x5A << 24 | i << 6 + 8 | AT91C_MC_FCMD_UNLOCK; // unlock page
while (!(*AT91C_MC_FSR & AT91C_MC_FRDY)); // wait for ready
}
*AT91C_MC_FMR = 72 << 16 | FWS << 8; // MCLK cycles in 1.5us
}
void RAMFUNC WriteFlash(int page) {
while (!(*AT91C_MC_FSR & AT91C_MC_FRDY)); // wait for ready
*AT91C_MC_FCR = 0x5A << 24 | page << 8 | AT91C_MC_FCMD_START_PROG; // key: 0x5A
while (!(*AT91C_MC_FSR & AT91C_MC_FRDY)); // wait for ready
}

View File

@ -1,102 +1,138 @@
#include "AT91SAM7S256.h"
#ifndef HARDWARE_H
#define HARDWARE_H
#include <inttypes.h>
#define MCLK 48000000
#define FWS 1 // Flash wait states
#define DISKLED AT91C_PIO_PA29
#define DISKLED_ON *AT91C_PIOA_CODR = DISKLED;
#define DISKLED_OFF *AT91C_PIOA_SODR = DISKLED;
#define MMC_SEL AT91C_PIO_PA31
#define USB_SEL AT91C_PIO_PA11
#define USB_PUP AT91C_PIO_PA16
#define SD_WP AT91C_PIO_PA1
#define SD_CD AT91C_PIO_PA0
#ifdef EMIST
// xilinx programming interface
#define XILINX_DONE AT91C_PIO_PA4
#define XILINX_DIN AT91C_PIO_PA9
#define XILINX_INIT_B AT91C_PIO_PA8
#define XILINX_PROG_B AT91C_PIO_PA7
#define XILINX_CCLK AT91C_PIO_PA15
#else
// altera programming interface
#define ALTERA_DONE AT91C_PIO_PA4
#define ALTERA_DATA0 AT91C_PIO_PA9
#define ALTERA_NCONFIG AT91C_PIO_PA8
#define ALTERA_NSTATUS AT91C_PIO_PA7
#define ALTERA_DCLK AT91C_PIO_PA15
#endif
// db9 joystick ports
#define JOY1_UP AT91C_PIO_PA28
#define JOY1_DOWN AT91C_PIO_PA27
#define JOY1_LEFT AT91C_PIO_PA26
#define JOY1_RIGHT AT91C_PIO_PA25
#define JOY1_BTN1 AT91C_PIO_PA24
#define JOY1_BTN2 AT91C_PIO_PA23
#define JOY1 (JOY1_UP|JOY1_DOWN|JOY1_LEFT|JOY1_RIGHT|JOY1_BTN1|JOY1_BTN2)
#define JOY0_UP AT91C_PIO_PA22
#define JOY0_DOWN AT91C_PIO_PA21
#define JOY0_LEFT AT91C_PIO_PA20
#define JOY0_RIGHT AT91C_PIO_PA19
#define JOY0_BTN1 AT91C_PIO_PA18
#define JOY0_BTN2 AT91C_PIO_PA17
#define JOY0 (JOY0_UP|JOY0_DOWN|JOY0_LEFT|JOY0_RIGHT|JOY0_BTN1|JOY0_BTN2)
// chip selects for FPGA communication
#define FPGA0 AT91C_PIO_PA10
#define FPGA1 AT91C_PIO_PA3
#define FPGA2 AT91C_PIO_PA2
#define FPGA3 AT91C_PIO_PA9 // same as ALTERA_DATA0
#define VBL AT91C_PIO_PA7
char mmc_inserted(void);
void USART_Init(unsigned long baudrate);
void USART_Write(unsigned char c);
unsigned char USART_Read(void);
unsigned long CheckButton(void);
void Timer_Init(void);
unsigned long GetTimer(unsigned long offset);
unsigned long CheckTimer(unsigned long t);
void WaitTimer(unsigned long time);
void TIMER_wait(unsigned long ms);
void USART_Poll(void);
void MCUReset();
void InitRTTC();
int inline GetRTTC() {return (int)(AT91C_BASE_RTTC->RTTC_RTVR);}
#ifdef FPGA3
// the MiST has the user inout on the arm controller
void EnableIO(void);
void DisableIO(void);
#endif
#define DEBUG_FUNC_IN()
#define DEBUG_FUNC_OUT()
#ifdef __GNUC__
void __init_hardware(void);
#endif
// minimig reset stuff
#define SPI_RST_USR 0x1
#define SPI_RST_CPU 0x2
#define SPI_CPU_HLT 0x4
extern uint8_t rstval;
#endif // HARDWARE_H
#include "AT91SAM7S256.h"
#ifndef HARDWARE_H
#define HARDWARE_H
#include <inttypes.h>
#define MCLK 48000000
#define FWS 1 // Flash wait states
#define FLASH_PAGESIZE 256
#define DISKLED AT91C_PIO_PA29
#define DISKLED_ON *AT91C_PIOA_CODR = DISKLED;
#define DISKLED_OFF *AT91C_PIOA_SODR = DISKLED;
#define MMC_SEL AT91C_PIO_PA31
#define USB_SEL AT91C_PIO_PA11
#define USB_PUP AT91C_PIO_PA16
#define SD_WP AT91C_PIO_PA1
#define SD_CD AT91C_PIO_PA0
// fpga programming interface
#define FPGA_OER *AT91C_PIOA_OER
#define FPGA_SODR *AT91C_PIOA_SODR
#define FPGA_CODR *AT91C_PIOA_CODR
#define FPGA_PDSR *AT91C_PIOA_PDSR
#define FPGA_DONE_PDSR FPGA_PDSR
#define FPGA_DATA0_CODR FPGA_CODR
#define FPGA_DATA0_SODR FPGA_SODR
#ifdef EMIST
// xilinx programming interface
#define XILINX_DONE AT91C_PIO_PA4
#define XILINX_DIN AT91C_PIO_PA9
#define XILINX_INIT_B AT91C_PIO_PA8
#define XILINX_PROG_B AT91C_PIO_PA7
#define XILINX_CCLK AT91C_PIO_PA15
#else
// altera programming interface
#define ALTERA_DONE AT91C_PIO_PA4
#define ALTERA_DATA0 AT91C_PIO_PA9
#define ALTERA_NCONFIG AT91C_PIO_PA8
#define ALTERA_NSTATUS AT91C_PIO_PA7
#define ALTERA_DCLK AT91C_PIO_PA15
#endif
// db9 joystick ports
#define JOY1_UP AT91C_PIO_PA28
#define JOY1_DOWN AT91C_PIO_PA27
#define JOY1_LEFT AT91C_PIO_PA26
#define JOY1_RIGHT AT91C_PIO_PA25
#define JOY1_BTN1 AT91C_PIO_PA24
#define JOY1_BTN2 AT91C_PIO_PA23
#define JOY1 (JOY1_UP|JOY1_DOWN|JOY1_LEFT|JOY1_RIGHT|JOY1_BTN1|JOY1_BTN2)
#define JOY0_UP AT91C_PIO_PA22
#define JOY0_DOWN AT91C_PIO_PA21
#define JOY0_LEFT AT91C_PIO_PA20
#define JOY0_RIGHT AT91C_PIO_PA19
#define JOY0_BTN1 AT91C_PIO_PA18
#define JOY0_BTN2 AT91C_PIO_PA17
#define JOY0 (JOY0_UP|JOY0_DOWN|JOY0_LEFT|JOY0_RIGHT|JOY0_BTN1|JOY0_BTN2)
// chip selects for FPGA communication
#define FPGA0 AT91C_PIO_PA10
#define FPGA1 AT91C_PIO_PA3
#define FPGA2 AT91C_PIO_PA2
#define FPGA3 AT91C_PIO_PA9 // same as ALTERA_DATA0
#define VBL AT91C_PIO_PA7
#define USB_LOAD_VAR *(int*)(0x0020FF04)
#define USB_LOAD_VALUE 12345678
#define DEBUG_MODE_VAR *(int*)(0x0020FF08)
#define DEBUG_MODE_VALUE 87654321
#define DEBUG_MODE (DEBUG_MODE_VAR == DEBUG_MODE_VALUE)
#define VIDEO_KEEP_VALUE 0x87654321
#define VIDEO_KEEP_VAR (*(int*)0x0020FF10)
#define VIDEO_ALTERED_VAR (*(uint8_t*)0x0020FF14)
#define VIDEO_SD_DISABLE_VAR (*(uint8_t*)0x0020FF15)
#define VIDEO_YPBPR_VAR (*(uint8_t*)0x0020FF16)
char mmc_inserted(void);
void USART_Init(unsigned long baudrate);
void USART_Write(unsigned char c);
unsigned char USART_Read(void);
unsigned long CheckButton(void);
void Timer_Init(void);
unsigned long GetTimer(unsigned long offset);
unsigned long CheckTimer(unsigned long t);
void WaitTimer(unsigned long time);
void TIMER_wait(unsigned long ms);
void USART_Poll(void);
void inline MCUReset() {*AT91C_RSTC_RCR = 0xA5 << 24 | AT91C_RSTC_PERRST | AT91C_RSTC_PROCRST | AT91C_RSTC_EXTRST;}
void InitRTTC();
int inline GetRTTC() {return (int)(AT91C_BASE_RTTC->RTTC_RTVR);}
int GetSPICLK();
void InitADC(void);
void PollADC();
// user, menu, DIP2, DIP1
unsigned char Buttons();
unsigned char MenuButton();
unsigned char UserButton();
void InitDB9();
char GetDB9(char index, unsigned char *joy_map);
char GetRTC(unsigned char *d);
char SetRTC(unsigned char *d);
void UnlockFlash();
void WriteFlash(int page);
#ifdef FPGA3
// the MiST has the user inout on the arm controller
void EnableIO(void);
void DisableIO(void);
#endif
#define DEBUG_FUNC_IN()
#define DEBUG_FUNC_OUT()
#ifdef __GNUC__
void __init_hardware(void);
#endif
#endif // HARDWARE_H

View File

@ -38,7 +38,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "spi.h"
#include "mmc.h"
#include "fat_compat.h"
// variables
static unsigned char crc;

View File

@ -1,5 +1,6 @@
#include <stdio.h>
#include "idxfile.h"
#include "hardware.h"
IDXFile sd_image[SD_IMAGES];

6
ikbd.c
View File

@ -31,7 +31,7 @@
#include "spi.h"
#include "ikbd.h"
#include "debug.h"
#include "usb.h"
#include "hardware.h"
#include "utils.h"
#define IKBD_AUTO_MS 20
@ -272,7 +272,7 @@ void ikbd_handler_time_set(void) {
DisableIO();
// try to set time on rtc if present
usb_rtc_set_time(ikbd.date);
SetRTC(ikbd.date);
spi_uio_cmd_cont(UIO_IKBD_IN);
@ -289,7 +289,7 @@ void ikbd_handler_interrogate_time(void) {
DisableIO();
// try to fetch time from rtc if present
usb_rtc_get_time(ikbd.date);
GetRTC(ikbd.date);
spi_uio_cmd_cont(UIO_IKBD_IN);

4
main.c
View File

@ -107,7 +107,6 @@ extern void inserttestfloppy();
int main(void)
{
uint8_t tmp;
uint8_t mmc_ok = 0;
#ifdef __GNUC__
@ -135,8 +134,7 @@ int main(void)
// TODO: If MMC fails try to wait for USB storage
tmp = MCLK / ((AT91C_SPI_CSR[0] & AT91C_SPI_SCBR) >> 8) / 1000000;
iprintf("spiclk: %u MHz\r", tmp);
iprintf("spiclk: %u MHz\r", GetSPICLK());
usb_init();

6
tos.c
View File

@ -326,6 +326,7 @@ static void handle_acsi(unsigned char *buffer) {
if(lba+length <= blocks) {
DISKLED_ON;
#ifndef SD_NO_DIRECT_MODE
if (user_io_core_type() == CORE_TYPE_MIST2) {
// SD-Card -> FPGA direct SPI transfer on MIST2
if(hdd_direct && target == 0) {
@ -337,6 +338,7 @@ static void handle_acsi(unsigned char *buffer) {
FileReadBlockEx(&sd_image[target+2].file, 0, length);
}
} else {
#endif
while(length) {
if(hdd_direct && target == 0) {
if(user_io_dip_switch1())
@ -351,7 +353,9 @@ static void handle_acsi(unsigned char *buffer) {
mist_memory_write_block(sector_buffer);
length--;
}
#ifndef SD_NO_DIRECT_MODE
}
#endif
DISKLED_OFF;
dma_ack(0x00);
asc[target] = 0x00;
@ -1071,7 +1075,7 @@ void tos_poll() {
mist_get_dmastate();
// check the user button
if(user_io_user_button()) {
if(!MenuButton() && UserButton()) {
if(timer == 1)
timer = GetTimer(1000);
else if(timer != 2)

View File

@ -8,9 +8,9 @@
#include "hidparser.h"
#include "debug.h"
#include "joymapping.h"
#include "hardware.h"
#include "../utils.h"
#include "../user_io.h"
#include "../hardware.h"
#include "../mist_cfg.h"
#include "../osd.h"
#include "../state.h"

151
user_io.c
View File

@ -1,4 +1,3 @@
#include "AT91SAM7S256.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -57,11 +56,6 @@ extern char rom_direct_upload;
// core variant (mostly for arcades)
static char core_mod = 0;
// permanent state of adc inputs used for dip switches
static unsigned char adc_state = 0;
AT91PS_ADC a_pADC = AT91C_BASE_ADC;
AT91PS_PMC a_pPMC = AT91C_BASE_PMC;
// keep state of caps lock
static char caps_lock_toggle = 0;
@ -87,12 +81,6 @@ bool scrl_status = 0;
#define RTC_FREQ 1000 // 1 s
static unsigned long rtc_timer;
#define VIDEO_KEEP_VALUE 0x87654321
#define video_keep (*(int*)0x0020FF10)
#define video_altered (*(uint8_t*)0x0020FF14)
#define video_sd_disable (*(uint8_t*)0x0020FF15)
#define video_ypbpr (*(uint8_t*)0x0020FF16)
static unsigned char modifier = 0, pressed[6] = { 0,0,0,0,0,0 };
static unsigned char ps2_typematic_rate = 0x80;
@ -117,64 +105,6 @@ char user_io_osd_is_visible() {
return osd_is_visible;
}
static void PollOneAdc() {
static unsigned char adc_cnt = 0xff;
// fetch result from previous run
if(adc_cnt != 0xff) {
unsigned int result;
// wait for end of convertion
while(!(AT91C_BASE_ADC->ADC_SR & (1 << (4+adc_cnt))));
switch (adc_cnt) {
case 0: result = AT91C_BASE_ADC->ADC_CDR4; break;
case 1: result = AT91C_BASE_ADC->ADC_CDR5; break;
case 2: result = AT91C_BASE_ADC->ADC_CDR6; break;
case 3: result = AT91C_BASE_ADC->ADC_CDR7; break;
}
if(result < 128) adc_state |= (1<<adc_cnt);
if(result > 128) adc_state &= ~(1<<adc_cnt);
}
adc_cnt = (adc_cnt + 1)&3;
// Enable desired chanel
AT91C_BASE_ADC->ADC_CHER = 1 << (4+adc_cnt);
// Start conversion
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
}
static void InitADC(void) {
// Enable clock for interface
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_ADC;
// Reset
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
AT91C_BASE_ADC->ADC_CR = 0x0;
// Set maximum startup time and hold time
AT91C_BASE_ADC->ADC_MR = 0x0F1F0F00 | AT91C_ADC_LOWRES_8_BIT;
// make sure we get the first values immediately
PollOneAdc();
PollOneAdc();
PollOneAdc();
PollOneAdc();
}
// poll one adc channel every 25ms
static void PollAdc() {
static long adc_timer = 0;
if(CheckTimer(adc_timer)) {
adc_timer = GetTimer(25);
PollOneAdc();
}
}
void user_io_reset() {
// no sd card image selected, SD card accesses will go directly
// to the card (first slot, and only until the first unmount)
@ -198,15 +128,15 @@ void user_io_init() {
user_io_reset();
if(video_keep != VIDEO_KEEP_VALUE) video_altered = 0;
video_keep = 0;
if(VIDEO_KEEP_VAR != VIDEO_KEEP_VALUE) VIDEO_ALTERED_VAR = 0;
VIDEO_KEEP_VAR = 0;
// mark remap table as unused
memset(key_remap_table, 0, sizeof(key_remap_table));
InitADC();
if(user_io_menu_button()) DEBUG_MODE_VAR = DEBUG_MODE ? 0 : DEBUG_MODE_VALUE;
if(MenuButton()) DEBUG_MODE_VAR = DEBUG_MODE ? 0 : DEBUG_MODE_VALUE;
iprintf("debug_mode = %d\n", DEBUG_MODE);
ikbd_init();
@ -275,7 +205,7 @@ void user_io_send_rtc(void) {
uint8_t date[7]; //year,month,date,hour,min,sec,day
uint8_t i;
if (usb_rtc_get_time((uint8_t*)&date)) {
if (GetRTC((uint8_t*)&date)) {
//iprintf("Sending time of day %u:%02u:%02u %u.%u.%u\n",
// date[3], date[4], date[5], date[2], date[1], 1900 + date[0]);
spi_uio_cmd_cont(UIO_SET_RTC);
@ -297,7 +227,11 @@ void user_io_detect_core_type() {
EnableIO();
core_type = SPI(0xff);
DisableIO();
#ifdef SD_NO_DIRECT_MODE
rom_direct_upload = 0;
#else
rom_direct_upload = (core_type & 0x10) >> 4; // bit 4 - direct upload support
#endif
core_type &= 0xef;
if((core_type != CORE_TYPE_DUMB) &&
@ -874,30 +808,30 @@ void user_io_send_buttons(char force) {
// frequently poll the adc the switches
// and buttons are connected to
PollAdc();
PollADC();
unsigned char map = 0;
if(adc_state & 1) map |= SWITCH2;
if(adc_state & 2) map |= SWITCH1;
if(Buttons() & 1) map |= SWITCH2;
if(Buttons() & 2) map |= SWITCH1;
if(adc_state & 4) map |= BUTTON1;
else if(adc_state & 8) map |= BUTTON2;
if(Buttons() & 4) map |= BUTTON1;
else if(Buttons() & 8) map |= BUTTON2;
if(kbd_reset) map |= BUTTON2;
if(!mist_cfg.keep_video_mode) video_altered = 0;
if(!mist_cfg.keep_video_mode) VIDEO_ALTERED_VAR = 0;
if(video_altered & 1)
if(VIDEO_ALTERED_VAR & 1)
{
if(video_sd_disable) map |= CONF_SCANDOUBLER_DISABLE;
if(VIDEO_SD_DISABLE_VAR) map |= CONF_SCANDOUBLER_DISABLE;
}
else
{
if(mist_cfg.scandoubler_disable) map |= CONF_SCANDOUBLER_DISABLE;
}
if(video_altered & 2)
if(VIDEO_ALTERED_VAR & 2)
{
if(video_ypbpr) map |= CONF_YPBPR;
if(VIDEO_YPBPR_VAR) map |= CONF_YPBPR;
}
else
{
@ -1207,17 +1141,9 @@ void user_io_poll() {
}
// poll db9 joysticks
static int joy0_state = JOY0;
if((*AT91C_PIOA_PDSR & JOY0) != joy0_state) {
joy0_state = *AT91C_PIOA_PDSR & JOY0;
unsigned char joy_map = 0;
unsigned char joy_map = 0;
if(!(joy0_state & JOY0_UP)) joy_map |= JOY_UP;
if(!(joy0_state & JOY0_DOWN)) joy_map |= JOY_DOWN;
if(!(joy0_state & JOY0_LEFT)) joy_map |= JOY_LEFT;
if(!(joy0_state & JOY0_RIGHT)) joy_map |= JOY_RIGHT;
if(!(joy0_state & JOY0_BTN1)) joy_map |= JOY_BTN1;
if(!(joy0_state & JOY0_BTN2)) joy_map |= JOY_BTN2;
if(GetDB9(0, &joy_map)) {
joy_map = virtual_joystick_mapping(0x00db, 0x0000, joy_map);
@ -1226,18 +1152,7 @@ void user_io_poll() {
StateJoySet(joy_map, mist_cfg.joystick_db9_fixed_index ? idx : hid_get_joysticks()); // send to OSD
virtual_joystick_keyboard(joy_map);
}
static int joy1_state = JOY1;
if((*AT91C_PIOA_PDSR & JOY1) != joy1_state) {
joy1_state = *AT91C_PIOA_PDSR & JOY1;
unsigned char joy_map = 0;
if(!(joy1_state & JOY1_UP)) joy_map |= JOY_UP;
if(!(joy1_state & JOY1_DOWN)) joy_map |= JOY_DOWN;
if(!(joy1_state & JOY1_LEFT)) joy_map |= JOY_LEFT;
if(!(joy1_state & JOY1_RIGHT)) joy_map |= JOY_RIGHT;
if(!(joy1_state & JOY1_BTN1)) joy_map |= JOY_BTN1;
if(!(joy1_state & JOY1_BTN2)) joy_map |= JOY_BTN2;
if(GetDB9(1, &joy_map)) {
joy_map = virtual_joystick_mapping(0x00db, 0x0001, joy_map);
@ -1662,7 +1577,7 @@ void user_io_poll() {
// and toggle scandoubler on/off then
static unsigned long timer = 1;
static unsigned char ypbpr_toggle = 0;
if(user_io_menu_button())
if(MenuButton())
{
if(timer == 1)
timer = GetTimer(1000);
@ -1676,12 +1591,12 @@ void user_io_poll() {
user_io_send_buttons(1);
OsdDisableMenuButton(1);
video_altered |= 1;
video_sd_disable = mist_cfg.scandoubler_disable;
VIDEO_ALTERED_VAR |= 1;
VIDEO_SD_DISABLE_VAR = mist_cfg.scandoubler_disable;
}
}
if(adc_state & 8)
if(UserButton())
{
if(!ypbpr_toggle)
{
@ -1692,8 +1607,8 @@ void user_io_poll() {
user_io_send_buttons(1);
OsdDisableMenuButton(1);
video_altered |= 2;
video_ypbpr = mist_cfg.ypbpr;
VIDEO_ALTERED_VAR |= 2;
VIDEO_YPBPR_VAR = mist_cfg.ypbpr;
}
}
else
@ -1711,15 +1626,7 @@ void user_io_poll() {
}
char user_io_dip_switch1() {
return(((adc_state & 2)?1:0) || DEBUG_MODE);
}
char user_io_menu_button() {
return((adc_state & 4)?1:0);
}
char user_io_user_button() {
return((!user_io_menu_button() && (adc_state & 8))?1:0);
return(((Buttons() & 2)?1:0) || DEBUG_MODE);
}
static void send_keycode(unsigned short code) {
@ -1887,7 +1794,7 @@ static void check_reset(unsigned short modifiers, char useKeys)
{
if(modifiers & 2) // with lshift - MiST reset
{
if(mist_cfg.keep_video_mode) video_keep = VIDEO_KEEP_VALUE;
if(mist_cfg.keep_video_mode) VIDEO_KEEP_VAR = VIDEO_KEEP_VALUE;
MCUReset(); // HW reset
for(;;);
}

View File

@ -168,9 +168,6 @@ char minimig_v1();
char minimig_v2();
char user_io_is_8bit_with_config_string();
void user_io_poll();
char user_io_menu_button();
char user_io_button_dip_switch1();
char user_io_user_button();
void user_io_osd_key_enable(char);
void user_io_serial_tx(char *, uint16_t);
char *user_io_8bit_get_string(char);
@ -211,13 +208,4 @@ unsigned char user_io_ext_idx(const char*, const char*);
void user_io_change_into_core_dir(void);
#define USB_LOAD_VAR *(int*)(0x0020FF04)
#define USB_LOAD_VAR *(int*)(0x0020FF04)
#define USB_LOAD_VALUE 12345678
#define DEBUG_MODE_VAR *(int*)(0x0020FF08)
#define DEBUG_MODE_VALUE 87654321
#define DEBUG_MODE (DEBUG_MODE_VAR == DEBUG_MODE_VALUE)
#endif // USER_IO_H