oehansens i2c and spi extensions

This commit is contained in:
Markus Fröschle
2013-04-15 06:19:00 +00:00
parent e99525ceee
commit efd01c2fa3
81 changed files with 48740 additions and 0 deletions

View File

@@ -0,0 +1,309 @@
/*
* BaS
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2010 - 2012 F. Aschwanden
* Copyright 2011 - 2012 V. Riviere
* Copyright 2012 M. Froeschle
*/
#include <stdint.h>
#include <stdbool.h>
#include "MCF5475.h"
#include "MCF5475_SLT.h"
#include "startcf.h"
#include "cache.h"
#include "bas_printf.h"
#include "bas_types.h"
#include "sd_card.h"
#include "wait.h"
#include "diskio.h"
#include "ff.h"
#include "s19reader.h"
/* imported routines */
extern int mmu_init();
extern int vec_init();
/* Symbols from the linker script */
extern uint8_t _STRAM_END[];
#define STRAM_END ((uint32_t)_STRAM_END)
extern uint8_t _TOS[];
#define TOS ((uint32_t)_TOS) /* final TOS location */
extern uint8_t _FASTRAM_END[];
#define FASTRAM_END ((uint32_t)_FASTRAM_END)
extern uint8_t _EMUTOS[];
#define EMUTOS ((uint32_t)_EMUTOS) /* where EmuTOS is stored in flash */
extern uint8_t _EMUTOS_SIZE[];
#define EMUTOS_SIZE ((uint32_t)_EMUTOS_SIZE) /* size of EmuTOS, in bytes */
/*
* check if it is possible to transfer data to PIC
*/
static inline bool pic_txready(void)
{
if (MCF_PSC3_PSCSR & MCF_PSC_PSCSR_TXRDY)
return true;
return true;
}
/*
* check if it is possible to receive data from PIC
*/
static inline bool pic_rxready(void)
{
if (MCF_PSC3_PSCSR & MCF_PSC_PSCSR_RXRDY)
return true;
return false;
}
void write_pic_byte(uint8_t value)
{
/* Wait until the transmitter is ready or 1000us are passed */
waitfor(1000, pic_txready);
/* Transmit the byte */
*(volatile uint8_t*)(&MCF_PSC3_PSCTB_8BIT) = value; // Really 8-bit
}
uint8_t read_pic_byte(void)
{
/* Wait until a byte has been received or 1000us are passed */
waitfor(1000, pic_rxready);
/* Return the received byte */
return *(volatile uint8_t*)(&MCF_PSC3_PSCTB_8BIT); // Really 8-bit
}
void pic_init(void)
{
char answer[4] = "OLD";
xprintf("initialize the PIC: ");
/* Send the PIC initialization string */
write_pic_byte('A');
write_pic_byte('C');
write_pic_byte('P');
write_pic_byte('F');
/* Read the 3-char answer string. Should be "OK!". */
answer[0] = read_pic_byte();
answer[1] = read_pic_byte();
answer[2] = read_pic_byte();
answer[3] = '\0';
if (answer[0] != 'O' || answer[1] != 'K' || answer[2] != '!')
{
xprintf("PIC initialization failed. Already initialized?\r\n");
}
else
{
xprintf("%s\r\n", answer);
}
}
void nvram_init(void)
{
int i;
xprintf("Restore the NVRAM data: ");
/* Request for NVRAM backup data */
write_pic_byte(0x01);
/* Check answer type */
if (read_pic_byte() != 0x81)
{
// FIXME: PIC protocol error
xprintf("FAILED\r\n");
return;
}
/* Restore the NVRAM backup to the FPGA */
for (i = 0; i < 64; i++)
{
uint8_t data = read_pic_byte();
*(volatile uint8_t*)0xffff8961 = i;
*(volatile uint8_t*)0xffff8963 = data;
}
xprintf("finished\r\n");
}
void enable_coldfire_interrupts()
{
xprintf("enable interrupts: ");
* (volatile uint32_t *) 0xf0010004 = 0L; /* disable all interrupts */
MCF_EPORT_EPPAR = 0xaaa8; /* all interrupts on falling edge */
MCF_GPT0_GMS = MCF_GPT_GMS_ICT(1) | /* timer 0 on, video change capture on rising edge */
MCF_GPT_GMS_IEN |
MCF_GPT_GMS_TMS(1);
MCF_INTC_ICR62 = 0x3f;
* (volatile uint8_t *) 0xf0010004 = 0xfe; /* enable int 1-7 */
MCF_EPORT_EPIER = 0xfe; /* int 1-7 on */
MCF_EPORT_EPFR = 0xff; /* clear all pending interrupts */
MCF_INTC_IMRL = 0xffffff00; /* int 1-7 on */
MCF_INTC_IMRH = 0xbffffffe; /* psc3 and timer 0 int on */
xprintf("finished\r\n");
}
void disable_coldfire_interrupts()
{
* (volatile uint32_t *) 0xf0010004 = 0L; /* disable all interrupts */
}
void BaS(void)
{
uint8_t *src;
uint8_t *dst = (uint8_t *)TOS;
uint32_t *adr;
pic_init();
nvram_init();
xprintf("copy EmuTOS: ");
/* copy EMUTOS */
src = (uint8_t *) EMUTOS;
while (src < (uint8_t *)(EMUTOS + EMUTOS_SIZE))
{
*dst++ = *src++;
}
xprintf("finished\r\n");
/* we have copied a code area, so flush the caches */
flush_and_invalidate_caches();
xprintf("initialize MMU: ");
mmu_init();
xprintf("finished\r\n");
xprintf("initialize exception vector table: ");
vec_init();
xprintf("finished\r\n");
MCF_MMU_MMUCR = MCF_MMU_MMUCR_EN; /* MMU on */
xprintf("IDE reset: ");
/* IDE reset */
* (volatile uint8_t *) (0xffff8802 - 2) = 14;
* (volatile uint8_t *) (0xffff8802 - 0) = 0x80;
wait(1);
* (volatile uint8_t *) (0xffff8802 - 0) = 0;
xprintf("finished\r\n");
xprintf("enable video: ");
/*
* video setup (25MHz)
*/
* (volatile uint32_t *) (0xf0000410 + 0) = 0x032002ba; /* horizontal 640x480 */
* (volatile uint32_t *) (0xf0000410 + 4) = 0x020c020a; /* vertical 640x480 */
* (volatile uint32_t *) (0xf0000410 + 8) = 0x0190015d; /* horizontal 320x240 */
* (volatile uint32_t *) (0xf0000410 + 12) = 0x020C020A; /* vertical 320x230 */
#ifdef _NOT_USED_
// 32MHz
move.l #0x037002ba,(a0)+ // horizontal 640x480
move.l #0x020d020a,(a0)+ // vertikal 640x480
move.l #0x02A001e0,(a0)+ // horizontal 320x240
move.l #0x05a00160,(a0)+ // vertikal 320x240
#endif /* _NOT_USED_ */
/* fifo on, refresh on, ddrcs and cke on, video dac on */
* (volatile uint32_t *) (0xf0000410 - 0x20) = 0x01070002;
xprintf("finished\r\n");
sd_card_init();
/*
* memory setup
*/
for (adr = (uint32_t *) 0x400L; adr < (uint32_t *) 0x800L; ) {
*adr++ = 0x0L;
*adr++ = 0x0L;
*adr++ = 0x0L;
*adr++ = 0x0L;
}
* (volatile uint8_t *) 0xffff8007 = 0x48; /* FIXME: what's that ? */
/* ST RAM */
* (uint32_t *) 0x42e = STRAM_END; /* phystop TOS system variable */
* (uint32_t *) 0x420 = 0x752019f3; /* memvalid TOS system variable */
* (uint32_t *) 0x43a = 0x237698aa; /* memval2 TOS system variable */
* (uint32_t *) 0x51a = 0x5555aaaa; /* memval3 TOS system variable */
/* TT-RAM */
* (uint32_t *) 0x5a4 = FASTRAM_END; /* ramtop TOS system variable */
* (uint32_t *) 0x5a8 = 0x1357bd13; /* ramvalid TOS system variable */
#define NOP() __asm__ __volatile__("nop\n\t" : : : "memory")
xprintf("init ACIA: ");
/* init ACIA */
* (uint8_t *) 0xfffffc00 = 3;
NOP();
* (uint8_t *) 0xfffffc04 = 3;
NOP();
* (uint8_t *) 0xfffffc00 = 0x96;
NOP();
* (uint8_t *) 0xfffffa0f = -1;
NOP();
* (uint8_t *) 0xfffffa11 = -1;
NOP();
xprintf("finished\r\n");
/* Test for pseudo-supervisor mode: DIP switch #6 down */
if (DIP_SWITCH & (1 << 7)) {
/* In this mode, the OS actually runs in user mode
* and all the supervisor instructions are emulated. */
__asm__ __volatile__("move.w #0x0700,sr \n\t" : : : "memory");
}
srec_execute("BASFLASH.S19");
/* Jump into the OS */
typedef void void_func(void);
typedef struct {
void *initial_sp;
void_func *initial_pc;
} ROM_HEADER;
xprintf("Call OS. BaS initialization finished...\r\n");
enable_coldfire_interrupts();
ROM_HEADER* os_header = (ROM_HEADER*)TOS;
os_header->initial_pc();
}

View File

@@ -0,0 +1,366 @@
/*
* tc.printf.c: A public-domain, minimal printf/sprintf routine that prints
* through the putchar() routine. Feel free to use for
* anything... -- 7/17/87 Paul Placeway
*/
/*-
* Copyright (c) 1980, 1991 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 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 <stdarg.h>
#include "MCF5475.h"
#include "bas_printf.h"
#include "bas_string.h"
/*
* Lexical definitions.
*
* All lexical space is allocated dynamically.
* The eighth/sixteenth bit of characters is used to prevent recognition,
* and eventually stripped.
*/
#define META 0200
#define ASCII 0177
#define QUOTE ((char) 0200) /* Eighth char bit used for 'ing */
#define TRIM 0177 /* Mask to strip quote bit */
#define UNDER 0000000 /* No extra bits to do both */
#define BOLD 0000000 /* Bold flag */
#define STANDOUT META /* Standout flag */
#define LITERAL 0000000 /* Literal character flag */
#define ATTRIBUTES 0200 /* The bits used for attributes */
#define CHAR 0000177 /* Mask to mask out the character */
#define INF 32766 /* should be bigger than any field to print */
static char snil[] = "(nil)";
static void xputchar(int c)
{
__asm__ __volatile__
(
".extern printf_helper\n\t"
"move.b %0,d0\n\t"
"bsr printf_helper\n\t"
/* output */:
/* input */: "r" (c)
/* clobber */: "d0","d2","a0","memory"
);
}
static void doprnt(void (*addchar)(int), const char *sfmt, va_list ap)
{
char buf[128]; /* FIXME: this gets allocated in BSS which is not reachable in -mpcrel code */
char *bp;
const char *f;
long l;
unsigned long u;
int i;
int fmt;
unsigned char pad = ' ';
int flush_left = 0;
int f_width = 0;
int prec = INF;
int hash = 0;
int do_long = 0;
int sign = 0;
int attributes = 0;
f = sfmt;
for (; *f; f++)
{
if (*f != '%')
{
/* then just out the char */
(*addchar)((int) (((unsigned char) *f) | attributes));
}
else
{
f++; /* skip the % */
if (*f == '-')
{ /* minus: flush left */
flush_left = 1;
f++;
}
if (*f == '0' || *f == '.')
{
/* padding with 0 rather than blank */
pad = '0';
f++;
}
if (*f == '*')
{
/* field width */
f_width = va_arg(ap, int);
f++;
}
else if (isdigit((unsigned char)*f))
{
f_width = atoi(f);
while (isdigit((unsigned char)*f))
f++; /* skip the digits */
}
if (*f == '.')
{ /* precision */
f++;
if (*f == '*')
{
prec = va_arg(ap, int);
f++;
}
else if (isdigit((unsigned char)*f))
{
prec = atoi(f);
while (isdigit((unsigned char)*f))
f++; /* skip the digits */
}
}
if (*f == '#')
{ /* alternate form */
hash = 1;
f++;
}
if (*f == 'l')
{ /* long format */
do_long++;
f++;
if (*f == 'l')
{
do_long++;
f++;
}
}
fmt = (unsigned char) *f;
if (fmt != 'S' && fmt != 'Q' && isupper(fmt))
{
do_long = 1;
fmt = tolower(fmt);
}
bp = buf;
switch (fmt)
{ /* do the format */
case 'd':
switch (do_long)
{
case 0:
l = (long) (va_arg(ap, int));
break;
case 1:
default:
l = va_arg(ap, long);
break;
}
if (l < 0)
{
sign = 1;
l = -l;
}
do
{
*bp++ = (char) (l % 10) + '0';
} while ((l /= 10) > 0);
if (sign)
*bp++ = '-';
f_width = f_width - (int) (bp - buf);
if (!flush_left)
while (f_width-- > 0)
(*addchar)((int) (pad | attributes));
for (bp--; bp >= buf; bp--)
(*addchar)((int) (((unsigned char) *bp) | attributes));
if (flush_left)
while (f_width-- > 0)
(*addchar)((int) (' ' | attributes));
break;
case 'p':
do_long = 1;
hash = 1;
fmt = 'x';
/* no break */
case 'o':
case 'x':
case 'u':
switch (do_long)
{
case 0:
u = (unsigned long) (va_arg(ap, unsigned int));
break;
case 1:
default:
u = va_arg(ap, unsigned long);
break;
}
if (fmt == 'u')
{ /* unsigned decimal */
do
{
*bp++ = (char) (u % 10) + '0';
} while ((u /= 10) > 0);
}
else if (fmt == 'o')
{ /* octal */
do
{
*bp++ = (char) (u % 8) + '0';
} while ((u /= 8) > 0);
if (hash)
*bp++ = '0';
}
else if (fmt == 'x')
{ /* hex */
do
{
i = (int) (u % 16);
if (i < 10)
*bp++ = i + '0';
else
*bp++ = i - 10 + 'a';
} while ((u /= 16) > 0);
if (hash)
{
*bp++ = 'x';
*bp++ = '0';
}
}
i = f_width - (int) (bp - buf);
if (!flush_left)
while (i-- > 0)
(*addchar)((int) (pad | attributes));
for (bp--; bp >= buf; bp--)
(*addchar)((int) (((unsigned char) *bp) | attributes));
if (flush_left)
while (i-- > 0)
(*addchar)((int) (' ' | attributes));
break;
case 'c':
i = va_arg(ap, int);
(*addchar)((int) (i | attributes));
break;
case 'S':
case 'Q':
case 's':
case 'q':
bp = va_arg(ap, char *);
if (!bp)
bp = snil;
f_width = f_width - strlen((char *) bp);
if (!flush_left)
while (f_width-- > 0)
(*addchar)((int) (pad | attributes));
for (i = 0; *bp && i < prec; i++)
{
if (fmt == 'q' && (*bp & QUOTE))
(*addchar)((int) ('\\' | attributes));
(*addchar)(
(int) (((unsigned char) *bp & TRIM) | attributes));
bp++;
}
if (flush_left)
while (f_width-- > 0)
(*addchar)((int) (' ' | attributes));
break;
case 'a':
attributes = va_arg(ap, int);
break;
case '%':
(*addchar)((int) ('%' | attributes));
break;
default:
break;
}
flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
sign = 0;
pad = ' ';
}
}
}
static char *xstring, *xestring;
static void xaddchar(int c)
{
if (xestring == xstring)
*xstring = '\0';
else
*xstring++ = (char) c;
}
void xsnprintf(char *str, size_t size, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
xstring = str;
xestring = str + size - 1;
doprnt(xaddchar, fmt, va);
va_end(va);
*xstring++ = '\0';
}
void xprintf(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
doprnt(xputchar, fmt, va);
va_end(va);
}
void xvprintf(const char *fmt, va_list va)
{
doprnt(xputchar, fmt, va);
}
void xvsnprintf(char *str, size_t size, const char *fmt, va_list va)
{
xstring = str;
xestring = str + size - 1;
doprnt(xaddchar, fmt, va);
*xstring++ = '\0';
}
void display_progress()
{
static int _progress_index;
char progress_char[] = "|/-\\";
xputchar(progress_char[_progress_index++ % strlen(progress_char)]);
xputchar('\r');
}

View File

@@ -0,0 +1,74 @@
/*
* bas_string.c
*
* Created on: 26.02.2013
* Author: mfro
*/
#include "bas_string.h"
int strncmp(const char *s1, const char *s2, int max)
{
int i;
int cmp;
for (i = 0; i < max && *s1++ && *s2++; i++);
{
cmp = (*s1 - *s2);
if (cmp != 0) return cmp;
}
return cmp;
}
char *strcpy(char *dst, const char *src)
{
char *ptr = dst;
while ((*dst++ = *src++) != '\0');
return ptr;
}
int atoi(const char *c)
{
int value = 0;
while (isdigit(*c))
{
value *= 10;
value += (int) (*c - '0');
c++;
}
return value;
}
size_t strlen(const char *s)
{
const char *start = s;
while (*s++);
return s - start - 1;
}
char *strcat(char *dst, const char *src)
{
char *ret = dst;
dst = &dst[strlen(dst)];
while ((*dst++ = *src++) != '\0');
return ret;
}
char *strncat(char *dst, const char *src, int max)
{
int i;
char *ret = dst;
dst = &dst[strlen(dst)];
for (i = 0; i < max && *src; i++)
{
*dst++ = *src++;
}
*dst++ = '\0';
return ret;
}

View File

@@ -0,0 +1,420 @@
/*
* basflash.c
*
* Created on: 18.12.2012
* Author: mfro
*/
#include <stdint.h>
#include <stdbool.h>
#include "bas_string.h"
#include "bas_printf.h"
#include "diskio.h"
#include "ff.h"
#include "s19reader.h"
static uint32_t mx29lv640d_flash_sectors[] =
{
0xe0000000, 0xe0002000, 0xe0004000, 0xe0006000, 0xe0008000, 0xe000a000, 0xe000c000, 0xe000e000,
0xe0010000, 0xe0020000, 0xe0030000, 0xe0040000, 0xe0050000, 0xe0060000, 0xe0070000, 0xe0080000,
0xe0090000, 0xe00a0000, 0xe00b0000, 0xe00c0000, 0xe00d0000, 0xe00e0000, 0xe00f0000, 0xe0100000,
0xe0110000, 0xe0120000, 0xe0130000, 0xe0140000, 0xe0150000, 0xe0160000, 0xe0170000, 0xe0180000,
0xe0190000, 0xe01a0000, 0xe01b0000, 0xe01c0000, 0xe01d0000, 0xe01e0000, 0xe01f0000, 0xe0200000,
0xe0210000, 0xe0220000, 0xe0230000, 0xe0240000, 0xe0250000, 0xe0260000, 0xe0270000, 0xe0280000,
0xe0290000, 0xe02a0000, 0xe02b0000, 0xe02c0000, 0xe02d0000, 0xe02e0000, 0xe02f0000, 0xe0300000,
0xe0310000, 0xe0320000, 0xe0330000, 0xe0340000, 0xe0350000, 0xe0360000, 0xe0370000, 0xe0380000,
0xe0390000, 0xe03a0000, 0xe03b0000, 0xe03c0000, 0xe03d0000, 0xe03e0000, 0xe03f0000, 0xe0400000,
0xe0410000, 0xe0420000, 0xe0430000, 0xe0440000, 0xe0450000, 0xe0460000, 0xe0470000, 0xe0480000,
0xe0490000, 0xe04a0000, 0xe04b0000, 0xe04c0000, 0xe04d0000, 0xe04e0000, 0xe04f0000, 0xe0500000,
0xe0510000, 0xe0520000, 0xe0530000, 0xe0540000, 0xe0550000, 0xe0560000, 0xe0570000, 0xe0580000,
0xe0590000, 0xe05a0000, 0xe05b0000, 0xe05c0000, 0xe05d0000, 0xe05e0000, 0xe05f0000, 0xe0600000,
0xe0610000, 0xe0620000, 0xe0630000, 0xe0640000, 0xe0650000, 0xe0660000, 0xe0670000, 0xe0680000,
0xe0690000, 0xe06a0000, 0xe06b0000, 0xe06c0000, 0xe06d0000, 0xe06e0000, 0xe06f0000, 0xe0700000,
0xe0710000, 0xe0720000, 0xe0730000, 0xe0740000, 0xe0750000, 0xe0760000, 0xe0770000, 0xe0780000,
0xe0790000, 0xe07a0000, 0xe07b0000, 0xe07c0000, 0xe07d0000, 0xe07e0000, 0xe07f0000, 0xe0800000
};
static const int num_flash_sectors = sizeof(mx29lv640d_flash_sectors) / sizeof(uint32_t);
typedef struct romram
{
uint32_t flash_address;
uint32_t ram_address;
char *name;
} ROMRAM;
static const struct romram flash_areas[] =
{
{ 0xe0600000, 0x00e00000, "EmuTOS" }, /* EmuTOS */
{ 0xe0400000, 0x00e00000, "FireTOS" }, /* FireTOS */
{ 0xe0700000, 0x00e00000, "FPGA" }, /* FPGA config */
};
static const int num_flash_areas = sizeof(flash_areas) / sizeof(struct romram);
#define FLASH_ADDRESS 0xe0000000
static volatile uint16_t *flash_unlock1 = (volatile uint16_t *) FLASH_ADDRESS + 0xaaa;
static volatile uint16_t *flash_unlock2 = (volatile uint16_t *) FLASH_ADDRESS + 0x554;
static const uint16_t cmd_unlock1 = 0xaa;
static const uint16_t cmd_unlock2 = 0x55;
static const uint16_t cmd_sector_erase1 = 0x80;
static const uint16_t cmd_sector_erase2 = 0x30;
static const uint16_t cmd_sector_erase_suspend = 0xb0;
static const uint16_t cmd_sector_erase_resume = 0x30;
static const uint16_t cmd_program = 0xa0;
static const uint16_t cmd_autoselect = 0x90;
static const uint16_t cmd_read = 0xf0;
/*
* this callback just does nothing besides returning OK. Meant to do a dry run over the file to check its integrity
*/
static err_t simulate()
{
err_t ret = OK;
return ret;
}
static err_t memcpy(uint8_t *dst, uint8_t *src, uint32_t length)
{
uint8_t *end = src + length;
do
{
*dst++ = *src++;
} while (src < end);
return OK;
}
static err_t flash(uint8_t *dst, uint8_t *src, uint32_t length)
{
err_t ret = OK;
/* TODO: do the actual flash */
return ret;
}
/*
* this callback verifies the data against the S-record file contents after a write to destination
*/
static err_t verify(uint8_t *dst, uint8_t *src, uint32_t length)
{
uint8_t *end = src + length;
do
{
if (*src++ != *dst++)
return FAIL;
} while (src < end);
return OK;
}
/*
* unlock a flash sector
*/
err_t unlock_flash_sector(int sector_num)
{
volatile uint32_t rd;
uint32_t size = (sector_num < num_flash_sectors ?
mx29lv640d_flash_sectors[sector_num + 1] - mx29lv640d_flash_sectors[sector_num] :
0);
*flash_unlock1 = cmd_unlock1;
*flash_unlock2 = cmd_unlock2;
*flash_unlock1 = cmd_autoselect;
rd = * (volatile uint32_t *) FLASH_ADDRESS;
* (volatile uint32_t *) FLASH_ADDRESS = size;
(void) rd; /* get rid of "unused variable" compiler warning */
return OK;
}
/*
* erase a flash sector
*
* sector_num is the index into the sector table above.
*
* FIXME: need to disable data cache to ensure proper operation
*/
err_t erase_flash_sector(int sector_num)
{
volatile uint32_t rd;
uint32_t size = (sector_num < num_flash_sectors ?
mx29lv640d_flash_sectors[sector_num + 1] - mx29lv640d_flash_sectors[sector_num] :
0);
if (unlock_flash_sector(sector_num) == OK)
{
*flash_unlock1 = cmd_unlock1;
*flash_unlock2 = cmd_unlock2;
*flash_unlock1 = cmd_sector_erase1;
*flash_unlock1 = cmd_unlock1;
*flash_unlock2 = cmd_unlock2;
*flash_unlock1 = cmd_sector_erase1;
rd = * (volatile uint32_t *) FLASH_ADDRESS;
* (volatile uint32_t *) FLASH_ADDRESS = size;
(void) rd; /* get rid of "unused variable" compiler warning */
return OK;
}
return ILLEGAL_SECTOR;
}
err_t erase_flash_region(void *start_address, uint32_t length)
{
err_t err;
int sector = -1;
int i;
/*
* determine first sector to erase
*
* FIXME: if the start address of the .s19 file does not fall on a sector boundary, we
* will probably erase vital code in the previous flash sector. This should not happen on the Firebee
* where we have fixed areas for the different flash codes, but we should probably take care anyway
*/
for (i = 0; i < num_flash_sectors; i++)
{
if (start_address >= (void *) mx29lv640d_flash_sectors[i] && start_address <= (void *) mx29lv640d_flash_sectors[i])
sector = i;
}
if (sector >= 0 && sector <= num_flash_sectors)
{
/*
* erase sectors until free space equals length
*
* FIXME: same as above. Currently, there is no prevention against overlapping flash areas.
*/
do {
err = erase_flash_sector(sector);
sector++;
} while ((uint8_t *) mx29lv640d_flash_sectors[sector] < (uint8_t *) start_address + length && ! err);
}
else
{
err = ILLEGAL_SECTOR;
}
return err;
}
void srec_flash(char *flash_filename)
{
DRESULT res;
FRESULT fres;
FATFS fs;
FIL file;
err_t err;
void *start_address;
uint32_t length;
res = disk_status(0);
if (res == RES_OK)
{
fres = f_mount(0, &fs);
if (fres == FR_OK)
{
if ((fres = f_open(&file, flash_filename, FA_READ) != FR_OK))
{
xprintf("flasher file %s not present on disk\r\n", flash_filename);
}
else
{
f_close(&file);
/* first pass: parse and check for inconsistencies */
xprintf("check file integrity: ");
err = read_srecords(flash_filename, &start_address, &length, simulate);
if (err == OK)
{
xprintf("OK.\r\nerase flash area (from %p, length 0x%lx): ", start_address, length);
err = erase_flash_region(start_address, length);
/* next pass: copy data to destination */
xprintf("OK.\r\flash data: ");
err = read_srecords(flash_filename, &start_address, &length, memcpy);
if (err == OK)
{
/* next pass: verify data */
xprintf("OK.\r\nverify data: ");
err = read_srecords(flash_filename, &start_address, &length, verify);
if (err == OK)
{
typedef void void_func(void);
void_func *func;
xprintf("OK.\r\n");
xprintf("target successfully written and verified. Start address: %p\r\n", start_address);
func = (void_func *) start_address;
(*func)();
}
else
{
xprintf("failed\r\n");
}
}
else
{
xprintf("failed\r\n");
}
}
else
{
xprintf("failed\r\n");
}
}
}
else
{
// xprintf("could not mount FAT FS\r\n");
}
f_mount(0, 0L);
}
else
{
// xprintf("could not initialize SD card\r\n");
}
}
err_t srec_load(char *flash_filename)
{
FRESULT fres;
FIL file;
err_t err;
void *start_address;
uint32_t length;
if ((fres = f_open(&file, flash_filename, FA_READ) != FR_OK))
{
xprintf("flasher file %s not present on disk\r\n", flash_filename);
}
else
{
f_close(&file);
/* first pass: parse and check for inconsistencies */
xprintf("check file integrity: ");
err = read_srecords(flash_filename, &start_address, &length, simulate);
if (err == OK)
{
/* next pass: copy data to destination */
xprintf("OK.\r\ncopy/flash data: ");
err = read_srecords(flash_filename, &start_address, &length, memcpy);
if (err == OK)
{
/* next pass: verify data */
xprintf("OK.\r\nverify data: ");
err = read_srecords(flash_filename, &start_address, &length, verify);
if (err == OK)
{
typedef void void_func(void);
void_func *func;
xprintf("OK.\r\n");
xprintf("target successfully written and verified. Start address: %p\r\n", start_address);
func = (void_func *) start_address;
(*func)();
}
else
{
xprintf("failed\r\n");
}
}
else
{
xprintf("failed\r\n");
}
}
else
{
xprintf("failed\r\n");
}
}
return OK;
}
void basflash(void)
{
const char *basflash_str = "\\BASFLASH";
const char *bastest_str = "\\BASTEST";
DRESULT res;
FRESULT fres;
FATFS fs;
xprintf("\r\nHello from BASFLASH.S19!\r\n\r\n");
/*
* read \BASTEST\ folder contents (search for .S19-files). If found load them to their final destination
* (after BaS has copied them, not their flash location) and return.
*
* Files located in the BASTEST-folder thus override those in flash. Useful for testing before flashing
*/
res = disk_status(0);
xprintf("disk_status(0) = %d\r\n", res);
if (res == RES_OK)
{
fres = f_mount(0, &fs);
xprintf("f_mount() = %d\r\n", fres);
if (fres == FR_OK)
{
DIR directory;
fres = f_opendir(&directory, bastest_str);
xprintf("f_opendir() = %d\r\n", fres);
if (fres == FR_OK)
{
FILINFO fileinfo;
fres = f_readdir(&directory, &fileinfo);
xprintf("f_readdir() = %d\r\n", fres);
while (fres == FR_OK)
{
const char *srec_ext = ".S19";
char path[30];
if (fileinfo.fname[0] != '\0') /* found a file */
{
xprintf("check file %s (%s == %s ?)\r\n", fileinfo.fname, &fileinfo.fname[strlen(fileinfo.fname) - 4], srec_ext);
if (strlen(fileinfo.fname) >= 4 && strncmp(&fileinfo.fname[strlen(fileinfo.fname) - 4], srec_ext, 4) == 0) /* we have a .S19 file */
{
/*
* build path + filename
*/
strcpy(path, bastest_str);
strcat(path, "\\");
strncat(path, fileinfo.fname, 13);
xprintf("loading file %s\r\n", path);
/*
* load file
*/
if (srec_load(path) != OK)
{
xprintf("failed to load file %s\r\n", path);
// error handling
}
}
}
else
break; /* exit if no file found */
fres = f_readdir(&directory, &fileinfo);
xprintf("f_readdir() = %d\r\n", fres);
}
}
else
{
xprintf("f_opendir %s failed with error code %d\r\n", bastest_str, fres);
}
}
else
{
// xprintf("could not mount FAT FS\r\n");
}
f_mount(0, 0L); /* unmount SD card */
}
}

View File

@@ -0,0 +1,26 @@
/*
* basflash_start.c
*
* Created on: 16.02.2013
* Author: mfro
*/
#include <stdint.h>
static uint32_t ownstack[4096];
static uint32_t *stackptr = &ownstack[4095];
/*
* setup our own stack in SDRAM to prevent clashing BaS's in SRAM (size limited).
*/
void startup(void)
{
static uint32_t oldstack;
void basflash(void);
__asm__ __volatile__("move.l sp,%0\n\t" : "=g"(oldstack) : :);
__asm__ __volatile__("move.l %0,sp\n\t" : : "g"(stackptr) : );
basflash();
__asm__ __volatile__("move.l %0,sp\n\t" : : "g"(oldstack) : "sp");
(void) stackptr; /* make compiler happy about unused variables */
}

View File

@@ -0,0 +1,48 @@
/*
* cache handling
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2010 - 2012 F. Aschwanden
* Copyright 2011 - 2012 V. Riviere
* Copyright 2012 M. Froeschle
*
*/
#include "cache.h"
void flush_and_invalidate_caches(void)
{
__asm__ (
" clr.l d0\n\t"
" clr.l d1\n\t"
" move.l d0,a0\n\t"
"cfa_setloop:\n\t"
" cpushl bc,(a0) | flush\n\t"
" lea 0x10(a0),a0 | index+1\n\t"
" addq.l #1,d1 | index+1\n\t"
" cmpi.w #512,d1 | all sets?\n\t"
" bne.s cfa_setloop | no->\n\t"
" clr.l d1\n\t"
" addq.l #1,d0\n\t"
" move.l d0,a0\n\t"
" cmpi.w #4,d0 | all ways?\n\t"
" bne.s cfa_setloop | no->\n\t"
/* input */ :
/* output */ :
/* clobber */ : "d0", "d1", "a0"
);
}

File diff suppressed because it is too large Load Diff

10973
i2cspi_BaS_gcc/sources/cc936.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,540 @@
/*------------------------------------------------------------------------*/
/* Unicode - Local code bidirectional converter (C)ChaN, 2009 */
/* (SBCS code pages) */
/*------------------------------------------------------------------------*/
/* 437 U.S. (OEM)
/ 720 Arabic (OEM)
/ 1256 Arabic (Windows)
/ 737 Greek (OEM)
/ 1253 Greek (Windows)
/ 1250 Central Europe (Windows)
/ 775 Baltic (OEM)
/ 1257 Baltic (Windows)
/ 850 Multilingual Latin 1 (OEM)
/ 852 Latin 2 (OEM)
/ 1252 Latin 1 (Windows)
/ 855 Cyrillic (OEM)
/ 1251 Cyrillic (Windows)
/ 866 Russian (OEM)
/ 857 Turkish (OEM)
/ 1254 Turkish (Windows)
/ 858 Multilingual Latin 1 + Euro (OEM)
/ 862 Hebrew (OEM)
/ 1255 Hebrew (Windows)
/ 874 Thai (OEM, Windows)
/ 1258 Vietnam (OEM, Windows)
*/
#include <ff.h>
#include <stdint.h>
#if _CODE_PAGE == 437
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 720
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9,
0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642,
0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A,
0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0xO650, 0x2248,
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 737
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398,
0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9,
0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0,
0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD,
0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E,
0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248,
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 775
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107,
0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A,
0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6,
0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118,
0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D,
0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B,
0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144,
0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019,
0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E,
0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 850
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE,
0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 852
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7,
0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A,
0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E,
0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A,
0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE,
0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161,
0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4,
0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8,
0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 855
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404,
0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C,
0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414,
0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438,
0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E,
0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580,
0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443,
0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116,
0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D,
0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 857
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F,
0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE,
0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000,
0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4,
0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 858
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
0x00A9, 0x2563, 0x2551, 0x2557, 0x2550, 0x00A2, 0x00A5, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x20AC, 0x00CD, 0x00CE,
0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00C6, 0x00CC, 0x2580,
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 862
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 866
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E,
0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0
};
#elif _CODE_PAGE == 874
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07,
0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17,
0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F,
0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47,
0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000
};
#elif _CODE_PAGE == 1250
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A,
0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B,
0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C,
0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
};
#elif _CODE_PAGE == 1251
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x0000, 0x2111, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457,
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F
};
#elif _CODE_PAGE == 1252
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178,
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
};
#elif _CODE_PAGE == 1253
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000,
0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015,
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7,
0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
0x03A8, 0x03A9, 0x03AA, 0x03AD, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000
};
#elif _CODE_PAGE == 1254
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178,
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x0130, 0x015E, 0x00DF,
0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF
};
#elif _CODE_PAGE == 1255
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000,
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3,
0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000
};
#elif _CODE_PAGE == 1256
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA,
0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F,
0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7,
0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0640, 0x0642, 0x0643,
0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7,
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF,
0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7,
0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2
}
#elif _CODE_PAGE == 1257
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000,
0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7,
0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112,
0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7,
0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113,
0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7,
0x0173, 0x014E, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9
};
#elif _CODE_PAGE == 1258
#define _TBLDEF 1
static
const uint16_t Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178,
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF,
0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7,
0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF,
0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF,
0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7,
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF
};
#endif
#if !_TBLDEF || !_USE_LFN
#error This file is not needed in current configuration. Remove from the project.
#endif
uint16_t ff_convert ( /* Converted character, Returns zero on error */
uint16_t src, /* Character code to be converted */
uint32_t dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
)
{
uint16_t c;
if (src < 0x80) { /* ASCII */
c = src;
} else {
if (dir) { /* OEMCP to Unicode */
c = (src >= 0x100) ? 0 : Tbl[src - 0x80];
} else { /* Unicode to OEMCP */
for (c = 0; c < 0x80; c++) {
if (src == Tbl[c]) break;
}
c = (c + 0x80) & 0xFF;
}
}
return c;
}
uint16_t ff_wtoupper ( /* Upper converted character */
uint16_t chr /* Input character */
)
{
static const uint16_t tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 };
static const uint16_t tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 };
int i;
for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ;
return tbl_lower[i] ? tbl_upper[i] : chr;
}

View File

@@ -0,0 +1,839 @@
/*
* initialize exception vectors
*/
#include "startcf.h"
.extern __Bas_base
.extern __SUP_SP
.extern _rom_entry
.extern __RAMBAR0
.extern _rt_cacr
.extern _rt_mod
.extern _rt_ssp
.extern _rt_usp
.extern _rt_vbr
.extern _illegal_instruction
.extern _privileg_violation
.extern _mmutr_miss
.extern __MBAR
.extern __MMUBAR
.extern _video_tlb
.extern _video_sbt
.extern cpusha
/* Register read/write macros */
#define MCF_MMU_MMUCR __MMUBAR
#define MCF_MMU_MMUOR __MMUBAR+0x04
#define MCF_MMU_MMUSR __MMUBAR+0x08
#define MCF_MMU_MMUAR __MMUBAR+0x10
#define MCF_MMU_MMUTR __MMUBAR+0x14
#define MCF_MMU_MMUDR __MMUBAR+0x18
#define MCF_EPORT_EPPAR __MBAR+0xF00
#define MCF_EPORT_EPDDR __MBAR+0xF04
#define MCF_EPORT_EPIER __MBAR+0xF05
#define MCF_EPORT_EPDR __MBAR+0xF08
#define MCF_EPORT_EPPDR __MBAR+0xF09
#define MCF_EPORT_EPFR __MBAR+0xF0C
#define MCF_GPIO_PODR_FEC1L __MBAR+0xA07
#define MCF_PSC0_PSCTB_8BIT __MBAR+0x860C
#define MCF_PSC3_PSCRB_8BIT __MBAR+0x890C
#define MCF_PSC3_PSCTB_8BIT __MBAR+0x890C
.global _vec_init
//mmu ---------------------------------------------------
/* Register read/write macros */
#define MCF_MMU_MMUCR __MMUBAR
#define MCF_MMU_MMUOR __MMUBAR+0x04
#define MCF_MMU_MMUSR __MMUBAR+0x08
#define MCF_MMU_MMUAR __MMUBAR+0x10
#define MCF_MMU_MMUTR __MMUBAR+0x14
#define MCF_MMU_MMUDR __MMUBAR+0x18
/* Bit definitions and macros for MCF_MMU_MMUCR */
#define MCF_MMU_MMUCR_EN (0x1)
#define MCF_MMU_MMUCR_ASM (0x2)
/* Bit definitions and macros for MCF_MMU_MMUOR */
#define MCF_MMU_MMUOR_UAA (0x1)
#define MCF_MMU_MMUOR_ACC (0x2)
#define MCF_MMU_MMUOR_RW (0x4)
#define MCF_MMU_MMUOR_ADR (0x8)
#define MCF_MMU_MMUOR_ITLB (0x10)
#define MCF_MMU_MMUOR_CAS (0x20)
#define MCF_MMU_MMUOR_CNL (0x40)
#define MCF_MMU_MMUOR_CA (0x80)
#define MCF_MMU_MMUOR_STLB (0x100)
#define MCF_MMU_MMUOR_AA(x) (((x)&0xFFFF)<<0x10)
/* Bit definitions and macros for MCF_MMU_MMUSR */
#define MCF_MMU_MMUSR_HIT (0x2)
#define MCF_MMU_MMUSR_WF (0x8)
#define MCF_MMU_MMUSR_RF (0x10)
#define MCF_MMU_MMUSR_SPF (0x20)
/* Bit definitions and macros for MCF_MMU_MMUAR */
#define MCF_MMU_MMUAR_FA(x) (((x)&0xFFFFFFFF)<<0)
/* Bit definitions and macros for MCF_MMU_MMUTR */
#define MCF_MMU_MMUTR_V (0x1)
#define MCF_MMU_MMUTR_SG (0x2)
#define MCF_MMU_MMUTR_ID(x) (((x)&0xFF)<<0x2)
#define MCF_MMU_MMUTR_VA(x) (((x)&0x3FFFFF)<<0xA)
/* Bit definitions and macros for MCF_MMU_MMUDR */
#define MCF_MMU_MMUDR_LK (0x2)
#define MCF_MMU_MMUDR_X (0x4)
#define MCF_MMU_MMUDR_W (0x8)
#define MCF_MMU_MMUDR_R (0x10)
#define MCF_MMU_MMUDR_SP (0x20)
#define MCF_MMU_MMUDR_CM(x) (((x)&0x3)<<0x6)
#define MCF_MMU_MMUDR_SZ(x) (((x)&0x3)<<0x8)
#define MCF_MMU_MMUDR_PA(x) (((x)&0x3FFFFF)<<0xA)
#define std_mmutr (MCF_MMU_MMUTR_SG|MCF_MMU_MMUTR_V)
#define mmuord_d ( MCF_MMU_MMUOR_ACC|MCF_MMU_MMUOR_UAA)
#define mmuord_i (MCF_MMU_MMUOR_ITLB|MCF_MMU_MMUOR_ACC|MCF_MMU_MMUOR_UAA)
#define wt_mmudr (MCF_MMU_MMUDR_SZ(00)|MCF_MMU_MMUDR_CM(00)|MCF_MMU_MMUDR_R|MCF_MMU_MMUDR_W|MCF_MMU_MMUDR_X)
#define cb_mmudr (MCF_MMU_MMUDR_SZ(00)|MCF_MMU_MMUDR_CM(01)|MCF_MMU_MMUDR_R|MCF_MMU_MMUDR_W|MCF_MMU_MMUDR_X)
#define nc_mmudr (MCF_MMU_MMUDR_SZ(00)|MCF_MMU_MMUDR_CM(10)|MCF_MMU_MMUDR_R|MCF_MMU_MMUDR_W|MCF_MMU_MMUDR_X)
//---------------------------------------------------
/*********************************************************************
*
* General Purpose Timers (GPT)
*
*********************************************************************/
/* Register read/write macros */
#define MCF_GPT0_GMS __MBAR+0x800
/*********************************************************************
*
* Slice Timers (SLT)
*
*********************************************************************/
#define MCF_SLT0_SCNT __MBAR+0x908
/**********************************************************/
// macros
/**********************************************************/
.altmacro
.macro irq vector,int_mask,clr_int
local irq_protect
local sev_supint
local irq_end
move.w #0x2700,sr // disable interrupt
subq.l #8,a7
movem.l d0/a5,(a7) // register sichern
lea MCF_EPORT_EPFR,a5
move.b #\clr_int,(a5) // clear int pending
// test auf protect mode ---------------------
move.b DIP_SWITCHa,d0
btst #7,d0
bne irq_protect // ja->
// -------------------------------------------
movem.l (a7),d0/a5 // register zurück
addq.l #8,a7
move.l \vector,-(a7)
move #0x2\int_mask\()00,sr
rts
irq_protect:
move.l usp,a5 // usp holen
tst.b _rt_mod // supervisor?
bne sev_supint // ja ->
mov3q.l #-1,_rt_mod // auf supervisor setzen
move.l a5,_rt_usp // rt_usp speichern
move.l _rt_ssp,a5 // rt_ssp holen
#ifdef cf_stack
move.l 12(a7),-(a5) // pc transferieren
move.l 8(a7),-(a5) // sr,vec
#else
move.w 8(a7),-(a5) // vector nr.
move.l 12(a7),-(a5) // pc verschieben
move.w 10(a7),-(a5) // sr verschieben
#endif
bra irq_end
sev_supint:
#ifdef cf_stack
move.l 12(a7),-(a5) // pc transferieren
move.l 8(a7),-(a5) // sr,vec
bset #5,2(a5) // auf super setzen
#else
move.w 8(a7),-(a5) // vector nr.
move.l 12(a7),-(a5) // pc verschieben
move.w 10(a7),-(a5) // sr verschieben
bset #5,(a5) // auf super
#endif
irq_end:
move.l a5,usp // usp setzen
lea \vector,a5
adda.l _rt_vbr,a5
move.l (a5),12(a7) // vectoradresse eintragen
move.b #\int_mask,10(a7) // intmaske setzen
movem.l (a7),d0/a5 // register zur<EFBFBD>ck
addq.l #8,a7
rte // und weg
.endm
/*
* FIXME: this is a GNU gas kludge. Ugly, but I just can't come up with any smarter solution
*
* GNU as does not support multi-character constants. At least I don't know of any way it would.
* The following might look more than strange, but I considered the statement
*
* mchar move.l, 'T,'E,'S,'T,-(SP)
*
* somewhat more readable than
*
* move.l #1413829460,-(SP)
*
* If anybody knows of any better way on how to do this - please do!
*
*/
.macro mchar st,a,b,c,d,tgt
\st #\a << 24|\b<<16|\c<<8|\d,\tgt
.endm
.text
_vec_init:
move.l a2,-(sp) // Backup registers
mov3q.l #-1,_rt_mod // rt_mod auf super
clr.l _rt_ssp
clr.l _rt_usp
clr.l _rt_vbr
move.l #__RAMBAR0,d0 // sind in rambar0
movec d0,VBR
move.l d0,a0
move.l a0,a2
init_vec:
move.l #256,d0
lea std_exc_vec(pc),a1 // standard vector
init_vec_loop:
move.l a1,(a2)+ // mal standard vector f<EFBFBD>r alle setzen
subq.l #1,d0
bne init_vec_loop
move.l #__SUP_SP,(a0)
lea reset_vector(pc),a1
move.l a1,0x04(a0)
lea acess(pc),a1
move.l a1,0x08(a0)
move.b DIP_SWITCHa,d0 // ++ vr
btst #7,d0
beq no_protect_vectors
lea _illegal_instruction(pc),a1
move.l a1,0x0c(a0)
lea _illegal_instruction(pc),a1
move.l a1,0x10(a0)
lea zero_divide(pc),a1
move.l a1,0x14(a0)
lea _privileg_violation(pc),a1
move.l a1,0x20(a0)
lea linea(pc),a1
move.l a1,0x28(a0)
lea linef(pc),a1
move.l a1,0x2c(a0)
lea format(pc),a1
move.l a1,0x38(a0)
// floating point overflow
lea flpoow(pc),a1
move.l a1,0xc0(a0)
lea flpoow(pc),a1
move.l a1,0xc4(a0)
lea flpoow(pc),a1
move.l a1,0xc8(a0)
lea flpoow(pc),a1
move.l a1,0xcc(a0)
lea flpoow(pc),a1
move.l a1,0xd0(a0)
lea flpoow(pc),a1
move.l a1,0xd4(a0)
lea flpoow(pc),a1
move.l a1,0xd8(a0)
lea flpoow(pc),a1
move.l a1,0xdc(a0)
no_protect_vectors:
// int 1-7
lea irq1(pc),a1
move.l a1,0x104(a0)
lea irq2(pc),a1
move.l a1,0x108(a0)
lea irq3(pc),a1
move.l a1,0x10c(a0)
lea irq4(pc),a1
move.l a1,0x110(a0)
lea irq5(pc),a1
move.l a1,0x114(a0)
lea irq6(pc),a1
move.l a1,0x118(a0)
lea irq7(pc),a1
move.l a1,0x11c(a0)
//psc_vectors
lea psc3(pc),a1
move.l a1,0x180(a0)
//timer 1 vectors
lea timer0(pc),a1
move.l a1,0x1f8(a0)
move.l (sp)+,a2 // Restore registers
rts
/*
* exception vector routines
*/
vector_table_start:
std_exc_vec:
move.w #0x2700,sr // disable interrupt
subq.l #8,a7
movem.l d0/a5,(a7) // register sichern
// test auf protect mode -------------------------------
move.b DIP_SWITCHa,d0
btst #7,d0
bne stv_protect // ja->
//------------------------------------------------------
move.w 8(a7),d0 // vector holen
and.l #0x3fc,d0 // vector nummer ausmaskieren
add.l _rt_vbr,d0 // + basis
move.l d0,a5
move.l (a5),d0
move.l 4(a7),a5 // a5 zur<EFBFBD>ck
move.l d0,4(a7)
move.w 10(a7),d0
bset #13,d0 // super
move.w d0,sr // orginal sr wert in super setzen
move.l (a7)+,d0 // d0 zur<EFBFBD>ck
rts
stv_protect:
move.l usp,a5 // usp holen
tst.b _rt_mod // supervisor?
bne sev_sup // ja ->
mov3q.l #-1,_rt_mod // auf supervisor setzen
move.l a5,_rt_usp // rt_usp speichern
move.l _rt_ssp,a5 // rt_ssp holen
#ifdef cf_stack
move.l 12(a7),-(a5) // pc transferieren
move.l 8(a7),d0 // sr holen
move.l d0,-(a5) // sr transferieren
swap d0 // vec -> lw
#else
move.w 8(a7),d0 // vector holen
move.w d0,-(a5) // ablegen
move.l 12(a7),-(a5) // pc transferieren
move.w 10(a7),-(a5) // sr transferieren
#endif
move.l a5,usp // usp setzen
and.l #0x3fc,d0 // vector nummer ausmaskieren
add.l _rt_vbr,d0 // + basis
move.l d0,a5
move.l (a5),12(a7) // hier geht's weiter
movem.l (a7),d0/a5 // register zur<EFBFBD>ck
addq.l #8,a7
rte // und weg
sev_sup:
#ifdef cf_stack
move.l 12(a7),-(a5) // pc transferieren
move.l 8(a7),d0 // sr holen
bset #13,d0 // war aus rt super
move.l d0,-(a5) // sr transferieren
swap d0 // vec -> lw
#else
move.w 8(a7),d0 // vector holen
move.w d0,-(a5) // ablegen
move.l 12(a7),-(a5) // pc transferieren
move.w 10(a7),-(a5) // sr transferieren
bset #5,(a5) // war aus super
#endif
move.l a5,usp // usp setzen
and.l #0x3fc,d0 // vector nummer ausmaskieren
add.l _rt_vbr,d0 // + basis
move.l d0,a5
move.l (a5),12(a7) // hier geht's weiter
movem.l (a7),d0/a5 // register zur<EFBFBD>ck
addq.l #8,a7
rte // und weg
//*******************************************
reset_vector:
move.w #0x2700,sr // disable interrupt
move.l #0x31415926,d0
cmp.l 0x426,d0 // reset vector g<EFBFBD>ltg?
beq std_exc_vec // ja->
jmp _rom_entry // sonst kaltstart
acess:
move.w #0x2700,sr // disable interrupt
move.l d0,-(sp) // ++ vr
move.w 4(sp),d0
andi.l #0x0c03,d0
cmpi.l #0x0401,d0
beq access_mmu
cmpi.l #0x0402,d0
beq access_mmu
cmpi.l #0x0802,d0
beq access_mmu
cmpi.l #0x0c02,d0
beq access_mmu
bra bus_error
access_mmu:
move.l MCF_MMU_MMUSR,d0
btst #1,d0
bne bus_error
move.l MCF_MMU_MMUAR,d0
cmp.l #__FASTRAM_END,d0 // max User RAM Bereich
bge bus_error // grösser -> bus error
bra _mmutr_miss
bus_error:
move.l (sp)+,d0
bra std_exc_vec
zero_divide:
move.w #0x2700,sr // disable interrupt
move.l a0,-(a7)
move.l d0,-(a7)
move.l 12(a7),a0 // pc
move.w (a0)+,d0 // befehlscode
btst #7,d0 // long?
beq zd_word // nein->
addq.l #2,a0
zd_word:
and.l 0x3f,d0 // ea ausmaskieren
cmp.w #0x08,d0 // -(ax) oder weniger
ble zd_end
addq.l #2,a0
cmp.w #0x39,d0 // xxx.L
bne zd_nal
addq.l #2,a0
bra zd_end
zd_nal: cmp.w #0x3c,d0 // immediate?
bne zd_end // nein->
btst #7,d0 // long?
beq zd_end // nein
addq.l #2,a0
zd_end:
move.l a0,12(a7)
move.l (a7)+,d0
move.l (a7)+,a0
rte
linea:
move.w #0x2700,sr // disable interrupt
halt
nop
nop
linef:
move.w #0x2700,sr // disable interrupt
halt
nop
nop
format:
move.w #0x2700,sr // disable interrupt
halt
nop
nop
//floating point
flpoow:
move.w #0x2700,sr // disable interrupt
halt
nop
nop
irq1:
irq 0x64,1,0x02
irq2: // hbl
// move.b #3,2(a7)
// rte
irq 0x68,2,0x04
irq3:
irq 0x6c,3,0x08
irq4: // vbl
irq 0x70,4,0x10
irq5: // acp
irq 0x74,5,0x20
irq6: // mfp
move.w #0x2700,sr // disable interrupt
subq.l #8,a7
movem.l d0/a5,(a7) // register sichern
lea MCF_EPORT_EPFR,a5
move.b #0x40,(a5) // clear int6
// test auf timeout screen adr change -------------------------------------------------------
move.l _video_sbt,d0
beq irq6_non_sca // wenn 0 nichts zu tun
sub.l #0x70000000,d0 // 14 sec abz<EFBFBD>hlen
lea MCF_SLT0_SCNT,a5
cmp.l (a5),d0 // aktuelle zeit weg
ble irq6_non_sca // noch nicht abgelaufen
lea -28(a7),a7
movem.l d0-d4/a0-a1,(a7) // register sichern
clr.l d3 // beginn mit 0
bsr cpusha // cache leeren
// eintrag suchen
irq6_next_sca:
move.l d3,d0
move.l d0,MCF_MMU_MMUAR // addresse
move.l #0x106,d4
move.l d4,MCF_MMU_MMUOR // suchen ->
nop
move.l MCF_MMU_MMUOR,d4
clr.w d4
swap d4
move.l d4,MCF_MMU_MMUAR
mvz.w #0x10e,d4
move.l d4,MCF_MMU_MMUOR // eintr<EFBFBD>ge holen aus mmu
nop
move.l MCF_MMU_MMUTR,d4 // ID holen
lsr.l #2,d4 // bit 9 bis 2
cmp.w #sca_page_ID,d4 // ist screen change ID?
bne irq6_sca_pn // nein -> page keine screen area next
// eintrag <EFBFBD>ndern
add.l #std_mmutr,d0
move.l d3,d1 // page 0?
beq irq6_sca_pn0 // ja ->
add.l #cb_mmudr,d1 // sonst page cb
bra irq6_sca_pn1c
irq6_sca_pn0:
add.l #wt_mmudr|MCF_MMU_MMUDR_LK,d1 // page wt and locked
irq6_sca_pn1c:
mvz.w #0x10b,d2 // MMU update
move.l d0,MCF_MMU_MMUTR
move.l d1,MCF_MMU_MMUDR
move.l d2,MCF_MMU_MMUOR // setze tlb data only
nop
// page copy
move.l d3,a0
add.l #0x60000000,a0
move.l d3,a1
move.l #0x10000,d4 // die ganze page
irq6_vcd0_loop:
move.l (a0)+,(a1)+ // page copy
move.l (a0)+,(a1)+
move.l (a0)+,(a1)+
move.l (a0)+,(a1)+
subq.l #1,d4
bne irq6_vcd0_loop
nop
irq6_sca_pn:
add.l #0x00100000,d3 // next
cmp.l #0x00d00000,d3 // ende?
blt irq6_next_sca // nein->
move.l #0x2000,d0
move.l d0,_video_tlb // anfangszustand wieder herstellen
clr.l _video_sbt // zeit l<EFBFBD>schen
movem.l (a7),d0-d4/a0-a1 // register zur<EFBFBD>ck
lea 28(a7),a7
irq6_non_sca:
// test auf acsi dma -----------------------------------------------------------------
lea 0xfffffa0b,a5
bset #7,-4(a5) // int ena
btst.b #7,(a5) // acsi dma int?
beq non_acsi_dma
bsr acsi_dma
non_acsi_dma:
// ----------------------------------------------------------------------------------
tst.b (a5)
bne irq6_1
tst.b 2(a5)
bne irq6_1
movem.l (a7),d0/a5
addq.l #8,a7
rte
irq6_1:
lea MCF_GPIO_PODR_FEC1L,a5
bclr.b #4,(a5) // led on
lea blinker,a5
addq.l #1,(a5) // +1
move.l (a5),d0
and.l #0x80,d0
bne irq6_2
lea MCF_GPIO_PODR_FEC1L,a5
bset.b #4,(a5) // led off
irq6_2:
// test auf protect mode ---------------------
move.b DIP_SWITCHa,d0
btst #7,d0
bne irq6_3 // ja->
// -------------------------------------------
move.l 0xF0020000,a5 // vector holen
add.l _rt_vbr,a5 // basis
move.l (a5),d0 // vector holen
move.l 4(a7),a5 // a5 zur<EFBFBD>ck
move.l d0,4(a7) // vector eintragen
move.l (a7)+,d0 // d0 zur<EFBFBD>ck
move #0x2600,sr
rts
irq6_3:
move.l usp,a5 // usp holen
tst.b _rt_mod // supervisor?
bne sev_sup6 // ja ->
mov3q.l #-1,_rt_mod // auf supervisor setzen
move.l a5,_rt_usp // rt_usp speichern
move.l _rt_ssp,a5 // rt_ssp holen
#ifdef cf_stack
move.l 12(a7),-(a5) // pc transferieren
move.l 8(a7),-(a5) // sr transferieren
#else
move.w 8(a7),-(a5) // vector transferieren
move.l 12(a7),-(a5) // pc transferieren
move.w 10(a7),-(a5) // sr transferieren
#endif
move.l a5,usp // usp setzen
move.l 0xF0020000,a5 // vector holen: intack routine
add.l _rt_vbr,a5 // virtuelle VBR des Systems
move.l (a5),12(a7) // hier gehts weiter
movem.l (a7),d0/a5 // register zur<EFBFBD>ck
addq.l #8,a7
move.b #6,2(a7) // intmaske setzen
rte // und weg
sev_sup6:
#ifdef cf_stack
move.l 12(a7),-(a5) // pc transferieren
move.l 8(a7),-(a5) // sr,vec
bset #5,2(a5) // auf super setzen
#else
move.w 8(a7),-(a5) // vector nr.
move.l 12(a7),-(a5) // pc verschieben
move.w 10(a7),-(a5) // sr verschieben
bset #5,(a5) // auf super
#endif
move.l a5,usp // usp setzen
move.l 0xF0020000,a5 // vector holen: intack routine
add.l _rt_vbr,a5 // virtuelle VBR des Systems
move.l (a5),12(a7) // hier gehts weiter
movem.l (a7),d0/a5 // register zur<EFBFBD>ck
rts
.data
blinker:.long 0
.text
/*
* pseudo dma
*/
acsi_dma: // atari dma
move.l a1,-(a7)
move.l d1,-(a7)
lea MCF_PSC0_PSCTB_8BIT,a1 // ++ vr
mchar move.l, 'D,'M','A,'\ ,(a1)
//move.l #"DMA ",(a1)
mchar move.l,'I,'N,'T,'!,(a1)
// move.l #'INT!',(a1)
lea 0xf0020110,a5 // fifo daten
acsi_dma_start:
move.l -12(a5),a1 // dma adresse
move.l -8(a5),d0 // byt counter
ble acsi_dma_end
btst.b #0,-16(a5) // write? (dma modus reg)
bne acsi_dma_wl // ja->
acsi_dma_rl:
tst.b -4(a5) // dma req?
bpl acsi_dma_fertig // nein->
move.l (a5),(a1)+ // read 4 bytes
move.l (a5),(a1)+ // read 4 bytes
move.l (a5),(a1)+ // read 4 bytes
move.l (a5),(a1)+ // read 4 bytes
moveq #'.',d1
move.b d1,MCF_PSC0_PSCTB_8BIT
sub.l #16,d0 // byt counter -16
bpl acsi_dma_rl
bra acsi_dma_fertig
acsi_dma_wl:
tst.b -4(a5) // dma req?
bpl acsi_dma_fertig // nein->
move.l (a1)+,(a5) // write 4 byts
move.l (a1)+,(a5) // write 4 byts
move.l (a1)+,(a5) // write 4 byts
move.l (a1)+,(a5) // write 4 byts
moveq #'.',d1
move.b d1,MCF_PSC0_PSCTB_8BIT
sub.l #16,d0 // byt counter -16
bpl acsi_dma_wl
acsi_dma_fertig:
move.l a1,-12(a5) // adresse zur<EFBFBD>ck
move.l d0,-8(a5) // byt counter zur<EFBFBD>ck
acsi_dma_end:
tst.b -4(a5) // dma req?
bmi acsi_dma_start // ja->
lea 0xfffffa0b,a5
bclr.b #7,4(a5) // clear int in service mfp
bclr.b #7,(a5) // clear int pending mfp 0xfffffa0b
move.w #0x0d0a,d1
move.w d1,MCF_PSC0_PSCTB_8BIT
move.l (a7)+,d1
move.l (a7)+,a1
rts
/*
* irq 7 = pseudo bus error
*/
irq7:
lea -12(sp),sp
movem.l d0/a0,(sp)
move.l __RAMBAR0+0x008,a0 // Real Access Error handler
move.l a0,8(sp) // This will be the return address for rts
move.w 12(sp),d0 // Format/Vector word
andi.l #0xf000,d0 // Keep only the Format
ori.l #2*4,d0 // Simulate Vector #2, no Fault
move.w d0,12(sp)
// TODO: Inside an interrupt handler, 16(sp) is the return address.
// For an Access Error, it should be the address of the fault instruction instead
lea MCF_EPORT_EPFR,a0
move.b #0x80,(a0) // clear int7
move.l (sp)+,d0
move.l (sp)+,a0
rts // Forward to the Access Error handler
/*
* psc3 com PIC MCF
*/
psc3:
move.w #0x2700,sr // disable interrupt
lea -20(a7),a7
movem.l d0-d2/a0/a3,(a7)
lea MCF_PSC3_PSCRB_8BIT,a3
move.b (a3),d1
cmp.b #2,d1 // anforderung rtc daten?
bne psc3_fertig
lea MCF_PSC0_PSCTB_8BIT,a0 // ++ vr
mchar move.l,'\P,'\I,'C,' ,(a0)
// move.l #'PIC ',(a0)
mchar move.l,'I,'N,'T,'\ ,(a0)
// move.l #'INT ',(a0)
mchar move.l,'R,'T,'C,'!,(a0)
// move.l #'RTC!',(a0)
mchar move.l,0x0d,0x0a,0,0,(a0)
//move.l #0x0d0a,(a0)
lea 0xffff8961,a0
lea MCF_PSC3_PSCTB_8BIT,a3
clr.l d1
moveq #64,d2
move.b #0x82,(a3) // header: rtcd mcf->pic
loop_sr2:
move.b d1,(a0)
move.b 2(a0),d0
move.b d0,(a3)
addq.l #1,d1
cmp.b d1,d2
bne loop_sr2
psc3_fertig:
movem.l (a7),d0-d2/a0/a3 // register zur<EFBFBD>ck
lea 20(a7),a7
RTE
/*
* timer 0: video change later also others
*/
timer0:
move #0x2700,sr
// halt
lea -28(a7),a7
movem.l d0-d4/a0-a1,(a7)
mvz.b 0xffff8201,d0 // l<EFBFBD>schen und high byt
cmp.w #2,d0
blt video_chg_end
cmp.w #0xd0,d0 // normale addresse
blt sca_other // nein->
lea MCF_SLT0_SCNT,a0
move.l (a0),d4
move.l d4,_video_sbt // time sichern
sca_other:
lsl.l #8,d0
move.b 0xffff8203,d0 // mid byt
lsl.l #8,d0
move.b 0xffff820d,d0 // low byt
move.l d0,d3
video_chg_1page:
// test ob page schon gesetzt
moveq #20,d4
move.l d0,d2
lsr.l d4,d2 // neue page
move.l _video_tlb,d4
bset.l d2,d4 // setzen als ge<EFBFBD>ndert
bne video_chg_2page // schon gesetzt gewesen? ja->weg
move.l d4,_video_tlb
bsr cpusha // cache leeren
// daten copieren
video_copy_data:
move.l d4,_video_tlb
and.l #0x00f00000,d0
move.l d0,a0
move.l a0,a1
add.l #0x60000000,a1
move.l #0x10000,d4 // die ganze page
video_copy_data_loop:
move.l (a0)+,(a1)+
move.l (a0)+,(a1)+
move.l (a0)+,(a1)+
move.l (a0)+,(a1)+
subq.l #1,d4
bne video_copy_data_loop
// eintrag suchen
move.l d0,MCF_MMU_MMUAR // addresse
move.l #0x106,d4
move.l d4,MCF_MMU_MMUOR // suchen -> schl<EFBFBD>gt neuen vor wenn keiner
nop
move.l MCF_MMU_MMUOR,d4
clr.w d4
swap d4
move.l d4,MCF_MMU_MMUAR
move.l d0,d1
add.l #MCF_MMU_MMUTR_ID(sca_page_ID)|std_mmutr,d0
add.l #0x60000000|wt_mmudr|MCF_MMU_MMUDR_LK,d1
mvz.w #0x10b,d2 // MMU update
move.l d0,MCF_MMU_MMUTR
move.l d1,MCF_MMU_MMUDR
move.l d2,MCF_MMU_MMUOR // setzen vidoe maped to 60xxx only data
nop
video_chg_2page:
// test ob evt. anschliessende page gesetzt werden muss
move.l d3,d0
mvz.w 0xffff8210,d4 // byts pro zeile
mvz.w 0xffff82aa,d2 // zeilen ende
mvz.w 0xffff82a8,d1 // zeilenstart
sub.l d1,d2 // differenz = anzahl zeilen
mulu d2,d4 // maximal 480 zeilen
add.l d4,d0 // video gr<EFBFBD>sse
cmp.l #__STRAM_END,d0 // maximale addresse
bge video_chg_end // wenn gleich oder gr<EFBFBD>sser -> fertig
moveq #20,d4
move.l d0,d2
lsr.l d4,d2 // neue page
move.l _video_tlb,d4
bset.l d2,d4 // setzen als ge<EFBFBD>ndert
beq video_copy_data // nein nochmal
video_chg_end:
// int pending l<EFBFBD>schen
lea MCF_GPT0_GMS,a0
bclr.b #0,3(a0)
nop
bset.b #0,3(a0)
movem.l (a7),d0-d4/a0-a1
lea 28(a7),a7
//--------------------------------------------------------------------------------------------------------
RTE

4158
i2cspi_BaS_gcc/sources/ff.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,111 @@
/*
* flash.c
*
* flashing routines for BaS_gcc
*
* Created on: 19.12.2012
* Author: mfro
* The ACP Firebee project
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2012 M. Froeschle
*/
#include <stdint.h>
void chip_erase(uint8_t *address)
{
* (volatile uint8_t *) (address + 0xaaa) = 0xaa;
* (volatile uint8_t *) (address + 0x555) = 0x55;
* (volatile uint8_t *) (address + 0xaaa) = 0x80;
* (volatile uint8_t *) (address + 0xaaa) = 0xaa;
* (volatile uint8_t *) (address + 0x555) = 0x55;
* (volatile uint8_t *) (address + 0xaaa) = 0x10;
}
void sector_erase(uint8_t *address, uint16_t sector)
{
* (volatile uint8_t *) (address + 0xaaa) = 0xaa;
* (volatile uint8_t *) (address + 0x555) = 0x55;
* (volatile uint8_t *) (address + 0xaaa) = 0x80;
* (volatile uint8_t *) (address + 0xaaa) = 0xaa;
* (volatile uint8_t *) (address + 0x555) = 0x55;
* (volatile uint8_t *) (address + sector) = 0x30;
do {
;
} while (* (volatile uint32_t *) (address + sector) != 0xffffffff);
}
#ifdef _NOT_USED_
* MX28LV640DB.alg
bra lab0x5a
move.w #0xaa,d0
move.w d0,0xaaa(a5)
move.w #0xff,d0
move.w d0,0x554(a5)
move.w #0x20,d0
move.w d0,0xaaa(a5)
lab0x1c:
move.w #0xa0,d0
move.w d0,(a5)
moveq #0,d0
move.w (a3),d0
move.w d0,(a4)
lab0x28:
move.w (a4),d1
andi.l #0xffff,d1
cmp.l d1,d0
bne.s lab0x28
adda.l #2,a3
adda.l #2,a4
cmpa.l a2,a3
blt.s lab0x1c
move.w #0x90,d0
move.w d0,(a5)
move.w #0,d0
move.w d0,(a5)
lab0x50:
nop
nop
halt
nop
bra.s lab0x50
lab0x5a:
move.w #0xaa,d0
move.w d0,0xaaa(a5)
move.w #0x55,d0
move.w d0,0x554(a5)
move.w #0x80,d0
move.w d0,0xaaa(a5)
move.w #0xaa,d0
move.w d0,0xaaa(a5)
move.w #0x55,d0
move.w d0,0x554(a5)
move.w #0x30,d0
move.w d0,(a4)
lab0x88:
move.l (a4),d1
move.l #-1,d0
cmp.l d1,d0
bne.s lab0x88
nop
nop
halt
nop
#endif /* _NOT_USED_ */

View File

@@ -0,0 +1,42 @@
/*
* illegal_instruction.S
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2010 - 2012 F. Aschwanden
* Copyright 2011 - 2012 V. Riviere
* Copyright 2012 M. Froeschle
*/
.global _illegal_instruction
.global _illegal_table_make
#include "startcf.h"
.extern _ii_shift_vec
.extern ewf
/*******************************************************/
.text
ii_error:
nop
halt
nop
nop
_illegal_instruction:
_illegal_table_make:
rts

View File

@@ -0,0 +1,113 @@
/*
* init_fpga.c
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2010 - 2012 F. Aschwanden
* Copyright 2011 - 2012 V. Riviere
* Copyright 2012 M. Froeschle
*
*/
#include <MCF5475.h>
#include "sysinit.h"
#define FPGA_STATUS (1 << 0)
#define FPGA_CLOCK (1 << 1)
#define FPGA_CONFIG (1 << 2)
#define FPGA_DATA0 (1 << 3)
#define FPGA_CONF_DONE (1 << 5)
extern void xprintf_before_copy(const char *fmt, ...);
#define xprintf xprintf_before_copy
#define display_progress display_progress_before_copy
/*
* load FPGA
*/
void init_fpga(void)
{
register uint8_t *fpga_data;
register int i;
xprintf("FPGA load config... ");
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK; /* FPGA clock => low */
MCF_GPIO_PODR_FEC1L &= ~FPGA_CONFIG; /* FPGA config => low */
while ((MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS) && (MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE));
MCF_GPIO_PODR_FEC1L |= FPGA_CONFIG; /* pull FPGA_CONFIG high */
while (!(MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS)); /* wait until status becomes high */
/*
* excerpt from an Altera configuration manual:
*
* The low-to-high transition of nCONFIG on the FPGA begins the configuration cycle. The
* configuration cycle consists of 3 stages<65>reset, configuration, and initialization.
* While nCONFIG is low, the device is in reset. When the device comes out of reset,
* nCONFIG must be at a logic high level in order for the device to release the open-drain
* nSTATUS pin. After nSTATUS is released, it is pulled high by a pull-up resistor and the FPGA
* is ready to receive configuration data. Before and during configuration, all user I/O pins
* are tri-stated. Stratix series, Arria series, and Cyclone series have weak pull-up resistors
* on the I/O pins which are on, before and during configuration.
*
* To begin configuration, nCONFIG and nSTATUS must be at a logic high level. You can delay
* configuration by holding the nCONFIG low. The device receives configuration data on its
* DATA0 pins. Configuration data is latched into the FPGA on the rising edge of DCLK. After
* the FPGA has received all configuration data successfully, it releases the CONF_DONE pin,
* which is pulled high by a pull-up resistor. A low to high transition on CONF_DONE indicates
* configuration is complete and initialization of the device can begin.
*/
fpga_data = (uint8_t *) FPGA_FLASH_DATA;
do
{
uint8_t value = *fpga_data++;
for (i = 0; i < 8; i++, value >>= 1)
{
if (value & 1)
{
/* bit set -> toggle DATA0 to high */
MCF_GPIO_PODR_FEC1L |= FPGA_DATA0;
}
else
{
/* bit is cleared -> toggle DATA0 to low */
MCF_GPIO_PODR_FEC1L &= ~FPGA_DATA0;
}
/* toggle DCLK -> FPGA reads the bit */
MCF_GPIO_PODR_FEC1L |= FPGA_CLOCK;
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK;
}
} while ((!(MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE)) && (fpga_data < (uint8_t *) FPGA_FLASH_DATA_END));
if (fpga_data < (uint8_t *) FPGA_FLASH_DATA_END)
{
while (fpga_data++ < (uint8_t *) FPGA_FLASH_DATA_END)
{
/* toggle a little more since it's fun ;) */
MCF_GPIO_PODR_FEC1L |= FPGA_CLOCK;
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK;
}
xprintf("finished\r\n");
}
else
{
xprintf("FAILED!\r\n");
}
}

View File

@@ -0,0 +1,100 @@
/*----------------------------------------------------------------------*/
/* FatFs sample project for generic microcontrollers (C)ChaN, 2012 */
/*----------------------------------------------------------------------*/
#include <stdio.h>
#include "ff.h"
FATFS Fatfs; /* File system object */
FIL Fil; /* File object */
uint8_t Buff[128]; /* File read buffer */
void die ( /* Stop with dying message */
FRESULT rc /* FatFs return value */
)
{
xprintf("Failed with rc=%u.\n", rc);
for (;;) ;
}
/*-----------------------------------------------------------------------*/
/* Program Main */
/*-----------------------------------------------------------------------*/
int main (void)
{
FRESULT rc; /* Result code */
DIR dir; /* Directory object */
FILINFO fno; /* File information object */
uint32_t bw, br, i;
f_mount(0, &Fatfs); /* Register volume work area (never fails) */
xprintf("\nOpen an existing file (message.txt).\n");
rc = f_open(&Fil, "MESSAGE.TXT", FA_READ);
if (rc) die(rc);
xprintf("\nType the file content.\n");
for (;;) {
rc = f_read(&Fil, Buff, sizeof Buff, &br); /* Read a chunk of file */
if (rc || !br) break; /* Error or end of file */
for (i = 0; i < br; i++) /* Type the data */
putchar(Buff[i]);
}
if (rc) die(rc);
xprintf("\nClose the file.\n");
rc = f_close(&Fil);
if (rc) die(rc);
xprintf("\nCreate a new file (hello.txt).\n");
rc = f_open(&Fil, "HELLO.TXT", FA_WRITE | FA_CREATE_ALWAYS);
if (rc) die(rc);
xprintf("\nWrite a text data. (Hello world!)\n");
rc = f_write(&Fil, "Hello world!\r\n", 14, &bw);
if (rc) die(rc);
xprintf("%u bytes written.\n", bw);
xprintf("\nClose the file.\n");
rc = f_close(&Fil);
if (rc) die(rc);
xprintf("\nOpen root directory.\n");
rc = f_opendir(&dir, "");
if (rc) die(rc);
xprintf("\nDirectory listing...\n");
for (;;) {
rc = f_readdir(&dir, &fno); /* Read a directory item */
if (rc || !fno.fname[0]) break; /* Error or end of dir */
if (fno.fattrib & AM_DIR)
xprintf(" <dir> %s\n", fno.fname);
else
xprintf("%8lu %s\n", fno.fsize, fno.fname);
}
if (rc) die(rc);
xprintf("\nTest completed.\n");
for (;;) ;
}
/*---------------------------------------------------------*/
/* User Provided Timer Function for FatFs module */
/*---------------------------------------------------------*/
uint32_t get_fattime (void)
{
return ((uint32_t)(2012 - 1980) << 25) /* Year = 2012 */
| ((uint32_t)1 << 21) /* Month = 1 */
| ((uint32_t)1 << 16) /* Day_m = 1*/
| ((uint32_t)0 << 11) /* Hour = 0 */
| ((uint32_t)0 << 5) /* Min = 0 */
| ((uint32_t)0 >> 1); /* Sec = 0 */
}

View File

@@ -0,0 +1,652 @@
#include <stdint.h>
#include <bas_types.h>
#include <sd_card.h>
#include <bas_printf.h>
#include <sysinit.h>
#include <wait.h>
#include <MCF5475.h>
/*
* Firebee: MMCv3/SDv1/SDv2 (SPI mode) control module
*
*
* Copyright (C) 2011, ChaN, all right reserved.
*
* This software is a free software and there is NO WARRANTY.
* No restriction on use. You can use, modify and redistribute it for
* personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
* Redistributions of source code must retain the above copyright notice.
*
*/
/* Copyright (C) 2012, mfro, all rights reserved. */
#define CS_HIGH() { dspi_fifo_val &= ~MCF_DSPI_DTFR_CS5; }
#define CS_LOW() { dspi_fifo_val |= MCF_DSPI_DTFR_CS5; }
#define SPICLK_FAST() { MCF_DSPI_DCTAR0 = MCF_DSPI_DCTAR_TRSZ(0b111) | /* transfer size = 8 bit */ \
MCF_DSPI_DCTAR_PCSSCK(0b01) | /* 1 clock DSPICS to DSPISCK delay prescaler */ \
MCF_DSPI_DCTAR_PASC_1CLK | /* 1 clock DSPISCK to DSPICS negation prescaler */ \
MCF_DSPI_DCTAR_PDT_1CLK | /* 1 clock delay between DSPICS assertions prescaler */ \
MCF_DSPI_DCTAR_PBR_3CLK | /* 3 clock Baudrate prescaler */ \
MCF_DSPI_DCTAR_ASC(0b0000) | /* 2 */ \
MCF_DSPI_DCTAR_DT(0b0000) | /* 2 */ \
MCF_DSPI_DCTAR_BR(0b0000); } /* clock / 2 */
#define SPICLK_SLOW() { MCF_DSPI_DCTAR0 = MCF_DSPI_DCTAR_TRSZ(0b111) | /* transfer size = 8 bit */ \
MCF_DSPI_DCTAR_PCSSCK(0b01) | /* 3 clock DSPICS to DSPISCK delay prescaler */ \
MCF_DSPI_DCTAR_PASC_3CLK | /* 3 clock DSPISCK to DSPICS negation prescaler */ \
MCF_DSPI_DCTAR_PDT_3CLK | /* 3 clock delay between DSPICS assertions prescaler */ \
MCF_DSPI_DCTAR_PBR_3CLK | /* 3 clock prescaler */ \
MCF_DSPI_DCTAR_ASC(0b1001) | /* 1024 */ \
MCF_DSPI_DCTAR_DT(0b1001) | /* 1024 */ \
MCF_DSPI_DCTAR_BR(0b0111); }
/*--------------------------------------------------------------------------
Module Private Functions
---------------------------------------------------------------------------*/
#include "diskio.h"
/* MMC/SD command */
#define CMD0 (0) /* GO_IDLE_STATE */
#define CMD1 (1) /* SEND_OP_COND (MMC) */
#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */
#define CMD8 (8) /* SEND_IF_COND */
#define CMD9 (9) /* SEND_CSD */
#define CMD10 (10) /* SEND_CID */
#define CMD12 (12) /* STOP_TRANSMISSION */
#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */
#define CMD16 (16) /* SET_BLOCKLEN */
#define CMD17 (17) /* READ_SINGLE_BLOCK */
#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
#define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */
#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24 (24) /* WRITE_BLOCK */
#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
#define CMD32 (32) /* ERASE_ER_BLK_START */
#define CMD33 (33) /* ERASE_ER_BLK_END */
#define CMD38 (38) /* ERASE */
#define CMD55 (55) /* APP_CMD */
#define CMD58 (58) /* READ_OCR */
static volatile DSTATUS Stat = 0 /* STA_NOINIT */; /* Physical drive status */
static uint8_t CardType; /* Card type flags */
/*-----------------------------------------------------------------------*/
/* Send/Receive data to the MMC (Platform dependent) */
/*-----------------------------------------------------------------------*/
static uint32_t dspi_fifo_val = /* CONT disable continous chip select */
/* CTAS use DCTAR0 for clock and attributes */
MCF_DSPI_DTFR_EOQ | /* current transfer is last in queue */
MCF_DSPI_DTFR_CTCNT;
/* Exchange a byte */
static uint8_t xchg_spi(uint8_t byte)
{
uint32_t fifo = dspi_fifo_val | byte;
uint8_t res;
MCF_DSPI_DTFR = fifo;
while (! (MCF_DSPI_DSR & MCF_DSPI_DSR_TCF)); /* wait until DSPI transfer complete */
MCF_DSPI_DSR = 0xffffffff; /* clear DSPI status register */
fifo = MCF_DSPI_DRFR;
MCF_DSPI_DSR = 0xffffffff;
res = fifo & 0xff;
return res;
}
/* Receive multiple byte
*
* buff: pointer to data buffer
* btr: number of bytes to receive (16, 64 or 512)
*/
static void rcvr_spi_multi(uint8_t *buff, uint32_t count)
{
int i;
for (i = 0; i < count; i++)
*buff++ = xchg_spi(0xff);
}
#if _USE_WRITE
/* Send multiple byte
*
* buff: pointer to data
* btx: number of bytes to send
*/
static void xmit_spi_multi(const uint8_t *buff, uint32_t btx)
{
int i;
for (i = 0; i < btx; i++)
xchg_spi(*buff++);
}
#endif
static bool card_ready(void)
{
uint8_t d;
d = xchg_spi(0xff);
return (d == 0xff);
}
/*
* Wait for card ready
*
* wt: timeout in ms
* returns 1: ready, 0: timeout
*/
static int wait_ready(uint32_t wt)
{
return waitfor(wt, card_ready);
}
/*
* Deselect card and release SPI
*/
static void deselect(void)
{
CS_HIGH();
xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */
}
/*
* Select card and wait for ready
*/
static int select(void) /* 1:OK, 0:Timeout */
{
CS_LOW();
xchg_spi(0xFF); /* Dummy clock (force DO enabled) */
if (wait_ready(5000000))
return 1; /* OK */
deselect();
return 0; /* Timeout */
}
/*
* Control SPI module (Platform dependent)
*/
static void power_on (void) /* Enable SSP module */
{
MCF_PAD_PAR_DSPI = 0x1fff; /* configure all DSPI GPIO pins for DSPI usage */
/*
* FIXME: really necessary or just an oversight
* that PAD_PAR_DSPI is only 16 bit?
*/
// MCF_PAD_PAR_TIMER = 0xff; leave off for now
/*
* initialize DSPI module configuration register
*/
MCF_DSPI_DMCR = MCF_DSPI_DMCR_MSTR | /* FireBee is DSPI master*/
MCF_DSPI_DMCR_CSIS5 | /* CS5 inactive state high */
MCF_DSPI_DMCR_CSIS3 | /* CS3 inactive state high */
MCF_DSPI_DMCR_CSIS2 | /* CS2 inactive state high */
MCF_DSPI_DMCR_DTXF | /* disable transmit FIFO */
MCF_DSPI_DMCR_DRXF | /* disable receive FIFO */
MCF_DSPI_DMCR_CTXF | /* clear transmit FIFO */
MCF_DSPI_DMCR_CRXF; /* clear receive FIFO */
/* initialize DSPI clock and transfer attributes register 0 */
MCF_DSPI_DCTAR0 = MCF_DSPI_DCTAR_TRSZ(0b111) | /* transfer size = 8 bit */
MCF_DSPI_DCTAR_PCSSCK(0b01) | /* 3 clock DSPICS to DSPISCK delay prescaler */
MCF_DSPI_DCTAR_PASC_3CLK | /* 3 clock DSPISCK to DSPICS negation prescaler */
MCF_DSPI_DCTAR_PDT_3CLK | /* 3 clock delay between DSPICS assertions prescaler */
MCF_DSPI_DCTAR_PBR_3CLK | /* 3 clock prescaler */
MCF_DSPI_DCTAR_ASC(0b1001) | /* 1024 */
MCF_DSPI_DCTAR_DT(0b1001) | /* 1024 */
MCF_DSPI_DCTAR_BR(0b0111);
CS_HIGH(); /* Set CS# high */
/* card should now be initialized as MMC */
wait(10 * 1000); /* 10ms */
}
static
void power_off (void) /* Disable SPI function */
{
select(); /* Wait for card ready */
deselect();
}
/*-----------------------------------------------------------------------*/
/* Receive a data packet from the MMC */
/*-----------------------------------------------------------------------*/
static
int rcvr_datablock ( /* 1:OK, 0:Error */
uint8_t *buff, /* Data buffer */
uint32_t btr /* Data block length (byte) */
)
{
uint8_t token;
uint32_t target = MCF_SLT_SCNT(0) - (200 * 1000L * 132);
do { /* Wait for DataStart token in timeout of 200ms */
token = xchg_spi(0xFF);
/* This loop will take a time. Insert rot_rdq() here for multitask envilonment. */
} while ((token == 0xFF) && MCF_SLT_SCNT(0) > target);
if(token != 0xFE) return 0; /* Function fails if invalid DataStart token or timeout */
rcvr_spi_multi(buff, btr); /* Store trailing data to the buffer */
xchg_spi(0xFF); xchg_spi(0xFF); /* Discard CRC */
return 1; /* Function succeeded */
}
/*-----------------------------------------------------------------------*/
/* Send a data packet to the MMC */
/*-----------------------------------------------------------------------*/
#if _USE_WRITE
static
int xmit_datablock ( /* 1:OK, 0:Failed */
const uint8_t *buff, /* Ponter to 512 byte data to be sent */
uint8_t token /* Token */
)
{
uint8_t resp;
if (!wait_ready(500)) return 0; /* Wait for card ready */
xchg_spi(token); /* Send token */
if (token != 0xFD) { /* Send data if token is other than StopTran */
xmit_spi_multi(buff, 512); /* Data */
xchg_spi(0xFF); xchg_spi(0xFF); /* Dummy CRC */
resp = xchg_spi(0xFF); /* Receive data resp */
if ((resp & 0x1F) != 0x05) /* Function fails if the data packet was not accepted */
return 0;
}
return 1;
}
#endif
/*-----------------------------------------------------------------------*/
/* Send a command packet to the MMC */
/*-----------------------------------------------------------------------*/
static uint8_t send_cmd ( /* Return value: R1 resp (bit7==1:Failed to send) */
uint8_t cmd, /* Command index */
uint32_t arg /* Argument */
)
{
uint8_t n, res;
if (cmd & 0x80) { /* Send a CMD55 prior to ACMD<n> */
cmd &= 0x7F;
res = send_cmd(CMD55, 0);
if (res > 1) return res;
}
/* Select card */
deselect();
if (!select()) return 0xFF;
/* Send command packet */
xchg_spi(0x40 | cmd); /* Start + command index */
xchg_spi((uint8_t)(arg >> 24)); /* Argument[31..24] */
xchg_spi((uint8_t)(arg >> 16)); /* Argument[23..16] */
xchg_spi((uint8_t)(arg >> 8)); /* Argument[15..8] */
xchg_spi((uint8_t)arg); /* Argument[7..0] */
n = 0x01; /* Dummy CRC + Stop */
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
xchg_spi(n);
/* Receive command resp */
if (cmd == CMD12) xchg_spi(0xFF); /* Diacard following one byte when CMD12 */
n = 10; /* Wait for response (10 bytes max) */
do
res = xchg_spi(0xFF);
while ((res & 0x80) && --n);
return res; /* Return received response */
}
/*--------------------------------------------------------------------------
Public Functions
---------------------------------------------------------------------------*/
/*
* Initialize disk drive
*
* drv: physical drive number (0)
*/
DSTATUS disk_initialize(uint8_t drv)
{
uint8_t n, cmd, ty, ocr[4];
if (drv) return STA_NOINIT; /* Supports only drive 0 */
power_on(); /* Initialize SPI */
if (Stat & STA_NODISK) return Stat; /* Is card existing in the socket? */
SPICLK_SLOW();
for (n = 10; n; n--) xchg_spi(0xFF); /* Send 80 dummy clocks */
ty = 0;
if (send_cmd(CMD0, 0) == 1) { /* Put the card SPI/Idle state */
uint32_t target = MCF_SLT_SCNT(0) - (1000L * 1000L * 132); /* 1 sec */
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */
for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); /* Get 32 bit return value of R7 resp */
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* Is the card supports vcc of 2.7-3.6V? */
while (MCF_SLT_SCNT(0) > target && send_cmd(ACMD41, 1UL << 30)) ; /* Wait for end of initialization with ACMD41(HCS) */
if (MCF_SLT_SCNT(0) > target && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);
ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* Card id SDv2 */
}
}
} else { /* Not SDv2 card */
if (send_cmd(ACMD41, 0) <= 1) { /* SDv1 or MMC? */
ty = CT_SD1; cmd = ACMD41; /* SDv1 (ACMD41(0)) */
} else {
ty = CT_MMC; cmd = CMD1; /* MMCv3 (CMD1(0)) */
}
while (MCF_SLT_SCNT(0) > target && send_cmd(cmd, 0)) ; /* Wait for end of initialization */
if (!MCF_SLT_SCNT(0) > target || send_cmd(CMD16, 512) != 0) /* Set block length: 512 */
ty = 0;
}
}
CardType = ty; /* Card type */
deselect();
if (ty) { /* OK */
SPICLK_FAST(); /* Set fast clock */
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT flag */
} else { /* Failed */
power_off();
Stat = STA_NOINIT;
}
return Stat;
}
/*-----------------------------------------------------------------------*/
/* Get disk status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
uint8_t drv /* Physical drive number (0) */
)
{
if (drv) return STA_NOINIT; /* Supports only drive 0 */
return Stat; /* Return disk status */
}
/*-----------------------------------------------------------------------*/
/* Read sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
uint8_t drv, /* Physical drive number (0) */
uint8_t *buff, /* Pointer to the data buffer to store read data */
uint32_t sector, /* Start sector number (LBA) */
uint8_t count /* Number of sectors to read (1..128) */
)
{
if (drv || !count) return RES_PARERR; /* Check parameter */
if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */
if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA ot BA conversion (byte addressing cards) */
if (count == 1) { /* Single sector read */
if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
&& rcvr_datablock(buff, 512))
count = 0;
}
else { /* Multiple sector read */
if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
do {
if (!rcvr_datablock(buff, 512)) break;
buff += 512;
} while (--count);
send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
}
}
deselect();
return count ? RES_ERROR : RES_OK; /* Return result */
}
/*-----------------------------------------------------------------------*/
/* Write sector(s) */
/*-----------------------------------------------------------------------*/
#if _USE_WRITE
DRESULT disk_write (
uint8_t drv, /* Physical drive number (0) */
const uint8_t *buff, /* Ponter to the data to write */
uint32_t sector, /* Start sector number (LBA) */
uint8_t count /* Number of sectors to write (1..128) */
)
{
if (drv || !count) return RES_PARERR; /* Check parameter */
if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check drive status */
if (Stat & STA_PROTECT) return RES_WRPRT; /* Check write protect */
if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA ==> BA conversion (byte addressing cards) */
if (count == 1) { /* Single sector write */
if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
&& xmit_datablock(buff, 0xFE))
count = 0;
}
else { /* Multiple sector write */
if (CardType & CT_SDC) send_cmd(ACMD23, count); /* Predefine number of sectors */
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
do {
if (!xmit_datablock(buff, 0xFC)) break;
buff += 512;
} while (--count);
if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
count = 1;
}
}
deselect();
return count ? RES_ERROR : RES_OK; /* Return result */
}
#endif
/*-----------------------------------------------------------------------*/
/* Miscellaneous drive controls other than data read/write */
/*-----------------------------------------------------------------------*/
#if _USE_IOCTL
DRESULT disk_ioctl (
uint8_t drv, /* Physical drive number (0) */
uint8_t ctrl, /* Control command code */
void *buff /* Pointer to the conrtol data */
)
{
DRESULT res;
uint8_t n, csd[16], *ptr = buff;
uint32_t *dp, st, ed, csize;
if (drv) return RES_PARERR; /* Check parameter */
if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */
res = RES_ERROR;
switch (ctrl) {
case CTRL_SYNC : /* Wait for end of internal write process of the drive */
if (select()) {
deselect();
res = RES_OK;
}
break;
case GET_SECTOR_COUNT : /* Get drive capacity in unit of sector (DWORD) */
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
csize = csd[9] + ((uint16_t)csd[8] << 8) + ((uint32_t)(csd[7] & 63) << 16) + 1;
*(uint32_t*)buff = csize << 10;
} else { /* SDC ver 1.XX or MMC ver 3 */
n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
csize = (csd[8] >> 6) + ((uint16_t)csd[7] << 2) + ((uint16_t)(csd[6] & 3) << 10) + 1;
*(uint32_t*)buff = csize << (n - 9);
}
res = RES_OK;
}
break;
case GET_SECTOR_SIZE : /* Get sector size in unit of byte (WORD) */
*(uint16_t*)buff = 512;
res = RES_OK;
break;
case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */
if (CardType & CT_SD2) { /* SDC ver 2.00 */
if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */
xchg_spi(0xFF);
if (rcvr_datablock(csd, 16)) { /* Read partial block */
for (n = 64 - 16; n; n--) xchg_spi(0xFF); /* Purge trailing data */
*(uint32_t*)buff = 16UL << (csd[10] >> 4);
res = RES_OK;
}
}
} else { /* SDC ver 1.XX or MMC */
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */
if (CardType & CT_SD1) { /* SDC ver 1.XX */
*(uint32_t*)buff = (((csd[10] & 63) << 1) + ((uint16_t)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
} else { /* MMC */
*(uint32_t*)buff = ((uint16_t)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
}
res = RES_OK;
}
}
break;
case CTRL_ERASE_SECTOR : /* Erase a block of sectors (used when _USE_ERASE == 1) */
if (!(CardType & CT_SDC)) break; /* Check if the card is SDC */
if (disk_ioctl(drv, MMC_GET_CSD, csd)) break; /* Get CSD */
if (!(csd[0] >> 6) && !(csd[10] & 0x40)) break; /* Check if sector erase can be applied to the card */
dp = buff; st = dp[0]; ed = dp[1]; /* Load sector block */
if (!(CardType & CT_BLOCK)) {
st *= 512; ed *= 512;
}
if (send_cmd(CMD32, st) == 0 && send_cmd(CMD33, ed) == 0 && send_cmd(CMD38, 0) == 0 && wait_ready(30000)) /* Erase sector block */
res = RES_OK; /* FatFs does not check result of this command */
break;
/* Following command are not used by FatFs module */
case MMC_GET_TYPE : /* Get MMC/SDC type (BYTE) */
*ptr = CardType;
res = RES_OK;
break;
case MMC_GET_CSD : /* Read CSD (16 bytes) */
if (send_cmd(CMD9, 0) == 0 /* READ_CSD */
&& rcvr_datablock(ptr, 16))
res = RES_OK;
break;
case MMC_GET_CID : /* Read CID (16 bytes) */
if (send_cmd(CMD10, 0) == 0 /* READ_CID */
&& rcvr_datablock(ptr, 16))
res = RES_OK;
break;
case MMC_GET_OCR : /* Read OCR (4 bytes) */
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
for (n = 4; n; n--) *ptr++ = xchg_spi(0xFF);
res = RES_OK;
}
break;
case MMC_GET_SDSTAT : /* Read SD status (64 bytes) */
if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
xchg_spi(0xFF);
if (rcvr_datablock(ptr, 64))
res = RES_OK;
}
break;
default:
res = RES_PARERR;
break;
}
deselect();
return res;
}
#endif
/*-----------------------------------------------------------------------*/
/* Device timer function */
/*-----------------------------------------------------------------------*/
/* This function must be called from timer interrupt routine in period
/ of 1 ms to generate card control timing.
*/
#ifdef _NOT_USED_
void disk_timerproc (void)
{
uint8_t s;
s = Stat;
if (WP) /* Write protected */
s |= STA_PROTECT;
else /* Write enabled */
s &= ~STA_PROTECT;
//if (INS) /* Card is in socket */
s &= ~STA_NODISK;
//else /* Socket empty */
// s |= (STA_NODISK | STA_NOINIT);
Stat = s;
}
#endif /* _NOT_USED_ */

View File

@@ -0,0 +1,195 @@
/*
* INIT ACR and MMU
*/
#include "startcf.h"
.extern _rt_vbr
.extern _rt_cacr
.extern _rt_asid
.extern _rt_acr0
.extern _rt_acr1
.extern _rt_acr2
.extern _rt_acr3
.extern _rt_mmubar
.extern ___MMUBAR
.extern cpusha
.extern _video_tlb
.extern _video_sbt
.extern __TOS
/* Register read/write macros */
#define MCF_MMU_MMUCR __MMUBAR
#define MCF_MMU_MMUOR __MMUBAR+0x04
#define MCF_MMU_MMUSR __MMUBAR+0x08
#define MCF_MMU_MMUAR __MMUBAR+0x10
#define MCF_MMU_MMUTR __MMUBAR+0x14
#define MCF_MMU_MMUDR __MMUBAR+0x18
/* Bit definitions and macros for MCF_MMU_MMUCR */
#define MCF_MMU_MMUCR_EN (0x1)
#define MCF_MMU_MMUCR_ASM (0x2)
/* Bit definitions and macros for MCF_MMU_MMUOR */
#define MCF_MMU_MMUOR_UAA (0x1)
#define MCF_MMU_MMUOR_ACC (0x2)
#define MCF_MMU_MMUOR_RW (0x4)
#define MCF_MMU_MMUOR_ADR (0x8)
#define MCF_MMU_MMUOR_ITLB (0x10)
#define MCF_MMU_MMUOR_CAS (0x20)
#define MCF_MMU_MMUOR_CNL (0x40)
#define MCF_MMU_MMUOR_CA (0x80)
#define MCF_MMU_MMUOR_STLB (0x100)
#define MCF_MMU_MMUOR_AA(x) (((x)&0xFFFF)<<0x10)
/* Bit definitions and macros for MCF_MMU_MMUSR */
#define MCF_MMU_MMUSR_HIT (0x2)
#define MCF_MMU_MMUSR_WF (0x8)
#define MCF_MMU_MMUSR_RF (0x10)
#define MCF_MMU_MMUSR_SPF (0x20)
/* Bit definitions and macros for MCF_MMU_MMUAR */
#define MCF_MMU_MMUAR_FA(x) (((x)&0xFFFFFFFF)<<0)
/* Bit definitions and macros for MCF_MMU_MMUTR */
#define MCF_MMU_MMUTR_V (0x1)
#define MCF_MMU_MMUTR_SG (0x2)
#define MCF_MMU_MMUTR_ID(x) (((x)&0xFF)<<0x2)
#define MCF_MMU_MMUTR_VA(x) (((x)&0x3FFFFF)<<0xA)
/* Bit definitions and macros for MCF_MMU_MMUDR */
#define MCF_MMU_MMUDR_LK (0x2)
#define MCF_MMU_MMUDR_X (0x4)
#define MCF_MMU_MMUDR_W (0x8)
#define MCF_MMU_MMUDR_R (0x10)
#define MCF_MMU_MMUDR_SP (0x20)
#define MCF_MMU_MMUDR_CM(x) (((x)&0x3)<<0x6)
#define MCF_MMU_MMUDR_SZ(x) (((x)&0x3)<<0x8)
#define MCF_MMU_MMUDR_PA(x) (((x)&0x3FFFFF)<<0xA)
#define std_mmutr (MCF_MMU_MMUTR_SG|MCF_MMU_MMUTR_V)
#define mmuord_d ( MCF_MMU_MMUOR_ACC|MCF_MMU_MMUOR_UAA)
#define mmuord_i (MCF_MMU_MMUOR_ITLB|MCF_MMU_MMUOR_ACC|MCF_MMU_MMUOR_UAA)
#define wt_mmudr (MCF_MMU_MMUDR_SZ(00)|MCF_MMU_MMUDR_CM(00)|MCF_MMU_MMUDR_R|MCF_MMU_MMUDR_W|MCF_MMU_MMUDR_X)
#define cb_mmudr (MCF_MMU_MMUDR_SZ(00)|MCF_MMU_MMUDR_CM(01)|MCF_MMU_MMUDR_R|MCF_MMU_MMUDR_W|MCF_MMU_MMUDR_X)
#define nc_mmudr (MCF_MMU_MMUDR_SZ(00)|MCF_MMU_MMUDR_CM(10)|MCF_MMU_MMUDR_R|MCF_MMU_MMUDR_W|MCF_MMU_MMUDR_X)
.global _mmu_init
.global _mmutr_miss
.text
_mmu_init:
move.l d3,-(sp) // Backup registers
move.l d2,-(sp)
clr.l d0
movec d0,ASID // ASID allways 0
move.l d0,_rt_asid // sichern
move.l #0xC03FC040,d0 // data r/w precise c000'0000-ffff'ffff
movec d0,ACR0
move.l d0,_rt_acr0 // sichern
move.l #0x601FC000,d0 // data r/w wt 6000'0000-7fff'ffff
movec d0,ACR1
move.l d0,_rt_acr1 // sichern
move.l #0xe007C400,d0 // instruction r wt e000'0000-e07f'ffff
movec d0,ACR2
move.l d0,_rt_acr2 // sichern
clr.l d0 // acr3 aus
movec d0,ACR3
move.l d0,_rt_acr3 // sichern
move.l #__MMUBAR+1,d0
movec d0,MMUBAR //mmubar setzen
move.l d0,_rt_mmubar // sichern
nop
move.l #MCF_MMU_MMUOR_CA,d0 // clear all entries,
move.l d0,MCF_MMU_MMUOR
nop
// 0000'0000 locked
moveq.l #0x00000000|std_mmutr,d0
moveq.l #0x00000000|cb_mmudr|MCF_MMU_MMUDR_LK,d1
moveq.l #mmuord_d,d2 // MMU update date
moveq.l #mmuord_i,d3 // MMU update instruction
move.l d0,MCF_MMU_MMUTR
move.l d1,MCF_MMU_MMUDR
move.l d2,MCF_MMU_MMUOR // MMU update date
move.l d3,MCF_MMU_MMUOR // MMU update instruction
//---------------------------------------------------------------------------------------
// 00d0'0000 locked ID=6
// video ram: read write execute normal write true
move.l #0x00d00000|MCF_MMU_MMUTR_ID(sca_page_ID)|std_mmutr,d0
move.l #0x60d00000|wt_mmudr|MCF_MMU_MMUDR_LK,d1
move.l d0,MCF_MMU_MMUTR
move.l d1,MCF_MMU_MMUDR
move.l d2,MCF_MMU_MMUOR // MMU update date
move.l #0x00d00000|std_mmutr,d0
move.l d3,MCF_MMU_MMUOR // MMU update instruction
move.l #0x2000,d0
move.l d0,_video_tlb // set page as video page
clr.l _video_sbt // clear time
//-------------------------------------------------------------------------------------
// Make the TOS (in SDRAM) read-only
move.l #__TOS+std_mmutr,d0
move.l #__TOS+cb_mmudr+MCF_MMU_MMUDR_LK,d1
move.l d0,MCF_MMU_MMUTR
move.l d1,MCF_MMU_MMUDR
move.l d2,MCF_MMU_MMUOR // setzen read only ?????? noch nicht
move.l d3,MCF_MMU_MMUOR // setzen
// 00f0'0000 locked
move.l #0x00f00000|std_mmutr,d0
move.l #0xfff00000|nc_mmudr|MCF_MMU_MMUDR_LK,d1
move.l d0,MCF_MMU_MMUTR
move.l d1,MCF_MMU_MMUDR
move.l d2,MCF_MMU_MMUOR // maped to ffffxxx, precise,
move.l d3,MCF_MMU_MMUOR // maped to ffffxxx, precise,
// 1fe0'0000 locked
move.l #0x1FE00000|std_mmutr,d0
move.l #0x1FE00000|cb_mmudr|MCF_MMU_MMUDR_LK,d1
move.l d0,MCF_MMU_MMUTR
move.l d1,MCF_MMU_MMUDR
move.l d2,MCF_MMU_MMUOR // setzen data
move.l d3,MCF_MMU_MMUOR // setzen instr
// 1ff0'0000 locked
move.l #0x1FF00000|std_mmutr,d0
move.l #0x1FF00000|cb_mmudr|MCF_MMU_MMUDR_LK,d1
move.l d0,MCF_MMU_MMUTR
move.l d1,MCF_MMU_MMUDR
move.l d2,MCF_MMU_MMUOR // setzen data
move.l d3,MCF_MMU_MMUOR // setzen instr
// instr 0xFFF0'0000 nach 0x1FF0'0000 umleiten -->> short sprung
/* move.l #0xFFF00000|std_mmutr,d0
move.l #0x1FF00000|cb_mmudr|MCF_MMU_MMUDR_LK,d1
move.l d0,MCF_MMU_MMUTR
move.l d1,MCF_MMU_MMUDR
move.l d3,MCF_MMU_MMUOR // setzen instr
*/
move.l (sp)+,d2 // Restore registers
move.l (sp)+,d3
rts
/*
* MMU table search
*/
_mmutr_miss:
bsr cpusha
and.l #0xFFF00000,d0
or.l #std_mmutr,d0
move.l d0,MCF_MMU_MMUTR
and.l #0xFFF00000,d0
or.l #cb_mmudr,d0
move.l d0,MCF_MMU_MMUDR
moveq.l #mmuord_d,d0 // MMU update data
move.l d0,MCF_MMU_MMUOR // setzen
moveq.l #mmuord_i,d0 // MMU update instruction
move.l d0,MCF_MMU_MMUOR // setzen
move.l (sp)+,d0
rte

View File

@@ -0,0 +1,36 @@
/*
* printf_helper.S
*
* assembler trampoline to let printf (compiled -mpcrel) indirectly reference __MBAR
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2010 - 2012 F. Aschwanden
* Copyright 2011 - 2012 V. Riviere
* Copyright 2012 M. Froeschle
*/
.global printf_helper
printf_helper:
.extern __MBAR
.wait_txready:
move.w __MBAR+0x8604,d2 // PSCSCR0 status register
btst #10,d2 // space left in TX fifo?
beq.s .wait_txready // no, loop
lea __MBAR+0x860C,a0 // PSCSTB0 transmitter buffer register
move.b d0,(a0) // send byte
rts

View File

@@ -0,0 +1,424 @@
/*
* s19reader.c
*
* Created on: 17.12.2012
* Author: mfro
* The ACP Firebee project
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2012 M. Froeschle
*/
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "bas_printf.h"
#include "sd_card.h"
#include "diskio.h"
#include "ff.h"
#include "s19reader.h"
#include "cache.h"
/*
* Yes, I know. The following doesn't really look like code should look like...
*
* I did try to map structures over the S-records with (packed) which didn't work reliably due to gcc _not_ packing them appropiate
* and finally ended up with this. Not nice, put paid (and working).
*
*/
#define SREC_TYPE(a) (a)[0] /* type of record */
#define SREC_COUNT(a) (a)[1] /* length of valid bytes to follow */
#define SREC_ADDR16(a) (256 * (a)[2] + (a)[3]) /* 2 byte address field */
#define SREC_ADDR24(a) (0x10000 * (a)[2] + 0x100 * \
(a)[3] + (a)[4]) /* 3 byte address field */
#define SREC_ADDR32(a) (0x1000000 * a[2] + 0x10000 * \
a[3] + 0x100 * (a)[4] + (a)[5]) /* 4 byte address field */
#define SREC_DATA16(a) ((uint8_t *)&((a)[4])) /* address of first byte of data in a record */
#define SREC_DATA24(a) ((uint8_t *)&((a)[5])) /* address of first data byte in 24 bit record */
#define SREC_DATA32(a) ((uint8_t *)&((a)[6])) /* adress of first byte of a record with 32 bit address field */
#define SREC_DATA16_SIZE(a) (SREC_COUNT((a)) - 3) /* length of the data[] array without the checksum field */
#define SREC_DATA24_SIZE(a) (SREC_COUNT((a)) - 4) /* length of the data[] array without the checksum field */
#define SREC_DATA32_SIZE(a) (SREC_COUNT((a)) - 5) /* length of the data[] array without the checksum field */
#define SREC_CHECKSUM(a) (a)[SREC_COUNT(a) + 2 - 1] /* record's checksum (two's complement of the sum of all bytes) */
/*
* convert a single hex character into byte
*/
static uint8_t nibble_to_byte(uint8_t nibble)
{
if ((nibble >= '0') && (nibble <= '9'))
return nibble - '0';
else if ((nibble >= 'A' && nibble <= 'F'))
return 10 + nibble - 'A';
else if ((nibble >= 'a' && nibble <= 'f'))
return 10 + nibble - 'a';
return 0;
}
/*
* convert two hex characters into byte
*/
static uint8_t hex_to_byte(uint8_t hex[2])
{
return 16 * (nibble_to_byte(hex[0])) + (nibble_to_byte(hex[1]));
}
/*
* convert four hex characters into a 16 bit word
*/
static uint16_t hex_to_word(uint8_t hex[4])
{
return 256 * hex_to_byte(&hex[0]) + hex_to_byte(&hex[2]);
}
/*
* convert eight hex characters into a 32 bit word
*/
static uint32_t hex_to_long(uint8_t hex[8])
{
return 65536 * hex_to_word(&hex[0]) + hex_to_word(&hex[4]);
}
/*
* compute the record checksum
*
* it consists of the one's complement of the byte sum of the data from the count field until the end
*/
static uint8_t checksum(uint8_t arr[])
{
int i;
uint8_t checksum = SREC_COUNT(arr);
for (i = 0; i < SREC_COUNT(arr) - 1; i++)
{
checksum += arr[i + 2];
}
return ~checksum;
}
#ifdef _NOT_USED_
void print_record(uint8_t *arr)
{
switch (SREC_TYPE(arr))
{
case 0:
{
xprintf("type 0x%x ", SREC_TYPE(arr));
xprintf("count 0x%x ", SREC_COUNT(arr));
xprintf("addr 0x%x ", SREC_ADDR16(arr));
xprintf("module %11.11s ", SREC_DATA16(arr));
xprintf("chk 0x%x 0x%x\r\n", SREC_CHECKSUM(arr), checksum(arr));
}
break;
case 3:
case 7:
{
xprintf("type 0x%x ", SREC_TYPE(arr));
xprintf("count 0x%x ", SREC_COUNT(arr));
xprintf("addr 0x%x ", SREC_ADDR32(arr));
xprintf("data %02x,%02x,%02x,%02x,... ",
SREC_DATA32(arr)[0], SREC_DATA32(arr)[1], SREC_DATA32(arr)[3], SREC_DATA32(arr)[4]);
xprintf("chk 0x%x 0x%x\r\n", SREC_CHECKSUM(arr), checksum(arr));
}
break;
default:
xprintf("unsupported report type %d in print_record\r\n", arr[0]);
break;
}
}
#endif /* _NOT_USED_ */
/*
* convert an S-record line into its corresponding byte vector (ASCII->binary)
*/
static void line_to_vector(uint8_t *buff, uint8_t *vector)
{
int i;
int length;
uint8_t *vp = vector;
length = hex_to_byte(buff + 2);
buff++;
*vp++ = nibble_to_byte(*buff); /* record type. Only one single nibble */
buff++;
for (i = 0; i <= length; i++)
{
*vp++ = hex_to_byte(buff);
buff += 2;
}
}
/*
* read and parse a Motorola S-record file and copy contents to dst. The theory of operation is to read and parse the S-record file
* and to use the supplied callback routine to copy the buffer to the destination once the S-record line is converted.
* The memcpy callback can be anything (as long as it conforms parameter-wise) - a basically empty function to just let
* read_srecords validate the file, a standard memcpy() to copy file contents to destination RAM or a more sophisticated
* routine that does write/erase flash
*
* FIXME: Currently only records that the gcc toolchain emits are supported.
*
* Parameters:
* IN
* filename - the filename that contains the S-records
* callback - the memcpy() routine discussed above
* OUT
* start_address - the execution address of the code as read from the file. Can be used to jump into and execute it
* actual_length - the overall length of the binary code read from the file
* returns
* OK or an err_t error code if anything failed
*/
err_t read_srecords(char *filename, void **start_address, uint32_t *actual_length, memcpy_callback_t callback)
{
FRESULT fres;
FIL file;
err_t ret = OK;
if ((fres = f_open(&file, filename, FA_READ) == FR_OK))
{
uint8_t line[80];
int lineno = 0;
int data_records = 0;
bool found_block_header = false;
bool found_block_end = false;
bool found_block_data = false;
while (ret == OK && (uint8_t *) f_gets((char *) line, sizeof(line), &file) != NULL)
{
lineno++;
uint8_t vector[80];
line_to_vector(line, vector); /* vector now contains the decoded contents of line, from line[1] on */
if (line[0] == 'S')
{
if (SREC_CHECKSUM(vector) != checksum(vector))
{
xprintf("invalid checksum 0x%x (should be 0x%x) in line %d\r\n",
SREC_CHECKSUM(vector), checksum(vector), lineno);
ret = FAIL;
}
switch (vector[0])
{
case 0: /* block header */
found_block_header = true;
if (found_block_data || found_block_end)
{
xprintf("S7 or S3 record found before S0: S-records corrupt?\r\n");
ret = FAIL;
}
break;
case 2: /* three byte address field data record */
if (!found_block_header || found_block_end)
{
xprintf("S3 record found before S0 or after S7: S-records corrupt?\r\n");
ret = FAIL;
}
ret = callback((uint8_t *) SREC_ADDR24(vector), SREC_DATA24(vector), SREC_DATA24_SIZE(vector));
data_records++;
break;
case 3: /* four byte address field data record */
if (!found_block_header || found_block_end)
{
xprintf("S3 record found before S0 or after S7: S-records corrupt?\r\n");
ret = FAIL;
}
ret = callback((uint8_t *) SREC_ADDR32(vector), SREC_DATA32(vector), SREC_DATA32_SIZE(vector));
data_records++;
break;
case 7: /* four byte address field end record */
if (!found_block_header || found_block_end)
{
xprintf("S7 record found before S0 or after S7: S-records corrupt?\r\n");
}
else
{
// xprintf("S7 record (end) found after %d valid data blocks\r\n", data_records);
*start_address = (void *) SREC_ADDR32(vector);
}
break;
case 8: /* three byte address field end record */
if (!found_block_header || found_block_end)
{
xprintf("S8 record found before S0 or after S8: S-records corrupt?\r\n");
}
else
{
// xprintf("S7 record (end) found after %d valid data blocks\r\n", data_records);
*start_address = (void *) SREC_ADDR24(vector);
}
break;
default:
xprintf("unsupported record type (%d) found in line %d\r\n", vector[0], lineno);
xprintf("offending line: \r\n");
xprintf("%s\r\n", line);
ret = FAIL;
break;
}
}
else
{
xprintf("illegal character ('%c') found on line %d: S-records corrupt?\r\n", line[0], lineno);
ret = FAIL;
break;
}
}
f_close(&file);
}
else
{
xprintf("could not open file %s\r\n", filename);
ret = FILE_OPEN;
}
return ret;
}
/*
* this callback just does nothing besides returning OK. Meant to do a dry run over the file to check its integrity
*/
static err_t simulate()
{
err_t ret = OK;
return ret;
}
static err_t memcpy(uint8_t *dst, uint8_t *src, uint32_t length)
{
uint8_t *end = src + length;
do
{
*dst++ = *src++;
} while (src < end);
return OK;
}
static err_t flash(uint8_t *dst, uint8_t *src, uint32_t length)
{
err_t ret = OK;
/* TODO: do the actual flash */
return ret;
}
/*
* this callback verifies the data against the S-record file contents after a write to destination
*/
static err_t verify(uint8_t *dst, uint8_t *src, uint32_t length)
{
uint8_t *end = src + length;
do
{
if (*src++ != *dst++)
return FAIL;
} while (src < end);
return OK;
}
void srec_execute(char *flasher_filename)
{
DRESULT res;
FRESULT fres;
FATFS fs;
FIL file;
err_t err;
void *start_address;
uint32_t length;
disk_initialize(0);
res = disk_status(0);
if (res == RES_OK)
{
fres = f_mount(0, &fs);
if (fres == FR_OK)
{
if ((fres = f_open(&file, flasher_filename, FA_READ) != FR_OK))
{
xprintf("flasher file %s not present on disk\r\n", flasher_filename);
}
else
{
f_close(&file);
/* first pass: parse and check for inconsistencies */
xprintf("check file integrity: ");
err = read_srecords(flasher_filename, &start_address, &length, simulate);
if (err == OK)
{
/* next pass: copy data to destination */
xprintf("OK.\r\ncopy/flash data: ");
err = read_srecords(flasher_filename, &start_address, &length, memcpy);
if (err == OK)
{
/* next pass: verify data */
xprintf("OK.\r\nverify data: ");
err = read_srecords(flasher_filename, &start_address, &length, verify);
if (err == OK)
{
xprintf("OK.\r\n");
typedef void void_func(void);
void_func *func;
xprintf("target successfully written and verified. Start address: %p\r\n", start_address);
func = start_address;
flush_and_invalidate_caches();
(*func)();
}
else
{
xprintf("failed\r\n");
}
}
else
{
xprintf("failed\r\n");
}
}
else
{
xprintf("failed\r\n");
}
}
}
else
{
// xprintf("could not mount FAT FS\r\n");
}
f_mount(0, NULL);
}
else
{
// xprintf("could not initialize SD card\r\n");
}
}

View File

@@ -0,0 +1,121 @@
/*
* sd_card.c
*
* Created on: 16.12.2012
* Author: mfro
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2012 M. Froeschle
*/
#include <sd_card.h>
#include <diskio.h>
#include <ff.h>
#include <bas_printf.h>
#define WELCOME_NAME "WELCOME.MSG"
#define FLASHCODE_NAME "BENCH.BIN"
#define FLASHCODE_ADDRESS 0x03000000L
/*
* initialize SD-card and FF FAT filesystem routines. Harness to load a file during boot.
*
* This is currently more like a proof of concept,
* but will be extended to load and execute a bootstrap flasher to be able to flash the Bee directly
* from card.
*/
void sd_card_init(void)
{
DRESULT res;
FATFS fs;
FRESULT fres;
disk_initialize(0);
res = disk_status(0);
xprintf("disk status of SD card is %d\r\n", res);
if (res == RES_OK)
{
fres = f_mount(0, &fs);
xprintf("mount status of SD card fs is %d\r\n", fres);
if (fres == FR_OK)
{
DIR directory;
FIL file;
fres = f_opendir(&directory, "\\");
if (fres == FR_OK)
{
FILINFO fi;
while (((fres = f_readdir(&directory, &fi)) == FR_OK) && fi.fname[0])
{
xprintf("%13.13s %d\r\n", fi.fname, fi.fsize);
}
}
else
{
xprintf("could not open directory \"\\\" on SD-card! Error code: %d\r\n", fres);
}
/*
* let's see if we find our boot flashing executable on disk
*/
fres = f_open(&file, FLASHCODE_NAME, FA_READ);
if (fres == FR_OK)
{
/*
* yes, load and execute it
*
* FIXME: we will need some kind of user confirmation here
* to avoid unwanted flashing or "bootsector viruses" before going productive
*/
uint32_t size; /* length of code piece read */
uint32_t total_size = 0L;
uint32_t start_time = MCF_SLT_SCNT(0);
uint32_t end_time;
uint32_t time = 0;
while ((fres = f_read(&file, (void *) FLASHCODE_ADDRESS, 1024 * 1000, &size)) == FR_OK && size > 0)
{
total_size += size / 1024;
xprintf("read hunk of %d bytes, total_size = %d kBytes\r\n", size, total_size);
}
end_time = MCF_SLT_SCNT(0);
time = (end_time - start_time) / 132L;
xprintf("result of f_read: %ld, %ld kbytes read\r\n", fres, total_size);
xprintf("time to load %s: %ld s\r\n", FLASHCODE_NAME, time / 1000 / 100);
xprintf("equals to about %ld kBytes/second\r\n", total_size / (time / 1000 / 100));
}
f_close(&file);
fres = f_open(&file, WELCOME_NAME, FA_READ);
if (fres == FR_OK)
{
char line[128];
while (f_gets(line, sizeof(line), &file))
{
xprintf("%s", line);
}
}
f_close(&file);
}
f_mount(0, 0L); /* release work area */
}
}

View File

@@ -0,0 +1,63 @@
/* This object file must be the first to be linked,
* so it will be placed at the very beginning of the ROM.
*/
.equ MCF_MMU_MMUCR, __MMUBAR + 0
.global _rom_header
.global _rom_entry
.extern _initialize_hardware
.extern _rt_mbar
/* ROM header */
_rom_header:
/* The first long is supposed to be the initial SP.
* We replace it by bra.s to allow running the ROM from the first byte.
* Then we add a fake jmp instruction for pretty disassembly.
*/
bra.s _rom_entry // Short jump to the real entry point
.short 0x4ef9 // Fake jmp instruction
/* The second long is the initial PC */
.long _rom_entry // Real entry point
/* ROM entry point */
_rom_entry:
/* disable interrupts */
move.w #0x2700,SR
/* Initialize MBAR */
move.l #__MBAR,d0
movec d0,MBAR
move.l d0,_rt_mbar
/* mmu off */
move.l #__MMUBAR+1,d0
movec d0,MMUBAR
clr.l d0
move.l d0,MCF_MMU_MMUCR
/* Initialize RAMBARs: locate SRAM and validate it */
move.l #__RAMBAR0 + 0x7,d0 /* supervisor only */
movec d0,RAMBAR0
move.l #__RAMBAR1 + 0x1,d0
movec d0,RAMBAR1
/* set stack pointer to end of SRAM1 */
lea __SUP_SP,a7
move.l #0,(sp)
/* Initialize the processor caches.
* The instruction cache is fully enabled.
* The data cache is enabled, but cache-inhibited by default.
* Later, the MMU will fully activate the data cache for specific areas.
* It is important to enable both caches now, otherwise cpushl would hang.
*/
move.l #0xa50c8120,d0
movec d0,cacr
andi.l #0xfefbfeff,d0 // Clear invalidate bits
move.l d0,_rt_cacr
/* initialize any hardware specific issues */
bra _initialize_hardware

View File

@@ -0,0 +1,565 @@
/*
* user/supervisor handler
*/
#include "startcf.h"
#define cf_stack
.extern _rt_cacr;
.extern _rt_mod;
.extern _rt_ssp;
.extern _rt_usp;
.extern ___MMUBAR
.extern _flush_and_invalidate_caches
/* Register read/write macros */
#define MCF_MMU_MMUCR __MMUBAR
#define MCF_MMU_MMUOR __MMUBAR+0x04
#define MCF_MMU_MMUSR __MMUBAR+0x08
#define MCF_MMU_MMUAR __MMUBAR+0x10
#define MCF_MMU_MMUTR __MMUBAR+0x14
#define MCF_MMU_MMUDR __MMUBAR+0x18
.global _privileg_violation
.global cpusha
.text
_privileg_violation:
move.w #0x2700,sr
lea -12(a7),a7
movem.l d0/a0/a5,(a7)
#ifndef cf_stack
lea 0x52f0,a0
move.l #0x20,(a0) // set auf 68030
#endif
lea _rt_mod,a0 // zugriff setzen
tst.b (a0) // vom rt_supervisormodus?
bne pv_work // ja->
// tats<EFBFBD>chlich privileg violation
mov3q.l #-1,(a0) // sr_mod setzen
move.l usp,a5 // usp holen
move.l a5,8(a0) // sichern
move.l 4(a0),a5 // rt_ssp holen
#ifdef cf_stack
move.l 16(a7),-(a5) // pc verschieben
move.l 12(a7),-(a5) // sr verschieben
bset #5,2(a5) // auf super setzen
#else
move.w 12(a7),-(a5) // vector nr.
move.l 16(a7),-(a5) // pc verschieben
move.w 14(a7),-(a5) // sr verschieben
bset #5,(a5) // auf super
#endif
move.l a5,usp
move.l 12(a0),a5 // rt_vbr
lea 0x18(a5),a5 // vector
move.l (a5),16(a7) // vector privileg violation
movem.l (a7),d0/a0/a5 // register zur<EFBFBD>ck
lea 12(a7),a7
rte
// privileg violation
pv_work:
move.l 16(a7),a5 // fault pc
move.b (a5),d0 // fault code
cmp.b #0x4e,d0 // 1.byt 0x4e
beq pv_4e // ja->
cmp.b #0x46,d0 // 1.byt 0x46
beq pv_46 // ja->
cmp.b #0x40,d0 // 1.byt 0x40
beq pv_40 // ja->
cmp.b #0xf4,d0 // 0xf4?
beq pv_f4
cmp.b #0xf3,d0 // 0xf3?
beq pv_f3
// hierher sollt man nicht kommen
nop
halt
nop
// code 0x4exx ********************************************
pv_4e:
move.b 1(a5),d0
cmp.b #0x73,d0 //rte?
beq pv_rte //ja->
cmp.b #0x72,d0 //stop?
beq pv_stop //ja->
cmp.b #0x7B,d0 //movec?
beq pv_movec //ja->
// move usp
btst #3,d0 // to or from
bne pv_usp_to_ax // usp -> ax
// move ax->usp
cmp.b #0x60,d0 //movec?
beq pv_a0_usp //ja->
cmp.b #0x61,d0 //movec?
beq pv_a1_usp //ja->
cmp.b #0x62,d0 //movec?
beq pv_a2_usp //ja->
cmp.b #0x63,d0 //movec?
beq pv_a3_usp //ja->
cmp.b #0x64,d0 //movec?
beq pv_a4_usp //ja->
cmp.b #0x65,d0 //movec?
beq pv_a5_usp //ja->
cmp.b #0x66,d0 //movec?
beq pv_a6_usp //ja->
halt
bra pv_a7_usp //ja->
// move usp->ax
pv_usp_to_ax:
move.l 8(a0),a5 //rt_usp holen
cmp.b #0x68,d0 //movec?
beq pv_usp_a0 //ja->
cmp.b #0x69,d0 //movec?
beq pv_usp_a1 //ja->
cmp.b #0x6a,d0 //movec?
beq pv_usp_a2 //ja->
cmp.b #0x6b,d0 //movec?
beq pv_usp_a3 //ja->
cmp.b #0x6c,d0 //movec?
beq pv_usp_a4 //ja->
cmp.b #0x6d,d0 //movec?
beq pv_usp_a5 //ja->
cmp.b #0x6e,d0 //movec?
beq pv_usp_a6 //ja->
// usp->a7
move.l a5,4(a0) // rt usp -> rt ssp
move.l a5,usp // und setzen
bra pv_usp_ax
// a0->usp
pv_a0_usp: move.l 4(a7),a5
bra pv_ax_usp
// a1->usp
pv_a1_usp: move.l a1,a5
bra pv_ax_usp
// a2->usp
pv_a2_usp: move.l a2,a5
bra pv_ax_usp
// a3->usp
pv_a3_usp: move.l a3,a5
bra pv_ax_usp
// a4->usp
pv_a4_usp: move.l a4,a5
bra pv_ax_usp
// a5->usp
pv_a5_usp: move.l 8(a7),a5
bra pv_ax_usp
// a6->usp
pv_a6_usp: move.l a6,a5
bra pv_ax_usp
// a7->usp
pv_a7_usp: move.l 4(a0),a5 // rt_ssp -> a5
pv_ax_usp:
move.l a5,8(a0) // usp -> rt_usp
addq.l #2,16(a7) // next
movem.l (a7),d0/a0/a5 // register zur<EFBFBD>ck
lea 12(a7),a7
rte
// usp->a0
pv_usp_a0:
move.l a5,4(a7)
bra pv_usp_ax
pv_usp_a1:
move.l a5,a1
bra pv_usp_ax
pv_usp_a2:
move.l a5,a2
bra pv_usp_ax
pv_usp_a3:
move.l a5,a3
bra pv_usp_ax
pv_usp_a4:
move.l a5,a4
bra pv_usp_ax
pv_usp_a5:
move.l a5,8(a7)
bra pv_usp_ax
pv_usp_a6:
move.l a5,a6
pv_usp_ax:
addq.l #2,16(a7) // next
movem.l (a7),d0/a0/a5 // register zur<EFBFBD>ck
lea 12(a7),a7
rte
// rte
pv_rte:
move.l usp,a5
#ifdef cf_stack
move.l (a5)+,12(a7) // sr verschieben
move.l (a5)+,16(a7) // pc verschieben
#else
move.w (a5)+,14(a7) // sr verschieben
move.l (a5)+,16(a7) // pc verschieben
move.w (a5)+,12(a7) // vector
#endif
bclr #5,14(a7) // war es von super?
bne pv_rte_sup // ja->
clr.l (a0) // rt_mod auf user
move.l a5,4(a0) // rt_ssp sichern
move.l 8(a0),a5 // rt_usp holen
pv_rte_sup:
move.l a5,usp // usp setzen
movem.l (a7),d0/a0/a5 // register zur<EFBFBD>ck
lea 12(a7),a7
rte
// stop
pv_stop:
move.b 2(a5),d0 // sr wert
and.l #0x0700,d0 // int mask
cmp.w #0x700,d0
beq stop7
cmp.w #0x600,d0
beq stop6
cmp.w #0x500,d0
beq stop5
cmp.w #0x400,d0
beq stop4
cmp.w #0x300,d0
beq stop3
cmp.w #0x200,d0
beq stop2
cmp.w #0x100,d0
beq stop1
stop #0x2000
bra stop_weiter
stop1:
stop #0x2100
bra stop_weiter
stop2:
stop #0x2200
bra stop_weiter
stop3:
stop #0x2300
bra stop_weiter
stop4:
stop #0x2400
bra stop_weiter
stop5:
stop #0x2500
bra stop_weiter
stop6:
stop #0x2600
bra stop_weiter
stop7:
stop #0x2700
stop_weiter:
addq.l #4,16(a7) // next
movem.l (a7),d0/a0/a5 // register zur<EFBFBD>ck
lea 12(a7),a7
rte
// movec ???????
pv_movec:
move.w 2(a5),d0 // 2.word holen
and.l #0xf000,d0
btst #15,d0 // addressregister?
bne pv_movec_ax // ja->
tst.w d0 // d0?
bne pvm_d1 // nein->
move.l (a7),-(a7) // d0 holen und sichern
bra pvm_me
pvm_d1:
cmp.w #0x1000,d0 // d1?
bne pvm_d2 // nein->
move.l d1,-(a7) // d1 holen und sichern
bra pvm_me // fertig machen
pvm_d2:
cmp.w #0x2000,d0 // d1?
bne pvm_d3 // nein->
move.l d2,-(a7) // d2 holen und sichern
bra pvm_me // fertig machen
pvm_d3:
cmp.w #0x3000,d0 // d1?
bne pvm_d4 // nein->
move.l d3,-(a7) // d3 holen und sichern
bra pvm_me // fertig machen
pvm_d4:
cmp.w #0x4000,d0 // d1?
bne pvm_d5 // nein->
move.l d4,-(a7) // d4 holen und sichern
bra pvm_me // fertig machen
pvm_d5:
cmp.w #0x5000,d0 // d1?
bne pvm_d6 // nein->
move.l d5,-(a7) // d5 holen und sichern
bra pvm_me // fertig machen
pvm_d6:
cmp.w #0x6000,d0 // d1?
bne pvm_d7 // nein->
move.l d6,-(a7) // d6 holen und sichern
bra pvm_me // fertig machen
pvm_d7:
move.l d7,-(a7) // d7 holen und sichern
bra pvm_me // fertig machen
pv_movec_ax:
cmp.w #0x8000,d0 // a0?
bne pvm_a1 // nein->
move.l 4(a7),-(a7) // a0 holen und sichern
bra pvm_me // fertig machen
pvm_a1:
cmp.w #0x9000,d0 // a0?
bne pvm_a2 // nein->
move.l a1,-(a7) // a1 holen und sichern
bra pvm_me // fertig machen
pvm_a2:
cmp.w #0xa000,d0 // a0?
bne pvm_a3 // nein->
move.l a2,-(a7) // a2 holen und sichern
bra pvm_me // fertig machen
pvm_a3:
cmp.w #0xb000,d0 // a0?
bne pvm_a4 // nein->
move.l a3,-(a7) // a3 holen und sichern
bra pvm_me // fertig machen
pvm_a4:
cmp.w #0xc000,d0 // a0?
bne pvm_a5 // nein->
move.l a4,-(a7) // a4 holen und sichern
bra pvm_me // fertig machen
pvm_a5:
cmp.w #0xd000,d0 // a0?
bne pvm_a6 // nein->
move.l 8(a7),-(a7) // a5 holen und sichern
bra pvm_me // fertig machen
pvm_a6:
cmp.w #0xe000,d0 // a0?
bne pvm_a7 // nein->
move.l a6,-(a7) // a6 holen und sichern
bra pvm_me // fertig machen
pvm_a7:
move.l 4(a7),-(a7) // a7 holen und sichern
pvm_me:
move.w 2(a5),d0 // 2.word holen
andi.l #0xf,d0 // nur letzte 4 bits
move.l (a7)+,8(a0,d0*4) // start bei +8, *4 weil long
jsr cpusha // gesammten cache flushen
rte
// code 0x46xx *****************************************
pv_46:
move.b 1(a5),d0
cmp.b #0xfc,d0 //#d16->sr
beq im_sr //ja->
//move dx->sr (sr und rt_mod ist supervisor sonst w<EFBFBD>re es privileg violation
cmp.b #0xc0,d0 //d0->sr?
bne d1_sr //nein->
move.w 2(a7),d0 //hier ist d0 gesichert
bra d0_sr
d1_sr:
cmp.b #0xc1,d0 //d1->sr?
bne d2_sr //nein->
move.w d1,d0
bra d0_sr
d2_sr:
cmp.b #0xc2,d0 //d2->sr?
bne d3_sr
move.w d2,d0
bra d0_sr
d3_sr:
cmp.b #0xc3,d0 //d3->sr?
bne d4_sr
move.w d3,d0
bra d0_sr
d4_sr:
cmp.b #0xc4,d0 //d4->sr?
bne d5_sr
move.w d4,d0
bra d0_sr
d5_sr:
cmp.b #0xc5,d0 //d5->sr?
bne d6_sr
move.w d5,d0
bra d0_sr
d6_sr:
cmp.b #0xc6,d0 //d6->sr?
bne d7_sr
move.w d6,d0
bra d0_sr
d7_sr:
move.w d7,d0 // sonst d7->sr
d0_sr:
addq.l #2,16(a7) // next
bra pv_set_sr_end // fertig machen
// move #xxxx,sr
im_sr:
addq.l #4,16(a7) // next
move.w 2(a5),d0 // data
pv_set_sr_end:
bclr #13,d0 // war super?
bne pv_sre2 // ja ->
clr.l (a0)
move.l usp,a5 // usp
move.l a5,4(a0) // rt_ssp speichern
move.l 8(a0),a5 // rt_usp holen
move.l a5,usp // setzen
pv_sre2:
move.w d0,14(a7) // sr setzen
movem.l (a7),d0/a0/a5 // register zur<EFBFBD>ck
lea 12(a7),a7
rte
// code 0x40xx *****************************************
pv_40:
move.b 1(a5),d0 // 2.byt
cmp.b #0xe7,d0
beq pv_strldsr
// move sr->dx
move.l 12(a7),a5 // sr holen
tst.b (a0) // super?
beq pv_40_user // nein?
lea 0x2000(a5),a5 // super zuaddieren
pv_40_user:
cmp.b #0xc0,d0
bne nsr_d1
move.w a5,2(a7)
bra sr_dx_end
nsr_d1:
cmp.b #0xc1,d0
bne nsr_d2
move.w a5,d1
bra sr_dx_end
nsr_d2:
cmp.b #0xc2,d0
bne nsr_d3
move.w a5,d2
bra sr_dx_end
nsr_d3:
cmp.b #0xc3,d0
bne nsr_d4
move.w a5,d3
bra sr_dx_end
nsr_d4:
cmp.b #0xc4,d0
bne nsr_d5
move.w a5,d4
bra sr_dx_end
nsr_d5:
cmp.b #0xc5,d0
bne nsr_d6
move.w a5,d5
bra sr_dx_end
nsr_d6:
cmp.b #0xc6,d0
bne nsr_d7
move.w a5,d6
bra sr_dx_end
nsr_d7:
move.w a5,d7
halt
sr_dx_end:
addq.l #2,16(a7) // next
movem.l (a7),d0/a0/a5 // register zur<EFBFBD>ck
lea 12(a7),a7
rte
// strldsr
pv_strldsr:
nop
halt
nop
// code 0xf4xx ***********************************
pv_f4:
addq.l #2,16(a7) // next instr
move.b 1(a5),d0 // 2.byt
bsr pv_ax_a0 // richtiges register
move.b 1(a5),d0 // 2.byt
cmp.b #0x30,d0 // >0xf430
blo pv_intouch
// cpushl
cpushl bc,(a0)
movem.l (a7),d0/a0/a5
lea 12(a7),a7
rte
pv_intouch:
intouch a0
movem.l (a7),d0/a0/a5
lea 12(a7),a7
rte
// subroutine register ax->a0
pv_ax_a0:
and.l #0x7,d0 // nur register nummer
subq.l #1,d0
bmi pv_a0_a0
subq.l #1,d0
bmi pv_a1_a0
subq.l #1,d0
bmi pv_a2_a0
subq.l #1,d0
bmi pv_a3_a0
subq.l #1,d0
bmi pv_a4_a0
subq.l #1,d0
bmi pv_a5_a0
subq.l #1,d0
bmi pv_a6_a0
move.l a7,a0
rts
pv_a0_a0:
move.l 8(a7),a0
rts
pv_a1_a0:
move.l a1,a0
rts
pv_a2_a0:
move.l a2,a0
rts
pv_a3_a0:
move.l a3,a0
rts
pv_a4_a0:
move.l a4,a0
rts
pv_a5_a0:
move.l 12(a7),a0
rts
pv_a6_a0:
move.l a6,a0
rts
// code 0xf4xx ***********************************
pv_f3:
addq.l #2,16(a7) // next instr
move.b 1(a5),d0 // 2. byt
cmp.b #0x40,d0
bgt pv_frestore
//fsave (ax) oder d16(ax)
jsr pv_ax_a0 // richtiges register holen
move.b 1(a5),d0
cmp.b #0x20,d0
// +d16
blt pv_f3_ax
addq.l #2,16(a7) // next instr
clr.l d0
move.w 2(a0),d0 // d16
add.l d0,a0
pv_f3_ax:
fsave (a0)
movem.l (a7),d0/a0/a5
lea 12(a7),a7
rte
pv_frestore:
cmp.b #0x7a,d0
beq pv_f_d16pc
// frestore (ax) oder d16(ax)
jsr pv_ax_a0 // richtiges register holen
move.b 1(a5),d0
cmp.b #0x60,d0
blt pv_frestore_ax
pv_fend:
addq.l #2,16(a7) // next instr
clr.l d0
move.w 2(a0),d0 // d16
add.l d0,a0
pv_frestore_ax:
frestore (a0)
movem.l (a7),d0/a0/a5
lea 12(a7),a7
rte
// frestore d16(pc)
pv_f_d16pc:
move.l 16(a7),a0 // pc holen
bra pv_fend
//*****************************************************
cpusha:
lea -16(a7),a7
movem.l d0-d1/a0-a1,(a7) // backup C trash registers
jsr _flush_and_invalidate_caches
movem.l (a7),d0-d1/a0-a1 // restore C trash registers
lea 16(a7),a7
rts
//*******************************************************33

View File

@@ -0,0 +1,877 @@
/*
* File: sysinit.c
* Purpose: Power-on Reset configuration of the Firebee board.
*
* Notes:
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2010 - 2012 F. Aschwanden
* Copyright 2011 - 2012 V. Riviere
* Copyright 2012 M. Froeschle
*
*/
#include "MCF5475.h"
#include "startcf.h"
#include "cache.h"
#include "sysinit.h"
#include "bas_printf.h"
#include "bas_types.h"
#include "wait.h"
extern void xprintf_before_copy(const char *fmt, ...);
#define xprintf xprintf_before_copy
extern void flush_and_invalidate_caches_before_copy(void);
#define flush_and_invalidate_caches flush_and_invalidate_caches_before_copy
#define UNUSED(x) (void)(x) /* Unused variable */
extern volatile long _VRAM; /* start address of video ram from linker script */
/*
* init SLICE TIMER 0
* all = 32.538 sec = 30.736mHz
* BYT0 = 127.1ms/tick = 7.876Hz offset 0
* BYT1 = 496.5us/tick = 2.014kHz offset 1
* BYT2 = 1.939us/tick = 515.6kHz offset 2
* BYT3 = 7.576ns/tick = 132.00MHz offset 3
* count down!!! 132MHz!!!
*/
void init_slt(void)
{
xprintf("slice timer initialization: ");
MCF_SLT0_STCNT = 0xffffffff;
MCF_SLT0_SCR = MCF_SLT_SCR_TEN | MCF_SLT_SCR_RUN; /* enable and run continuously */
xprintf("finished\r\n");
}
/*
* init GPIO general purpose I/O module
*/
void init_gpio(void)
{
/*
* pad register P.S.:FBCTL and FBCS set correctly at reset
*/
/*
* configure all four 547x GPIO module DMA pins:
*
* /DACK1 - DMA acknowledge 1
* /DACK0 - DMA acknowledge 0
* /DREQ1 - DMA request 1
* /DREQ0 - DMA request 0
*
* for DMA operation
*/
MCF_PAD_PAR_DMA = MCF_PAD_PAR_DMA_PAR_DACK0_DACK0 |
MCF_PAD_PAR_DMA_PAR_DACK1_DACK1 |
MCF_PAD_PAR_DMA_PAR_DREQ1_DREQ1 |
MCF_PAD_PAR_DMA_PAR_DREQ0_DREQ0;
/*
* configure FEC0 pin assignment on GPIO module as FEC0
* configure FEC1 pin assignment (PAR_E17, PAR_E1MII) as GPIO,
* /IRQ5 and /IRQ6 from GPIO (needs to be disabled on EPORT module, which also can
* use those INTs).
*/
MCF_PAD_PAR_FECI2CIRQ = MCF_PAD_PAR_FECI2CIRQ_PAR_E07 |
MCF_PAD_PAR_FECI2CIRQ_PAR_E0MII |
MCF_PAD_PAR_FECI2CIRQ_PAR_E0MDIO |
MCF_PAD_PAR_FECI2CIRQ_PAR_E0MDC |
MCF_PAD_PAR_FECI2CIRQ_PAR_E1MDIO_E1MDIO |
MCF_PAD_PAR_FECI2CIRQ_PAR_E1MDC_E1MDC |
MCF_PAD_PAR_FECI2CIRQ_PAR_SDA |
MCF_PAD_PAR_FECI2CIRQ_PAR_SCL |
MCF_PAD_PAR_FECI2CIRQ_PAR_IRQ6 |
MCF_PAD_PAR_FECI2CIRQ_PAR_IRQ5;
/*
* configure PCI Grant pin assignment on GPIO module:
*
* /PCIBG4 used as FlexBus /TBST
* /PCIBG3 used as general purpose I/O
* /PCIBG2 used as /PCIBG2
* /PCIBG1 used as /PCIBG1
* /PCIBG0 used as /PCIBG0
*/
MCF_PAD_PAR_PCIBG = MCF_PAD_PAR_PCIBG_PAR_PCIBG4_TBST |
MCF_PAD_PAR_PCIBG_PAR_PCIBG3_GPIO |
MCF_PAD_PAR_PCIBG_PAR_PCIBG2_PCIBG2 |
MCF_PAD_PAR_PCIBG_PAR_PCIBG1_PCIBG1 |
MCF_PAD_PAR_PCIBG_PAR_PCIBG0_PCIBG0;
/*
* configure PCI request pin assignment on GPIO module:
* /PCIBR4 as /IRQ4
* /PCIBR3 as GPIO (PIC)
* /PCIBR2 as /PCIBR2
* /PCIBR1 as /PCIBR1
* /PCIBR0 as /PCIBR0
*/
MCF_PAD_PAR_PCIBR = MCF_PAD_PAR_PCIBR_PAR_PCIBR4_IRQ4 |
MCF_PAD_PAR_PCIBR_PAR_PCIBR3_GPIO |
MCF_PAD_PAR_PCIBR_PAR_PCIBR2_PCIBR2 |
MCF_PAD_PAR_PCIBR_PAR_PCIBR1_PCIBR1 |
MCF_PAD_PAR_PCIBR_PAR_PCIBR0_PCIBR0;
/*
* configure PSC3 pin assignment on GPIO module:
* /PSC3CTS as /PSC3PTS
* /PSC3RTS as /PSC3RTS
* PSC3RXD as PSC3RXD
* PSC3TXD as PSC3TXD
*/
MCF_PAD_PAR_PSC3 = MCF_PAD_PAR_PSC3_PAR_TXD3 | MCF_PAD_PAR_PSC3_PAR_RXD3;
/*
* Configure PSC1 pin assignment on GPIO module:
* - all pins configured for serial interface operation
*/
MCF_PAD_PAR_PSC1 = MCF_PAD_PAR_PSC1_PAR_CTS1_CTS |
MCF_PAD_PAR_PSC1_PAR_RTS1_RTS |
MCF_PAD_PAR_PSC1_PAR_RXD1 |
MCF_PAD_PAR_PSC1_PAR_TXD1;
/*
* Configure PSC0 Pin Assignment on GPIO module:
* - all pins configured for serial interface operation
*/
MCF_PAD_PAR_PSC0 = MCF_PAD_PAR_PSC0_PAR_CTS0_CTS |
MCF_PAD_PAR_PSC0_PAR_RTS0_RTS |
MCF_PAD_PAR_PSC0_PAR_RXD0 |
MCF_PAD_PAR_PSC0_PAR_TXD0;
MCF_PAD_PAR_DSPI = 0b0001111111111111; /* DSPI NORMAL */
MCF_PAD_PAR_TIMER = 0b00101101; /* TIN3..2=#IRQ3..2;TOUT3..2=NORMAL */
// ALLE OUTPUTS NORMAL LOW
// ALLE DIR NORMAL INPUT = 0
MCF_GPIO_PDDR_FEC1L = 0b00011110; /* OUT: 4=LED,3=PRG_DQ0,2=#FPGA_CONFIG,1=PRG_CLK(FPGA) */
#define FPGA_STATUS (1 << 0)
#define FPGA_CLOCK (1 << 1)
#define FPGA_CONFIG (1 << 2)
#define FPGA_DATA0 (1 << 3)
#define FPGA_CONF_DONE (1 << 5)
/* pull FPGA config to low as early as possible */
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK; /* FPGA clock => low */
MCF_GPIO_PODR_FEC1L &= ~FPGA_CONFIG; /* FPGA config => low */
}
/*
* init serial
*/
void init_serial(void)
{
/* PSC0: SER1 */
MCF_PSC0_PSCSICR = 0; /* PSC control register: select UART mode */
MCF_PSC0_PSCCSR = 0xDD; /* use TX and RX baud rate from PSC timer */
MCF_PSC0_PSCCTUR = 0x00; /* =\ */
MCF_PSC0_PSCCTLR = 36; /* divide sys_clk by 36 => BAUD RATE = 115200 bps */
MCF_PSC0_PSCCR = 0x20; /* reset receiver and RxFIFO */
MCF_PSC0_PSCCR = 0x30; /* reset transmitter and TxFIFO */
MCF_PSC0_PSCCR = 0x40; /* reset all error status */
MCF_PSC0_PSCCR = 0x50; /* reset break change interrupt */
MCF_PSC0_PSCCR = 0x10; /* reset MR pointer */
MCF_PSC0_PSCIMR = 0x8700; /* enable input port change interrupt, enable delta break interrupt, */
/* enable receiver interrupt/request, enable transceiver interrupt/request */
MCF_PSC0_PSCACR = 0x03; /* enable state change of CTS */
MCF_PSC0_PSCMR1 = 0xb3; /* 8 bit, no parity */
MCF_PSC0_PSCMR2 = 0x07; /* 1 stop bit */
MCF_PSC0_PSCRFCR = 0x0F;
MCF_PSC0_PSCTFCR = 0x0F;
MCF_PSC0_PSCRFAR = 0x00F0;
MCF_PSC0_PSCTFAR = 0x00F0;
MCF_PSC0_PSCOPSET = 0x01;
MCF_PSC0_PSCCR = 0x05;
/* PSC3: PIC */
MCF_PSC3_PSCSICR = 0; // UART
MCF_PSC3_PSCCSR = 0xDD;
MCF_PSC3_PSCCTUR = 0x00;
MCF_PSC3_PSCCTLR = 36; // BAUD RATE = 115200
MCF_PSC3_PSCCR = 0x20;
MCF_PSC3_PSCCR = 0x30;
MCF_PSC3_PSCCR = 0x40;
MCF_PSC3_PSCCR = 0x50;
MCF_PSC3_PSCCR = 0x10;
MCF_PSC3_PSCIMR = 0x0200; // receiver interrupt enable
MCF_PSC3_PSCACR = 0x03;
MCF_PSC3_PSCMR1 = 0xb3;
MCF_PSC3_PSCMR2 = 0x07;
MCF_PSC3_PSCRFCR = 0x0F;
MCF_PSC3_PSCTFCR = 0x0F;
MCF_PSC3_PSCRFAR = 0x00F0;
MCF_PSC3_PSCTFAR = 0x00F0;
MCF_PSC3_PSCOPSET = 0x01;
MCF_PSC3_PSCCR = 0x05;
MCF_INTC_ICR32 = 0x3F; //MAXIMALE PRIORITY/**********/
xprintf("serial interfaces initialization: finished\r\n");
}
/********************************************************************/
/* Initialize DDR DIMMs on the EVB board */
/********************************************************************/
void init_ddram(void)
{
xprintf("SDRAM controller initialization: ");
/*
* Check to see if the SDRAM has already been initialized
* by a run control tool
*/
if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
/* Basic configuration and initialization */
/*
* SB_E (Bits 9-8): 10 <=> 7.6 mA (SDCKE)
* SB_C (Bits 7-6): 10 <=> 7.6 mA (SDRAM Clocks)
* SB_A (Bits 5-4): 10 <=> 7.6 mA (RAS, CAS, SDWE, SDADDR[12:0], and SDBA)
* SB_S (Bits 3-2): 10 <=> 7.6 mA (SDRDQS)
* SB_D (Bits 1-0): 10 <=> 7.6 mA (SDRDQS)
*
* -> lowest setting the Coldfire SDRAM controller allows
*/
MCF_SDRAMC_SDRAMDS = 0x000002AA;/* SDRAMDS configuration */
MCF_SDRAMC_CS0CFG = 0x0000001A; /* SDRAM CS0 configuration (128Mbytes 0000_0000 - 07FF_FFFF) */
MCF_SDRAMC_CS1CFG = 0x0800001A; /* SDRAM CS1 configuration (128Mbytes 0800_0000 - 0FFF_FFFF) */
MCF_SDRAMC_CS2CFG = 0x1000001A; /* SDRAM CS2 configuration (128Mbytes 1000_0000 - 07FF_FFFF) */
MCF_SDRAMC_CS3CFG = 0x1800001A; /* SDRAM CS3 configuration (128Mbytes 1800_0000 - 1FFF_FFFF) */
/*
*
*/
MCF_SDRAMC_SDCFG1 = MCF_SDRAMC_SDCFG1_WTLAT(3) /* Write latency */
| MCF_SDRAMC_SDCFG1_REF2ACT(8) /* Refresh to Active Delay */
| MCF_SDRAMC_SDCFG1_PRE2ACT(2) /* Precharge to Active Delay */
| MCF_SDRAMC_SDCFG1_ACT2RW(2) /* Active to Read/Write Delay */
| MCF_SDRAMC_SDCFG1_RDLAT(6) /* Read CAS latency */
| MCF_SDRAMC_SDCFG1_SWT2RD(3) /* Single Write to Read/Write/Precharge delay */
| MCF_SDRAMC_SDCFG1_SRD2RW(7); /* Single Read to Read/Write/Precharge delay */
MCF_SDRAMC_SDCFG2 = MCF_SDRAMC_SDCFG2_BL(7) /* Burst Length */
| MCF_SDRAMC_SDCFG2_BRD2WT(7) /* Burst Read to Write delay */
| MCF_SDRAMC_SDCFG2_BWT2RW(6) /* Burst Write to Read/Write/Precharge delay */
| MCF_SDRAMC_SDCFG2_BRD2PRE(4); /* Burst Read to Read/Precharge delay */
#ifdef _NOT_USED_
MCF_SDRAMC_SDCFG1 = 0x73622830; /* SDCFG1 */
MCF_SDRAMC_SDCFG2 = 0x46770000; /* SDCFG2 */
#endif /* _NOT_USED_ */
MCF_SDRAMC_SDCR = MCF_SDRAMC_SDCR_IPALL /* initiate Precharge All command */
| MCF_SDRAMC_SDCR_RCNT(13) /* Refresh Count (= (x + 1) * 64 */
| MCF_SDRAMC_SDCR_MUX(1) /* Muxing control */
| MCF_SDRAMC_SDCR_DDR
| MCF_SDRAMC_SDCR_CKE
| MCF_SDRAMC_SDCR_MODE_EN;
MCF_SDRAMC_SDMR = MCF_SDRAMC_SDMR_CMD /* Generate an LMR/LEMR command */
| MCF_SDRAMC_SDMR_AD(0) /* Address */
| MCF_SDRAMC_SDMR_BNKAD(1); /* LEMR */
MCF_SDRAMC_SDMR = MCF_SDRAMC_SDMR_CMD /* Generate an LMR/LEMR command */
| MCF_SDRAMC_SDMR_AD(0x123)
| MCF_SDRAMC_SDMR_BNKAD(0); /* LMR */
#ifdef _NOT_USED_
MCF_SDRAMC_SDCR = 0xE10D0002; /* SDCR + IPALL */
MCF_SDRAMC_SDMR = 0x40010000; /* SDMR (write to LEMR) */
MCF_SDRAMC_SDMR = 0x048D0000; /* SDRM (write to LMR) */
#endif /* _NOT_USED_ */
MCF_SDRAMC_SDCR = 0xE10D0002; /* SDCR + IPALL */
MCF_SDRAMC_SDCR = 0xE10D0004; /* SDCR + IREF (first refresh) */
MCF_SDRAMC_SDCR = 0xE10D0004; /* SDCR + IREF (second refresh) */
MCF_SDRAMC_SDMR = 0x008D0000; /* SDMR (write to LMR) */
MCF_SDRAMC_SDCR = 0x710D0F00; /* SDCR (lock SDMR and enable refresh) */
xprintf("finished\r\n");
}
else
{
xprintf("skipped. Already initialized (running from RAM)\r\n");
}
}
/*
* initialize FlexBus chip select registers
*/
void init_fbcs()
{
xprintf("FlexBus chip select registers initialization: ");
/* Flash */
MCF_FBCS0_CSAR = 0xE0000000; /* flash base address */
MCF_FBCS0_CSCR = MCF_FBCS_CSCR_PS_16 |
MCF_FBCS_CSCR_WS(4)|
MCF_FBCS_CSCR_AA;
MCF_FBCS0_CSMR = MCF_FBCS_CSMR_BAM_8M |
MCF_FBCS_CSMR_V; /* 8 MByte on */
MCF_FBCS1_CSAR = 0xFFF00000; /* ATARI I/O ADRESS */
MCF_FBCS1_CSCR = MCF_FBCS_CSCR_PS_16 /* 16BIT PORT */
| MCF_FBCS_CSCR_WS(8) /* DEFAULT 8WS */
| MCF_FBCS_CSCR_AA; /* AA */
MCF_FBCS1_CSMR = MCF_FBCS_CSMR_BAM_1M | MCF_FBCS_CSMR_V;
MCF_FBCS2_CSAR = 0xF0000000; // NEUER I/O ADRESS-BEREICH
MCF_FBCS2_CSCR = MCF_FBCS_CSCR_PS_32 // 32BIT PORT
| MCF_FBCS_CSCR_WS(8) // DEFAULT 4WS
| MCF_FBCS_CSCR_AA; // AA
MCF_FBCS2_CSMR = (MCF_FBCS_CSMR_BAM_128M // F000'0000-F7FF'FFFF
| MCF_FBCS_CSMR_V);
MCF_FBCS3_CSAR = 0xF8000000; // NEUER I/O ADRESS-BEREICH
MCF_FBCS3_CSCR = MCF_FBCS_CSCR_PS_16 // 16BIT PORT
| MCF_FBCS_CSCR_AA; // AA
MCF_FBCS3_CSMR = (MCF_FBCS_CSMR_BAM_64M // F800'0000-FBFF'FFFF
| MCF_FBCS_CSMR_V);
MCF_FBCS4_CSAR = 0x40000000; // VIDEO RAM BEREICH, #FB_CS3 WIRD NICHT BENÜTZT, DECODE DIREKT AUF DEM FPGA
MCF_FBCS4_CSCR = MCF_FBCS_CSCR_PS_32 // 32BIT PORT
| MCF_FBCS_CSCR_BSTR // BURST READ ENABLE
| MCF_FBCS_CSCR_BSTW; // BURST WRITE ENABLE
MCF_FBCS4_CSMR = MCF_FBCS_CSMR_BAM_1G // 4000'0000-7FFF'FFFF
| MCF_FBCS_CSMR_V;
xprintf("finished\r\n");
}
void wait_pll(void)
{
uint32_t trgt = MCF_SLT0_SCNT - 100000;
do
{
;
} while ((* (volatile int16_t *) 0xf0000800 < 0) && MCF_SLT0_SCNT > trgt);
}
static volatile uint8_t *pll_base = (volatile uint8_t *) 0xf0000600;
void init_pll(void)
{
xprintf("FPGA PLL initialization: ");
wait_pll();
* (volatile uint16_t *) (pll_base + 0x48) = 27; /* loopfilter r */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x08) = 1; /* charge pump 1 */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x00) = 12; /* N counter high = 12 */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x40) = 12; /* N counter low = 12 */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x114) = 1; /* ck1 bypass */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x118) = 1; /* ck2 bypass */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x11c) = 1; /* ck3 bypass */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x10) = 1; /* ck0 high = 1 */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x50) = 1; /* ck0 low = 1 */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x144) = 1; /* M odd division */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x44) = 1; /* M low = 1 */
wait_pll();
* (volatile uint16_t *) (pll_base + 0x04) = 145; /* M high = 145 = 146 MHz */
wait_pll();
* (volatile uint8_t *) 0xf0000800 = 0; /* set */
xprintf("finished\r\n");
}
/*
* INIT VIDEO DDR RAM
*/
#define NOP() __asm__ __volatile__("nop\n\t" : : : "memory")
void init_video_ddr(void) {
xprintf("init video RAM: ");
* (volatile uint16_t *) 0xf0000400 = 0xb; /* set cke = 1, cs=1, config = 1 */
NOP();
_VRAM = 0x00050400; /* IPALL */
NOP();
_VRAM = 0x00072000; /* load EMR pll on */
NOP();
_VRAM = 0x00070122; /* load MR: reset pll, cl=2, burst=4lw */
NOP();
_VRAM = 0x00050400; /* IPALL */
NOP();
_VRAM = 0x00060000; /* auto refresh */
NOP();
_VRAM = 0x00060000; /* auto refresh */
NOP();
_VRAM = 0000070022; /* load MR dll on */
NOP();
* (uint32_t *) 0xf0000400 = 0x01070002; /* fifo on, refresh on, ddrcs und cke on, video dac on */
xprintf("finished\r\n");
}
#define PCI_MEMORY_OFFSET (0x80000000)
#define PCI_MEMORY_SIZE (0x40000000)
#define PCI_IO_OFFSET (0xD0000000)
#define PCI_IO_SIZE (0x10000000)
/*
* INIT PCI
*/
void init_PCI(void) {
xprintf("PCI BUS controller initialization: ");
MCF_PCIARB_PACR = MCF_PCIARB_PACR_INTMPRI
+ MCF_PCIARB_PACR_EXTMPRI(0x1F)
+ MCF_PCIARB_PACR_INTMINTEN
+ MCF_PCIARB_PACR_EXTMINTEN(0x1F);
// Setup burst parameters
MCF_PCI_PCICR1 = MCF_PCI_PCICR1_CACHELINESIZE(4) + MCF_PCI_PCICR1_LATTIMER(32);
MCF_PCI_PCICR2 = MCF_PCI_PCICR2_MINGNT(16) + MCF_PCI_PCICR2_MAXLAT(16);
// Turn on error signaling
MCF_PCI_PCIICR = MCF_PCI_PCIICR_TAE + MCF_PCI_PCIICR_TAE + MCF_PCI_PCIICR_REE + 32;
MCF_PCI_PCIGSCR |= MCF_PCI_PCIGSCR_SEE;
/* Configure Initiator Windows */
/* initiator window 0 base / translation adress register */
MCF_PCI_PCIIW0BTAR = (PCI_MEMORY_OFFSET + ((PCI_MEMORY_SIZE -1) >> 8)) & 0xffff0000;
/* initiator window 1 base / translation adress register */
MCF_PCI_PCIIW1BTAR = (PCI_IO_OFFSET + ((PCI_IO_SIZE - 1) >> 8)) & 0xffff0000;
/* initiator window 2 base / translation address register */
MCF_PCI_PCIIW2BTAR = 0L; /* not used */
/* initiator window configuration register */
MCF_PCI_PCIIWCR = MCF_PCI_PCIIWCR_WINCTRL0_MEMRDLINE + MCF_PCI_PCIIWCR_WINCTRL1_IO;
/* reset PCI devices */
MCF_PCI_PCIGSCR &= ~MCF_PCI_PCIGSCR_PR;
xprintf("finished\r\n");
}
/*
* probe for UPC720101 (USB)
*/
void test_upd720101(void)
{
xprintf("UDP720101 USB controller initialization: ");
/* select UPD720101 AD17 */
MCF_PCI_PCICAR = MCF_PCI_PCICAR_E +
MCF_PCI_PCICAR_DEVNUM(17) +
MCF_PCI_PCICAR_FUNCNUM(0) +
MCF_PCI_PCICAR_DWORD(0);
if (* (uint32_t *) PCI_IO_OFFSET == 0x33103500)
{
MCF_PCI_PCICAR = MCF_PCI_PCICAR_E +
MCF_PCI_PCICAR_DEVNUM(17) +
MCF_PCI_PCICAR_FUNCNUM(0) +
MCF_PCI_PCICAR_DWORD(57);
//* (uint8_t *) PCI_IO_OFFSET = 0x20; // commented out (hangs currently)
}
else
{
MCF_PSC0_PSCTB_8BIT = 'NOT ';
MCF_PCI_PCICAR = MCF_PCI_PCICAR_DEVNUM(17) +
MCF_PCI_PCICAR_FUNCNUM(0) +
MCF_PCI_PCICAR_DWORD(57);
}
xprintf("finished\r\n");
}
static bool i2c_transfer_finished(void)
{
if (MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)
return true;
return false;
}
static void wait_i2c_transfer_finished(void)
{
waitfor(100000, i2c_transfer_finished); /* wait until interrupt bit has been set */
MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF; /* clear interrupt bit (byte transfer finished */
}
static bool i2c_bus_free(void)
{
return (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB);
}
/*
* TFP410 (DVI) on
*/
void dvi_on(void) {
uint8_t receivedByte;
uint8_t dummyByte; /* only used for a dummy read */
int num_tries = 0;
xprintf("DVI digital video output initialization: ");
MCF_I2C_I2FDR = 0x3c; /* divide system clock by 1280: 100kHz standard */
do {
/* disable all i2c interrupt routing targets */
MCF_I2C_I2ICR = 0x0; //~(MCF_I2C_I2ICR_IE | MCF_I2C_I2ICR_RE | MCF_I2C_I2ICR_TE | MCF_I2C_I2ICR_BNBE);
/* disable i2c, disable i2c interrupts, slave, receive, i2c = acknowledge, no repeat start */
MCF_I2C_I2CR = 0x0;
/* repeat start, transmit acknowledge */
MCF_I2C_I2CR = MCF_I2C_I2CR_RSTA | MCF_I2C_I2CR_TXAK;
receivedByte = MCF_I2C_I2DR; /* read a byte */
MCF_I2C_I2SR = 0x0; /* clear status register */
MCF_I2C_I2CR = 0x0; /* disable i2c */
MCF_I2C_I2ICR = MCF_I2C_I2ICR_IE; /* route i2c interrupts to cpu */
/* i2c enable, master mode, transmit acknowledge */
MCF_I2C_I2CR = MCF_I2C_I2CR_IEN | MCF_I2C_I2CR_MSTA | MCF_I2C_I2CR_MTX;
MCF_I2C_I2DR = 0x7a; /* send data: address of TFP410 */
wait_i2c_transfer_finished();
if (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK) /* next try if no acknowledge */
continue;
MCF_I2C_I2DR = 0x00; /* send data: SUB ADRESS 0 */
wait_i2c_transfer_finished();
MCF_I2C_I2CR |= MCF_I2C_I2CR_RSTA; /* repeat start */
MCF_I2C_I2DR = 0x7b; /* begin read */
wait_i2c_transfer_finished();
if (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK) /* next try if no acknowledge */
continue;
MCF_I2C_I2CR &= 0xef; //~MCF_I2C_I2CR_MTX; /* switch to receive mode */
dummyByte = MCF_I2C_I2DR; /* dummy read */
wait_i2c_transfer_finished();
MCF_I2C_I2CR |= MCF_I2C_I2CR_TXAK; /* transmit acknowledge enable */
receivedByte = MCF_I2C_I2DR; /* read a byte */
wait_i2c_transfer_finished();
MCF_I2C_I2CR = MCF_I2C_I2CR_IEN; /* stop */
dummyByte = MCF_I2C_I2DR; // dummy read
if (receivedByte != 0x4c)
continue;
MCF_I2C_I2CR = 0x0; // stop
MCF_I2C_I2SR = 0x0; // clear sr
waitfor(10000, i2c_bus_free);
MCF_I2C_I2CR = 0xb0; // on tx master
MCF_I2C_I2DR = 0x7A;
wait_i2c_transfer_finished();
if (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK)
continue;
MCF_I2C_I2DR = 0x08; // SUB ADRESS 8
wait_i2c_transfer_finished();
MCF_I2C_I2DR = 0xbf; // ctl1: power on, T:M:D:S: enable
wait_i2c_transfer_finished();
MCF_I2C_I2CR = 0x80; // stop
dummyByte = MCF_I2C_I2DR; // dummy read
MCF_I2C_I2SR = 0x0; // clear sr
waitfor(10000, i2c_bus_free);
MCF_I2C_I2CR = 0xb0;
MCF_I2C_I2DR = 0x7A;
wait_i2c_transfer_finished();
if (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK)
continue;
MCF_I2C_I2DR = 0x08; // SUB ADRESS 8
wait_i2c_transfer_finished();
MCF_I2C_I2CR |= 0x4; // repeat start
MCF_I2C_I2DR = 0x7b; // beginn read
wait_i2c_transfer_finished();
if (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK)
continue;
MCF_I2C_I2CR &= 0xef; // switch to rx
dummyByte = MCF_I2C_I2DR; // dummy read
wait_i2c_transfer_finished();
MCF_I2C_I2CR |= 0x08; // txak=1
wait(50);
receivedByte = MCF_I2C_I2DR;
wait_i2c_transfer_finished();
MCF_I2C_I2CR = 0x80; // stop
dummyByte = MCF_I2C_I2DR; // dummy read
num_tries++;
} while ((receivedByte != 0xbf) && (num_tries < 10));
if (num_tries >= 10) {
xprintf("FAILED!\r\n");
} else {
xprintf("finished\r\n");
}
UNUSED(dummyByte);
// Avoid warning
}
/*
* AC97
*/
void init_ac97(void) {
// PSC2: AC97 ----------
int i;
int zm;
int va;
int vb;
int vc;
xprintf("AC97 sound chip initialization: ");
MCF_PAD_PAR_PSC2 = MCF_PAD_PAR_PSC2_PAR_RTS2_RTS // PSC2=TX,RX BCLK,CTS->AC'97
| MCF_PAD_PAR_PSC2_PAR_CTS2_BCLK
| MCF_PAD_PAR_PSC2_PAR_TXD2
| MCF_PAD_PAR_PSC2_PAR_RXD2;
MCF_PSC2_PSCMR1 = 0x0;
MCF_PSC2_PSCMR2 = 0x0;
MCF_PSC2_PSCIMR = 0x0300;
MCF_PSC2_PSCSICR = 0x03; //AC97
MCF_PSC2_PSCRFCR = 0x0f000000;
MCF_PSC2_PSCTFCR = 0x0f000000;
MCF_PSC2_PSCRFAR = 0x00F0;
MCF_PSC2_PSCTFAR = 0x00F0;
for (zm = 0; zm < 100000; zm++) // wiederholen bis synchron
{
MCF_PSC2_PSCCR = 0x20;
MCF_PSC2_PSCCR = 0x30;
MCF_PSC2_PSCCR = 0x40;
MCF_PSC2_PSCCR = 0x05;
// MASTER VOLUME -0dB
MCF_PSC2_PSCTB_AC97 = 0xE0000000; //START SLOT1 + SLOT2, FIRST FRAME
MCF_PSC2_PSCTB_AC97 = 0x02000000; //SLOT1:WR REG MASTER VOLUME adr 0x02
for (i = 2; i < 13; i++)
{
MCF_PSC2_PSCTB_AC97 = 0x0; //SLOT2-12:WR REG ALLES 0
}
// read register
MCF_PSC2_PSCTB_AC97 = 0xc0000000; //START SLOT1 + SLOT2, FIRST FRAME
MCF_PSC2_PSCTB_AC97 = 0x82000000; //SLOT1:master volume
for (i = 2; i < 13; i++)
{
MCF_PSC2_PSCTB_AC97 = 0x00000000; //SLOT2-12:RD REG ALLES 0
}
wait(50);
va = MCF_PSC2_PSCTB_AC97;
if ((va & 0x80000fff) == 0x80000800) {
vb = MCF_PSC2_PSCTB_AC97;
vc = MCF_PSC2_PSCTB_AC97;
/* FIXME: that looks more than suspicious (Fredi?) */
/* fixed with parentheses to avoid compiler warnings, but this looks still more than wrong to me */
if (((va & 0xE0000fff) == 0xE0000800) & (vb == 0x02000000) & (vc == 0x00000000)) {
goto livo;
}
}
}
uart_out_word(' NOT');
livo:
// AUX VOLUME ->-0dB
MCF_PSC2_PSCTB_AC97 = 0xE0000000; //START SLOT1 + SLOT2, FIRST FRAME
MCF_PSC2_PSCTB_AC97 = 0x16000000; //SLOT1:WR REG AUX VOLUME adr 0x16
MCF_PSC2_PSCTB_AC97 = 0x06060000; //SLOT1:VOLUME
for (i = 3; i < 13; i++) {
MCF_PSC2_PSCTB_AC97 = 0x0; //SLOT2-12:WR REG ALLES 0
}
// line in VOLUME +12dB
MCF_PSC2_PSCTB_AC97 = 0xE0000000; //START SLOT1 + SLOT2, FIRST FRAME
MCF_PSC2_PSCTB_AC97 = 0x10000000; //SLOT1:WR REG MASTER VOLUME adr 0x02
for (i = 2; i < 13; i++) {
MCF_PSC2_PSCTB_AC97 = 0x0; //SLOT2-12:WR REG ALLES 0
}
// cd in VOLUME 0dB
MCF_PSC2_PSCTB_AC97 = 0xE0000000; //START SLOT1 + SLOT2, FIRST FRAME
MCF_PSC2_PSCTB_AC97 = 0x12000000; //SLOT1:WR REG MASTER VOLUME adr 0x02
for (i = 2; i < 13; i++) {
MCF_PSC2_PSCTB_AC97 = 0x0; //SLOT2-12:WR REG ALLES 0
}
// mono out VOLUME 0dB
MCF_PSC2_PSCTB_AC97 = 0xE0000000; //START SLOT1 + SLOT2, FIRST FRAME
MCF_PSC2_PSCTB_AC97 = 0x06000000; //SLOT1:WR REG MASTER VOLUME adr 0x02
MCF_PSC2_PSCTB_AC97 = 0x00000000; //SLOT1:WR REG MASTER VOLUME adr 0x02
for (i = 3; i < 13; i++) {
MCF_PSC2_PSCTB_AC97 = 0x0; //SLOT2-12:WR REG ALLES 0
}
MCF_PSC2_PSCTFCR |= MCF_PSC_PSCTFCR_WFR; //set EOF
MCF_PSC2_PSCTB_AC97 = 0x00000000; //last data
xprintf(" finished\r\n");
}
/* Symbols from the linker script */
extern uint8_t _STRAM_END[];
#define STRAM_END ((uint32_t)_STRAM_END)
extern uint8_t _FIRETOS[];
#define FIRETOS ((uint32_t)_FIRETOS) /* where FireTOS is stored in flash */
extern uint8_t _BAS_LMA[];
#define BAS_LMA ((uint32_t)_BAS_LMA) /* where the BaS is stored in flash */
extern uint8_t _BAS_IN_RAM[];
#define BAS_IN_RAM ((uint32_t)_BAS_IN_RAM) /* where the BaS is run in RAM */
extern uint8_t _BAS_SIZE[];
#define BAS_SIZE ((uint32_t)_BAS_SIZE) /* size of the BaS, in bytes */
void initialize_hardware(void) {
/* used in copy loop */
uint32_t *src; /* src address to read from flash */
uint32_t *end; /* end address to read from flash */
uint32_t *dst; /* destination address to copy to */
/* Test for FireTOS switch: DIP switch #5 up */
if (!(DIP_SWITCH & (1 << 6))) {
/* Minimal hardware initialization */
init_gpio();
init_serial();
init_slt();
init_fbcs();
init_ddram();
init_fpga();
/* FireTOS seems to have trouble to initialize the ST-RAM by itself, so... */
/* Validate ST RAM */
* (volatile uint32_t *) 0x42e = STRAM_END; /* phystop TOS system variable */
* (volatile uint32_t *) 0x420 = 0x752019f3; /* memvalid TOS system variable */
* (volatile uint32_t *) 0x43a = 0x237698aa; /* memval2 TOS system variable */
* (volatile uint32_t *) 0x51a = 0x5555aaaa; /* memval3 TOS system variable */
/* Jump into FireTOS */
typedef void void_func(void);
void_func* FireTOS = (void_func*)FIRETOS;
FireTOS(); // Should never return
return;
}
init_gpio();
init_serial();
init_slt();
init_fbcs();
init_ddram();
init_PCI();
init_fpga();
init_pll();
init_video_ddr();
dvi_on();
test_upd720101();
//video_1280_1024();
init_ac97();
/* copy the BaS code contained in flash to its final location */
src = (uint32_t *)BAS_LMA;
end = (uint32_t *)(BAS_LMA + BAS_SIZE);
dst = (uint32_t *)BAS_IN_RAM;
/* The linker script will ensure that the Bas size
* is a multiple of the following.
*/
while (src < end)
{
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
}
/* we have copied a code area, so flush the caches */
flush_and_invalidate_caches();
/* jump into the BaS in RAM */
extern void BaS(void);
BaS();
}

View File

@@ -0,0 +1,17 @@
#include <ff.h>
#if _USE_LFN != 0
#if _CODE_PAGE == 932
#include "cc932.c"
#elif _CODE_PAGE == 936
#include "cc936.c"
#elif _CODE_PAGE == 949
#include "cc949.c"
#elif _CODE_PAGE == 950
#include "cc950.c"
#else
#include "ccsbcs.c"
#endif
#endif

View File

@@ -0,0 +1,31 @@
/*
* wait.c
*
* Created on: 10.12.2012
* Author: mfro
*
* This file is part of BaS_gcc.
*
* BaS_gcc 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.
*
* BaS_gcc 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 BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2010 - 2012 F. Aschwanden
* Copyright 2011 - 2012 V. Riviere
* Copyright 2012 M. Froeschle
*
*/
#include <stdint.h>
#include <MCF5475.h>
#include <wait.h>