equivalent of corresponding file release
This commit is contained in:
336
BaS_gcc/sources/BaS.c
Normal file
336
BaS_gcc/sources/BaS.c
Normal file
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* 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_string.h"
|
||||
#include "bas_types.h"
|
||||
#include "sd_card.h"
|
||||
#include "wait.h"
|
||||
|
||||
#include "diskio.h"
|
||||
#include "ff.h"
|
||||
#include "s19reader.h"
|
||||
#include "dma.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 */
|
||||
|
||||
#define NOP() __asm__ __volatile__("nop\n\t" : : : "memory") /* need this to force pipeline sync after MMUCR write */
|
||||
|
||||
/*
|
||||
* 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");
|
||||
}
|
||||
|
||||
#define KBD_ACIA_CONTROL ((uint8_t *) 0xfffffc00)
|
||||
#define MIDI_ACIA_CONTROL ((uint8_t *) 0xfffffc04)
|
||||
#define MFP_INTR_IN_SERVICE_A ((uint8_t *) 0xfffffa0f)
|
||||
#define MFP_INTR_IN_SERVICE_B ((uint8_t *) 0xfffffa11)
|
||||
|
||||
void acia_init()
|
||||
{
|
||||
xprintf("init ACIA: ");
|
||||
/* init ACIA */
|
||||
* KBD_ACIA_CONTROL = 3; /* master reset */
|
||||
NOP();
|
||||
|
||||
* MIDI_ACIA_CONTROL = 3; /* master reset */
|
||||
NOP();
|
||||
|
||||
* KBD_ACIA_CONTROL = 0x96; /* clock div = 64, 8N1, RTS low, TX int disable, RX int enable */
|
||||
NOP();
|
||||
|
||||
* MFP_INTR_IN_SERVICE_A = -1;
|
||||
NOP();
|
||||
|
||||
* MFP_INTR_IN_SERVICE_B = -1;
|
||||
NOP();
|
||||
|
||||
xprintf("finished\r\n");
|
||||
}
|
||||
|
||||
/* ACP interrupt controller */
|
||||
#define FPGA_INTR_CONTRL (volatile uint32_t *) 0xf0010000
|
||||
#define FPGA_INTR_ENABLE (volatile uint8_t *) 0xf0010004
|
||||
#define FPGA_INTR_PENDIN (volatile uint32_t *) 0xf0010008
|
||||
|
||||
void enable_coldfire_interrupts()
|
||||
{
|
||||
xprintf("enable interrupts: ");
|
||||
*FPGA_INTR_CONTRL = 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);
|
||||
/* route GPT0 interrupt on interrupt controller */
|
||||
MCF_INTC_ICR62 = 0x3f; /* interrupt level 7, interrupt priority 7 */
|
||||
|
||||
*FPGA_INTR_ENABLE = 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()
|
||||
{
|
||||
*FPGA_INTR_ENABLE = 0; /* disable all interrupts */
|
||||
MCF_EPORT_EPIER = 0x0;
|
||||
MCF_EPORT_EPFR = 0x0;
|
||||
MCF_INTC_IMRL = 0xfffffffe;
|
||||
MCF_INTC_IMRH = 0xffffffff;
|
||||
}
|
||||
|
||||
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;
|
||||
memcpy(dst, src, EMUTOS_SIZE);
|
||||
xprintf("finished\r\n");
|
||||
|
||||
xprintf("initialize MMU: ");
|
||||
mmu_init();
|
||||
xprintf("finished\r\n");
|
||||
|
||||
xprintf("initialize exception vector table: ");
|
||||
vec_init();
|
||||
xprintf("finished\r\n");
|
||||
|
||||
xprintf("flush caches and enable MMU: ");
|
||||
flush_and_invalidate_caches();
|
||||
MCF_MMU_MMUCR = MCF_MMU_MMUCR_EN; /* MMU on */
|
||||
NOP(); /* force pipeline sync */
|
||||
xprintf("finished\r\n");
|
||||
|
||||
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
|
||||
* (volatile uint32_t *) (0xf0000410 + 0) = 0x037002ba; /* horizontal 640x480 */
|
||||
* (volatile uint32_t *) (0xf0000410 + 4) = 0x020d020a; /* vertical 640x480 */
|
||||
* (volatile uint32_t *) (0xf0000410 + 8) = 0x02a001e0; /* horizontal 320x240 */
|
||||
* (volatile uint32_t *) (0xf0000410 + 12) = 0x05a00160; /* vertical 320x230 */
|
||||
#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;
|
||||
}
|
||||
|
||||
/* set Falcon bus control register */
|
||||
/* sets bit 3 and 6. Both are undefined on an original Falcon? */
|
||||
|
||||
* (volatile uint8_t *) 0xffff8007 = 0x48;
|
||||
|
||||
/* 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 *) 0x5a4 = 0x1d000000;
|
||||
* (uint32_t *) 0x5a8 = 0x1357bd13; /* ramvalid TOS system variable */
|
||||
|
||||
acia_init();
|
||||
|
||||
/* 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("initialize and test DMA\r\n");
|
||||
dma_init();
|
||||
|
||||
xprintf("BaS initialization finished, enable interrupts\r\n");
|
||||
enable_coldfire_interrupts();
|
||||
|
||||
xprintf("call EmuTOS\r\n");
|
||||
ROM_HEADER* os_header = (ROM_HEADER*)TOS;
|
||||
os_header->initial_pc();
|
||||
}
|
||||
403
BaS_gcc/sources/bas_printf.c
Normal file
403
BaS_gcc/sources/bas_printf.c
Normal file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* 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)";
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
void hexdump(uint8_t buffer[], int size)
|
||||
{
|
||||
int i;
|
||||
int line = 0;
|
||||
uint8_t *bp = buffer;
|
||||
|
||||
while (bp < buffer + size) {
|
||||
uint8_t *lbp = bp;
|
||||
|
||||
xprintf("%08x ", line);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (bp + i > buffer + size) {
|
||||
break;
|
||||
}
|
||||
xprintf("%02x ", (uint8_t) *lbp++);
|
||||
}
|
||||
|
||||
lbp = bp;
|
||||
for (i = 0; i < 16; i++) {
|
||||
int8_t c = *lbp++;
|
||||
|
||||
if (bp + i > buffer + size) {
|
||||
break;
|
||||
}
|
||||
if (c > ' ' && c < '~') {
|
||||
xprintf("%c", c);
|
||||
} else {
|
||||
xprintf(".");
|
||||
}
|
||||
}
|
||||
xprintf("\r\n");
|
||||
|
||||
bp += 16;
|
||||
line += 16;
|
||||
}
|
||||
}
|
||||
102
BaS_gcc/sources/bas_string.c
Normal file
102
BaS_gcc/sources/bas_string.c
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* bas_string.c
|
||||
*
|
||||
* Created on: 26.02.2013
|
||||
* Author: mfro
|
||||
*/
|
||||
|
||||
#include "bas_types.h"
|
||||
#include <stdint.h>
|
||||
#include "bas_string.h"
|
||||
|
||||
void *memcpy(void *dst, const void *src, size_t n)
|
||||
{
|
||||
uint8_t *to = dst;
|
||||
|
||||
while (to < (uint8_t *) dst + n)
|
||||
*to++ = * (uint8_t *) src++;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void bzero(void *s, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
((unsigned char *) s)[i] = '\0';
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
char *strncpy(char *dst, const char *src, int max)
|
||||
{
|
||||
char *ptr = dst;
|
||||
|
||||
while ((*dst++ = *src++) != '\0' && max-- >= 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;
|
||||
}
|
||||
652
BaS_gcc/sources/basflash.c
Normal file
652
BaS_gcc/sources/basflash.c
Normal file
@@ -0,0 +1,652 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#define AMD_FLASH_BUS_SHIFT 1
|
||||
#define AMD_FLASH_CELL volatile uint16_t
|
||||
#define AMD_FLASH_CELL_BYTES 2
|
||||
#define AMD_FLASH_CELL_MASK 0x1
|
||||
#define AMD_FLASH_CMD_DATA(x) ((uint16_t) x)
|
||||
|
||||
struct amd_flash_sector_info
|
||||
{
|
||||
uint32_t size; /* sector size in bytes */
|
||||
uint32_t offset; /* offset from base of device */
|
||||
};
|
||||
|
||||
/*
|
||||
* AM29LV640D flash layout (bottom boot as used in the Firebee )
|
||||
*/
|
||||
static struct amd_flash_sector_info sector[] =
|
||||
{
|
||||
{ 8 * 1024, 0x00000000 }, /* SA0 */
|
||||
{ 8 * 1024, 0x00008000 }, /* SA1 */
|
||||
{ 8 * 1024, 0x00010000 }, /* SA2 */
|
||||
{ 8 * 1024, 0x00018000 }, /* SA3 */
|
||||
{ 8 * 1024, 0x00020000 }, /* SA4 */
|
||||
{ 8 * 1024, 0x00028000 }, /* SA5 */
|
||||
{ 8 * 1024, 0x00030000 }, /* SA6 */
|
||||
{ 8 * 1024, 0x00038000 }, /* SA7 */
|
||||
{ 8 * 1024, 0x00040000 }, /* SA8 */
|
||||
{ 64 * 1024, 0x00048000 }, /* SA9 */
|
||||
{ 64 * 1024, 0x00050000 }, /* SA10 */
|
||||
{ 64 * 1024, 0x00058000 }, /* SA11 */
|
||||
{ 64 * 1024, 0x00060000 }, /* SA12 */
|
||||
{ 64 * 1024, 0x00068000 }, /* SA13 */
|
||||
{ 64 * 1024, 0x00070000 }, /* SA14 */
|
||||
{ 64 * 1024, 0x00078000 }, /* SA15 */
|
||||
{ 64 * 1024, 0x00080000 }, /* SA16 */
|
||||
{ 64 * 1024, 0x00088000 }, /* SA17 */
|
||||
{ 64 * 1024, 0x00090000 }, /* SA18 */
|
||||
{ 64 * 1024, 0x00098000 }, /* SA19 */
|
||||
{ 64 * 1024, 0x000a0000 }, /* SA20 */
|
||||
{ 64 * 1024, 0x000a8000 }, /* SA21 */
|
||||
{ 64 * 1024, 0x000b0000 }, /* SA22 */
|
||||
{ 64 * 1024, 0x000b8000 }, /* SA23 */
|
||||
{ 64 * 1024, 0x000c0000 }, /* SA24 */
|
||||
{ 64 * 1024, 0x000c8000 }, /* SA25 */
|
||||
{ 64 * 1024, 0x000d0000 }, /* SA26 */
|
||||
{ 64 * 1024, 0x000d8000 }, /* SA27 */
|
||||
{ 64 * 1024, 0x000e0000 }, /* SA28 */
|
||||
{ 64 * 1024, 0x000e8000 }, /* SA29 */
|
||||
{ 64 * 1024, 0x000f0000 }, /* SA30 */
|
||||
{ 64 * 1024, 0x000f8000 }, /* SA31 */
|
||||
{ 64 * 1024, 0x00100000 }, /* SA32 */
|
||||
{ 64 * 1024, 0x00108000 }, /* SA32 */
|
||||
{ 64 * 1024, 0x00110000 }, /* SA34 */
|
||||
{ 64 * 1024, 0x00118000 }, /* SA35 */
|
||||
{ 64 * 1024, 0x00120000 }, /* SA36 */
|
||||
{ 64 * 1024, 0x00128000 }, /* SA37 */
|
||||
{ 64 * 1024, 0x00130000 }, /* SA38 */
|
||||
{ 64 * 1024, 0x00138000 }, /* SA39 */
|
||||
{ 64 * 1024, 0x00140000 }, /* SA40 */
|
||||
{ 64 * 1024, 0x00148000 }, /* SA41 */
|
||||
{ 64 * 1024, 0x00150000 }, /* SA42 */
|
||||
{ 64 * 1024, 0x00158000 }, /* SA43 */
|
||||
{ 64 * 1024, 0x00160000 }, /* SA44 */
|
||||
{ 64 * 1024, 0x00168000 }, /* SA45 */
|
||||
{ 64 * 1024, 0x00170000 }, /* SA46 */
|
||||
{ 64 * 1024, 0x00178000 }, /* SA47 */
|
||||
{ 64 * 1024, 0x00180000 }, /* SA48 */
|
||||
{ 64 * 1024, 0x00188000 }, /* SA49 */
|
||||
{ 64 * 1024, 0x00190000 }, /* SA50 */
|
||||
{ 64 * 1024, 0x00198000 }, /* SA51 */
|
||||
{ 64 * 1024, 0x001a0000 }, /* SA52 */
|
||||
{ 64 * 1024, 0x001a8000 }, /* SA53 */
|
||||
{ 64 * 1024, 0x001b0000 }, /* SA54 */
|
||||
{ 64 * 1024, 0x001b8000 }, /* SA55 */
|
||||
{ 64 * 1024, 0x001c0000 }, /* SA56 */
|
||||
{ 64 * 1024, 0x001c8000 }, /* SA57 */
|
||||
{ 64 * 1024, 0x001d0000 }, /* SA58 */
|
||||
{ 64 * 1024, 0x001d8000 }, /* SA59 */
|
||||
{ 64 * 1024, 0x001e0000 }, /* SA60 */
|
||||
{ 64 * 1024, 0x001e8000 }, /* SA61 */
|
||||
{ 64 * 1024, 0x001f0000 }, /* SA62 */
|
||||
{ 64 * 1024, 0x001f8000 }, /* SA63 */
|
||||
{ 64 * 1024, 0x00200000 }, /* SA64 */
|
||||
{ 64 * 1024, 0x00208000 }, /* SA65 */
|
||||
{ 64 * 1024, 0x00210000 }, /* SA66 */
|
||||
{ 64 * 1024, 0x00218000 }, /* SA67 */
|
||||
{ 64 * 1024, 0x00220000 }, /* SA68 */
|
||||
{ 64 * 1024, 0x00228000 }, /* SA69 */
|
||||
{ 64 * 1024, 0x00230000 }, /* SA70 */
|
||||
{ 64 * 1024, 0x00238000 }, /* SA71 */
|
||||
{ 64 * 1024, 0x00240000 }, /* SA72 */
|
||||
{ 64 * 1024, 0x00248000 }, /* SA73 */
|
||||
{ 64 * 1024, 0x00250000 }, /* SA74 */
|
||||
{ 64 * 1024, 0x00258000 }, /* SA75 */
|
||||
{ 64 * 1024, 0x00260000 }, /* SA76 */
|
||||
{ 64 * 1024, 0x00268000 }, /* SA77 */
|
||||
{ 64 * 1024, 0x00270000 }, /* SA78 */
|
||||
{ 64 * 1024, 0x00278000 }, /* SA79 */
|
||||
{ 64 * 1024, 0x00280000 }, /* SA80 */
|
||||
{ 64 * 1024, 0x00288000 }, /* SA81 */
|
||||
{ 64 * 1024, 0x00290000 }, /* SA82 */
|
||||
{ 64 * 1024, 0x00298000 }, /* SA83 */
|
||||
{ 64 * 1024, 0x002a0000 }, /* SA84 */
|
||||
{ 64 * 1024, 0x002a8000 }, /* SA85 */
|
||||
{ 64 * 1024, 0x002b0000 }, /* SA86 */
|
||||
{ 64 * 1024, 0x002b8000 }, /* SA87 */
|
||||
{ 64 * 1024, 0x002c0000 }, /* SA88 */
|
||||
{ 64 * 1024, 0x002c8000 }, /* SA89 */
|
||||
{ 64 * 1024, 0x002d0000 }, /* SA90 */
|
||||
{ 64 * 1024, 0x002d8000 }, /* SA91 */
|
||||
{ 64 * 1024, 0x002e0000 }, /* SA92 */
|
||||
{ 64 * 1024, 0x002e8000 }, /* SA93 */
|
||||
{ 64 * 1024, 0x002f0000 }, /* SA94 */
|
||||
{ 64 * 1024, 0x002f8000 }, /* SA95 */
|
||||
{ 64 * 1024, 0x00300000 }, /* SA96 */
|
||||
{ 64 * 1024, 0x00308000 }, /* SA97 */
|
||||
{ 64 * 1024, 0x00310000 }, /* SA98 */
|
||||
{ 64 * 1024, 0x00318000 }, /* SA99 */
|
||||
{ 64 * 1024, 0x00320000 }, /* SA100 */
|
||||
{ 64 * 1024, 0x00328000 }, /* SA101 */
|
||||
{ 64 * 1024, 0x00330000 }, /* SA102 */
|
||||
{ 64 * 1024, 0x00338000 }, /* SA103 */
|
||||
{ 64 * 1024, 0x00340000 }, /* SA104 */
|
||||
{ 64 * 1024, 0x00348000 }, /* SA105 */
|
||||
{ 64 * 1024, 0x00350000 }, /* SA106 */
|
||||
{ 64 * 1024, 0x00358000 }, /* SA107 */
|
||||
{ 64 * 1024, 0x00360000 }, /* SA108 */
|
||||
{ 64 * 1024, 0x00368000 }, /* SA109 */
|
||||
{ 64 * 1024, 0x00370000 }, /* SA110 */
|
||||
{ 64 * 1024, 0x00378000 }, /* SA111 */
|
||||
{ 64 * 1024, 0x00380000 }, /* SA112 */
|
||||
{ 64 * 1024, 0x00388000 }, /* SA113 */
|
||||
{ 64 * 1024, 0x00390000 }, /* SA114 */
|
||||
{ 64 * 1024, 0x00398000 }, /* SA115 */
|
||||
{ 64 * 1024, 0x003a0000 }, /* SA116 */
|
||||
{ 64 * 1024, 0x003a8000 }, /* SA117 */
|
||||
{ 64 * 1024, 0x003b0000 }, /* SA118 */
|
||||
{ 64 * 1024, 0x003b8000 }, /* SA119 */
|
||||
{ 64 * 1024, 0x003c0000 }, /* SA120 */
|
||||
{ 64 * 1024, 0x003c8000 }, /* SA121 */
|
||||
{ 64 * 1024, 0x003d0000 }, /* SA122 */
|
||||
{ 64 * 1024, 0x003d8000 }, /* SA123 */
|
||||
{ 64 * 1024, 0x003e0000 }, /* SA124 */
|
||||
{ 64 * 1024, 0x003e8000 }, /* SA125 */
|
||||
{ 64 * 1024, 0x003f0000 }, /* SA126 */
|
||||
{ 64 * 1024, 0x003f8000 }, /* SA127 */
|
||||
};
|
||||
|
||||
static const int AMD_FLASH_SECTORS = sizeof(sector) / sizeof(struct amd_flash_sector_info);
|
||||
|
||||
#define SOFFSET(n) (sector[n].offset)
|
||||
#define SADDR(n) (SOFFSET(n) >> AMD_FLASH_BUS_SHIFT)
|
||||
#define SSIZE(n) (sector[n].size)
|
||||
|
||||
#define AMD_FLASH_DEVICES 1
|
||||
|
||||
static AMD_FLASH_CELL *pFlash;
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* erase a flash sector
|
||||
*
|
||||
* sector_num is the index into the sector table above.
|
||||
*
|
||||
* FIXME: need to disable data cache to ensure proper operation
|
||||
*/
|
||||
void amd_flash_sector_erase(int n)
|
||||
{
|
||||
volatile AMD_FLASH_CELL status;
|
||||
|
||||
pFlash[0x555] = AMD_FLASH_CMD_DATA(0xAA);
|
||||
pFlash[0x2AA] = AMD_FLASH_CMD_DATA(0x55);
|
||||
pFlash[0x555] = AMD_FLASH_CMD_DATA(0x80);
|
||||
pFlash[0x555] = AMD_FLASH_CMD_DATA(0xAA);
|
||||
pFlash[0x2AA] = AMD_FLASH_CMD_DATA(0x55);
|
||||
pFlash[SADDR(n)] = AMD_FLASH_CMD_DATA(0x30);
|
||||
|
||||
do
|
||||
status = pFlash[SADDR(n)];
|
||||
while ((status & AMD_FLASH_CMD_DATA(0x80)) != AMD_FLASH_CMD_DATA(0x80));
|
||||
|
||||
/*
|
||||
* Place device in read mode
|
||||
*/
|
||||
pFlash[0] = AMD_FLASH_CMD_DATA(0xAA);
|
||||
pFlash[0] = AMD_FLASH_CMD_DATA(0x55);
|
||||
pFlash[0] = AMD_FLASH_CMD_DATA(0xF0);
|
||||
}
|
||||
|
||||
int amd_flash_erase(void *start, int bytes, void (*putchar)(int))
|
||||
{
|
||||
int i, ebytes = 0;
|
||||
|
||||
if (bytes == 0)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < AMD_FLASH_SECTORS; i++)
|
||||
{
|
||||
if (start >= (void *)((void *) pFlash + SOFFSET(i)) &&
|
||||
start <= (void *)((void *) pFlash + SOFFSET(i) + (SSIZE(i) - 1)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (ebytes < bytes)
|
||||
{
|
||||
if (putchar != NULL)
|
||||
{
|
||||
putchar('.');
|
||||
}
|
||||
amd_flash_sector_erase(i);
|
||||
ebytes += SSIZE(i);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (putchar != NULL)
|
||||
{
|
||||
putchar(10); /* LF */
|
||||
putchar(13); /* CR */
|
||||
}
|
||||
|
||||
return ebytes;
|
||||
}
|
||||
|
||||
void amd_flash_program_cell(AMD_FLASH_CELL *dst, AMD_FLASH_CELL data)
|
||||
{
|
||||
volatile AMD_FLASH_CELL status;
|
||||
int retry;
|
||||
|
||||
pFlash[0x555] = AMD_FLASH_CMD_DATA(0xAA);
|
||||
pFlash[0x2AA] = AMD_FLASH_CMD_DATA(0x55);
|
||||
pFlash[0x555] = AMD_FLASH_CMD_DATA(0xA0);
|
||||
*dst = data;
|
||||
|
||||
/*
|
||||
* Wait for program operation to finish
|
||||
* (Data# Polling Algorithm)
|
||||
*/
|
||||
retry = 0;
|
||||
while (1)
|
||||
{
|
||||
status = *dst;
|
||||
if ((status & AMD_FLASH_CMD_DATA(0x80)) ==
|
||||
(data & AMD_FLASH_CMD_DATA(0x80)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (status & AMD_FLASH_CMD_DATA(0x20))
|
||||
{
|
||||
status = *dst;
|
||||
if ((status & AMD_FLASH_CMD_DATA(0x80)) ==
|
||||
(data & AMD_FLASH_CMD_DATA(0x80)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (++retry > 1024)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int amd_flash_program(void *dest, void *source, int bytes, int erase, void (*func)(void), void (*putchar)(int))
|
||||
{
|
||||
AMD_FLASH_CELL *src, *dst;
|
||||
int hashi=1,hashj=0;
|
||||
char hash[5];
|
||||
|
||||
hash[0]=8; /* Backspace */
|
||||
hash[1]=124;/* "|" */
|
||||
hash[2]=47; /* "/" */
|
||||
hash[3]=45; /* "-" */
|
||||
hash[4]=92; /* "\" */
|
||||
|
||||
src = (AMD_FLASH_CELL *)source;
|
||||
dst = (AMD_FLASH_CELL *)dest;
|
||||
|
||||
/*
|
||||
* Place device in read mode
|
||||
*/
|
||||
pFlash[0] = AMD_FLASH_CMD_DATA(0xAA);
|
||||
pFlash[0] = AMD_FLASH_CMD_DATA(0x55);
|
||||
pFlash[0] = AMD_FLASH_CMD_DATA(0xF0);
|
||||
|
||||
/*
|
||||
* Erase device if necessary
|
||||
*/
|
||||
if (erase)
|
||||
{
|
||||
amd_flash_erase(dest, bytes, putchar);
|
||||
}
|
||||
|
||||
/*
|
||||
* Program device
|
||||
*/
|
||||
while (bytes > 0)
|
||||
{
|
||||
amd_flash_program_cell(dst,*src);
|
||||
|
||||
/* Verify Write */
|
||||
if (*dst == *src)
|
||||
{
|
||||
bytes -= AMD_FLASH_CELL_BYTES;
|
||||
*dst++, *src++;
|
||||
|
||||
if ((putchar != NULL))
|
||||
{
|
||||
/* Hash marks to indicate progress */
|
||||
if (hashj == 0x1000)
|
||||
{
|
||||
hashj = -1;
|
||||
putchar(hash[0]);
|
||||
putchar(hash[hashi]);
|
||||
|
||||
hashi++;
|
||||
if (hashi == 5)
|
||||
{
|
||||
hashi=1;
|
||||
}
|
||||
|
||||
}
|
||||
hashj++;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Place device in read mode
|
||||
*/
|
||||
pFlash[0] = AMD_FLASH_CMD_DATA(0xAA);
|
||||
pFlash[0] = AMD_FLASH_CMD_DATA(0x55);
|
||||
pFlash[0] = AMD_FLASH_CMD_DATA(0xF0);
|
||||
|
||||
if (putchar != NULL)
|
||||
{
|
||||
putchar(hash[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* If a function was passed in, call it now
|
||||
*/
|
||||
if ((func != NULL))
|
||||
{
|
||||
func();
|
||||
}
|
||||
|
||||
return ((int)src - (int)source);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 flash(uint8_t *dst, uint8_t *src, uint32_t length)
|
||||
{
|
||||
err_t ret = OK;
|
||||
|
||||
/* TODO: do the actual flash */
|
||||
amd_flash_program(dst, src, length, 1, NULL, xputchar);
|
||||
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, size_t length)
|
||||
{
|
||||
uint8_t *end = src + length;
|
||||
|
||||
do
|
||||
{
|
||||
if (*src++ != *dst++)
|
||||
return FAIL;
|
||||
} while (src < end);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
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 = amd_flash_erase(start_address, length, xputchar);
|
||||
|
||||
/* next pass: copy data to destination */
|
||||
xprintf("OK.\r\flash data: ");
|
||||
err = read_srecords(flash_filename, &start_address, &length, flash);
|
||||
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 */
|
||||
}
|
||||
}
|
||||
26
BaS_gcc/sources/basflash_start.c
Normal file
26
BaS_gcc/sources/basflash_start.c
Normal 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 */
|
||||
}
|
||||
145
BaS_gcc/sources/cache.c
Normal file
145
BaS_gcc/sources/cache.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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 cacr_set(uint32_t value)
|
||||
{
|
||||
extern uint32_t rt_cacr;
|
||||
|
||||
rt_cacr = value;
|
||||
__asm__ __volatile__("movec %0, cacr\n\t"
|
||||
: /* output */
|
||||
: "r" (rt_cacr)
|
||||
: /* clobbers */);
|
||||
}
|
||||
|
||||
uint32_t cacr_get(void)
|
||||
{
|
||||
extern uint32_t rt_cacr;
|
||||
|
||||
return rt_cacr;
|
||||
}
|
||||
|
||||
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"
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* flush and invalidate a specific memory region from the instruction cache
|
||||
*/
|
||||
void flush_icache_range(void *address, size_t size)
|
||||
{
|
||||
uint32_t set;
|
||||
uint32_t start_set;
|
||||
uint32_t end_set;
|
||||
void *endaddr = address + size;
|
||||
|
||||
start_set = (uint32_t) address & _ICACHE_SET_MASK;
|
||||
end_set = (uint32_t) endaddr & _ICACHE_SET_MASK;
|
||||
|
||||
if (start_set > end_set) {
|
||||
/* from the begining to the lowest address */
|
||||
for (set = 0; set <= end_set; set += (0x10 - 3)) {
|
||||
asm volatile("cpushl ic,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl ic,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl ic,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl ic,(%0)" : "=a" (set) : "a" (set));
|
||||
}
|
||||
/* next loop will finish the cache ie pass the hole */
|
||||
end_set = LAST_ICACHE_ADDR;
|
||||
}
|
||||
for (set = start_set; set <= end_set; set += (0x10 - 3)) {
|
||||
asm volatile("cpushl ic,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl ic,(%0)\n\t"
|
||||
"addq%.l #1,%0\n\t"
|
||||
"cpushl ic,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl ic,(%0)" : "=a" (set) : "a" (set));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* flush and invalidate a specific region from the data cache
|
||||
*/
|
||||
void flush_dcache_range(void *address, size_t size)
|
||||
{
|
||||
unsigned long set;
|
||||
unsigned long start_set;
|
||||
unsigned long end_set;
|
||||
void *endaddr;
|
||||
|
||||
endaddr = address + size;
|
||||
start_set = (uint32_t) address & _DCACHE_SET_MASK;
|
||||
end_set = (uint32_t) endaddr & _DCACHE_SET_MASK;
|
||||
|
||||
if (start_set > end_set) {
|
||||
/* from the begining to the lowest address */
|
||||
for (set = 0; set <= end_set; set += (0x10 - 3)) {
|
||||
asm volatile("cpushl dc,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl dc,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl dc,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl dc,(%0)" : "=a" (set) : "a" (set));
|
||||
}
|
||||
/* next loop will finish the cache ie pass the hole */
|
||||
end_set = LAST_DCACHE_ADDR;
|
||||
}
|
||||
for (set = start_set; set <= end_set; set += (0x10 - 3)) {
|
||||
asm volatile("cpushl dc,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl dc,(%0)\n\t"
|
||||
"addq%.l #1,%0\n\t"
|
||||
"cpushl dc,(%0)\n\t"
|
||||
"addq.l #1,%0\n\t"
|
||||
"cpushl dc,(%0)" : "=a" (set) : "a" (set));
|
||||
}
|
||||
}
|
||||
3798
BaS_gcc/sources/cc932.c
Normal file
3798
BaS_gcc/sources/cc932.c
Normal file
File diff suppressed because it is too large
Load Diff
10973
BaS_gcc/sources/cc936.c
Normal file
10973
BaS_gcc/sources/cc936.c
Normal file
File diff suppressed because it is too large
Load Diff
8603
BaS_gcc/sources/cc949.c
Normal file
8603
BaS_gcc/sources/cc949.c
Normal file
File diff suppressed because it is too large
Load Diff
6829
BaS_gcc/sources/cc950.c
Normal file
6829
BaS_gcc/sources/cc950.c
Normal file
File diff suppressed because it is too large
Load Diff
540
BaS_gcc/sources/ccsbcs.c
Normal file
540
BaS_gcc/sources/ccsbcs.c
Normal 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;
|
||||
}
|
||||
176
BaS_gcc/sources/dma.c
Normal file
176
BaS_gcc/sources/dma.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* dma.c
|
||||
*
|
||||
* Created on: 27.07.2013
|
||||
* Author: mfro
|
||||
*/
|
||||
|
||||
#include "dma.h"
|
||||
#include <MCD_dma.h>
|
||||
#include "mcd_initiators.h"
|
||||
#include "bas_printf.h"
|
||||
#include "bas_string.h"
|
||||
#include "cache.h"
|
||||
|
||||
extern char _SYS_SRAM[];
|
||||
#define SYS_SRAM &_SYS_SRAM[0]
|
||||
|
||||
void print_sp(void)
|
||||
{
|
||||
register char *sp asm("sp");
|
||||
xprintf("sp=%x\r\n", sp);
|
||||
}
|
||||
|
||||
|
||||
void *dma_memcpy(void *dst, void *src, size_t n)
|
||||
{
|
||||
int ret;
|
||||
volatile int32_t time;
|
||||
volatile int32_t start;
|
||||
volatile int32_t end;
|
||||
uint8_t *d;
|
||||
uint8_t *s;
|
||||
|
||||
xprintf("compare memcpy() to memory to memory DMA from %p to %p (0x%x bytes ending at 0x%x)\r\n",
|
||||
src, dst, n, dst + n);
|
||||
d = dst;
|
||||
s = src;
|
||||
|
||||
//#ifdef _NOT_USED_
|
||||
start = MCF_SLT0_SCNT;
|
||||
/* first check if we can do a "traditional" memcpy() to the destination and measure speed */
|
||||
|
||||
memcpy(d, s, n);
|
||||
|
||||
//#endif /* _NOT_USED_ */
|
||||
|
||||
end = MCF_SLT0_SCNT;
|
||||
|
||||
time = (start - end) / 132 / 1000;
|
||||
xprintf("memcpy() took %d ms (%d.%d Mbytes/second)\r\n",
|
||||
time, n / time / 1000, n / time % 1000);
|
||||
flush_and_invalidate_caches();
|
||||
//#endif
|
||||
|
||||
xprintf("clear target area after memcpy():");
|
||||
start = MCF_SLT0_SCNT;
|
||||
bzero(dst, n);
|
||||
end = MCF_SLT0_SCNT;
|
||||
time = (start - end) / 132;
|
||||
xprintf("bzero() took %d ms (%d.%d Mbytes/second)\r\n", time, n / time / 1000, n / time % 1000);
|
||||
|
||||
xprintf(" finished, flush caches: ");
|
||||
flush_and_invalidate_caches();
|
||||
xprintf("finished\r\n");
|
||||
|
||||
start = MCF_SLT0_SCNT;
|
||||
ret = MCD_startDma(1, src, 4, dst, 4, n, 4, DMA_ALWAYS, 0, MCD_SINGLE_DMA, 0);
|
||||
if (ret == MCD_OK)
|
||||
{
|
||||
xprintf("DMA on channel 1 successfully started\r\n");
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
ret = MCD_dmaStatus(1);
|
||||
switch (ret)
|
||||
{
|
||||
case MCD_NO_DMA:
|
||||
xprintf("MCD_NO_DMA: no DMA active on this channel\r\n");
|
||||
return NULL;
|
||||
break;
|
||||
case MCD_IDLE:
|
||||
xprintf("MCD_IDLE: DMA defined but not active (initiator not ready)\r\n");
|
||||
break;
|
||||
case MCD_RUNNING:
|
||||
xprintf("MCD_RUNNING: DMA active and working on this channel\r\n");
|
||||
break;
|
||||
case MCD_PAUSED:
|
||||
xprintf("MCD_PAUSED: DMA defined and enabled, but currently paused\r\n");
|
||||
break;
|
||||
case MCD_HALTED:
|
||||
xprintf("MCD_HALTED: DMA killed\r\n");
|
||||
return NULL;
|
||||
break;
|
||||
case MCD_DONE:
|
||||
xprintf("MCD_DONE: DMA finished\r\n");
|
||||
break;
|
||||
case MCD_CHANNEL_INVALID:
|
||||
xprintf("MCD_CHANNEL_INVALID: invalid DMA channel\r\n");
|
||||
return NULL;
|
||||
break;
|
||||
default:
|
||||
xprintf("unknown DMA status %d\r\n", ret);
|
||||
break;
|
||||
}
|
||||
} while (ret != MCD_DONE);
|
||||
|
||||
end = MCF_SLT0_SCNT;
|
||||
time = (start - end) / 132 / 1000;
|
||||
xprintf("start = %d, end = %d, time = %d\r\n", start, end, time);
|
||||
//xprintf("took %d ms (%d.%d Mbytes/second)\r\n", time, n / time / 1000, n / time % 1000);
|
||||
|
||||
/*
|
||||
* verify if copy succeeded
|
||||
*/
|
||||
xprintf("verify if DMA copy succeeded:\r\n");
|
||||
|
||||
xprintf("flush caches first:");
|
||||
flush_and_invalidate_caches();
|
||||
xprintf(" done.\r\n");
|
||||
|
||||
s = src;
|
||||
d = dst;
|
||||
|
||||
start = MCF_SLT0_SCNT;
|
||||
do
|
||||
{
|
||||
if (*d != *s)
|
||||
{
|
||||
xprintf("copy verification failed: %d (%p) != %d (%p) !\r\n", *d, d, *s, s);
|
||||
break;
|
||||
}
|
||||
d++; s++;
|
||||
} while (d < (uint8_t *) dst + n);
|
||||
if (d >= (uint8_t *) dst + n)
|
||||
{
|
||||
xprintf("DMA copy verification successful!\r\n");
|
||||
end = MCF_SLT0_SCNT;
|
||||
|
||||
time = (start - end) / 132 / 1000;
|
||||
xprintf("took %d ms (%d.%d Mbytes/second)\r\n", time, n / time / 1000, n / time % 1000);
|
||||
|
||||
}
|
||||
|
||||
#ifdef _NOT_USED_
|
||||
__asm__ __volatile__("move.w sr,d0\n\t"
|
||||
"stop #0x2700\n\t"
|
||||
"move.w d0,sr": : :); /* halt CPU until DMA finished */
|
||||
#endif /* _NOT_USED_ */
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
int dma_init(void)
|
||||
{
|
||||
int res;
|
||||
int version;
|
||||
char *long_version;
|
||||
|
||||
xprintf("MCD DMA API initialization: ");
|
||||
res = MCD_initDma((dmaRegs *) &_MBAR[0x8000], SYS_SRAM, MCD_RELOC_TASKS | MCD_COMM_PREFETCH_EN);
|
||||
if (res != MCD_OK)
|
||||
{
|
||||
xprintf("DMA API initialization failed (0x%x)\r\n", res);
|
||||
return 0;
|
||||
}
|
||||
version = MCD_getVersion(&long_version);
|
||||
xprintf("DMA API version %d.%d initialized. Tasks are at %p\r\n", version / 0xff, version % 0xff, SYS_SRAM);
|
||||
|
||||
// test
|
||||
dma_memcpy((void *) 0x01000000, (void *) 0xe0000000, 0x00100000); /* copy one megabyte of flash to RAM */
|
||||
|
||||
xprintf("DMA finished\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
1029
BaS_gcc/sources/exceptions.S
Normal file
1029
BaS_gcc/sources/exceptions.S
Normal file
File diff suppressed because it is too large
Load Diff
183
BaS_gcc/sources/fault_vectors.c
Normal file
183
BaS_gcc/sources/fault_vectors.c
Normal file
@@ -0,0 +1,183 @@
|
||||
#include "MCF5475.h"
|
||||
#include "bas_types.h"
|
||||
#include "bas_printf.h"
|
||||
|
||||
/*
|
||||
* provide an early exception vector branch table to catch exceptions _before_ VBR has been setup eventually
|
||||
* (to RAMBAR0, in exceptions.S)
|
||||
*/
|
||||
|
||||
typedef void (*exception_handler)(void);
|
||||
extern exception_handler SDRAM_VECTOR_TABLE[];
|
||||
|
||||
/*
|
||||
* decipher Coldfire exception stack frame and print it out in cleartext
|
||||
*/
|
||||
void fault_handler(uint32_t pc, uint32_t format_status)
|
||||
{
|
||||
int format;
|
||||
int fault_status;
|
||||
int vector;
|
||||
int sr;
|
||||
|
||||
xprintf("\007\007exception! Processor halted.\r\n");
|
||||
xprintf("format_status: %lx\r\n", format_status);
|
||||
xprintf("pc: %lx\r\n", pc);
|
||||
|
||||
/*
|
||||
* extract info from format-/status word
|
||||
*/
|
||||
format = (format_status & 0b11110000000000000000000000000000) >> 28;
|
||||
fault_status = ((format_status & 0b00001100000000000000000000000000) >> 26) |
|
||||
((format_status & 0b00000000000000110000000000000000) >> 16);
|
||||
vector = (format_status & 0b00000011111111000000000000000000) >> 18;
|
||||
sr = (format_status & 0b00000000000000001111111111111111);
|
||||
|
||||
xprintf("format: %x\r\n", format);
|
||||
xprintf("fault_status: %x (", fault_status);
|
||||
switch (fault_status)
|
||||
{
|
||||
case 0:
|
||||
xprintf("not an access or address error nor an interrupted debug service routine");
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
case 11:
|
||||
xprintf("reserved");
|
||||
break;
|
||||
case 2:
|
||||
xprintf("interrupt during a debug service routine for faults other than access errors");
|
||||
break;
|
||||
case 4:
|
||||
xprintf("error (for example, protection fault) on instruction fetch");
|
||||
break;
|
||||
case 5:
|
||||
xprintf("TLB miss on opword or instruction fetch");
|
||||
break;
|
||||
case 6:
|
||||
xprintf("TLB miss on extension word of instruction fetch");
|
||||
break;
|
||||
case 7:
|
||||
xprintf("IFP access error while executing in emulator mode");
|
||||
break;
|
||||
case 8:
|
||||
xprintf("error on data write");
|
||||
break;
|
||||
case 9:
|
||||
xprintf("error on attempted write to write-protected space");
|
||||
break;
|
||||
case 10:
|
||||
xprintf("TLB miss on data write");
|
||||
break;
|
||||
case 12:
|
||||
xprintf("error on data read");
|
||||
break;
|
||||
case 13:
|
||||
xprintf("attempted read, read-modify-write of protected space");
|
||||
break;
|
||||
case 14:
|
||||
xprintf("TLB miss on data read or read-modify-write");
|
||||
break;
|
||||
case 15:
|
||||
xprintf("OEP access error while executing in emulator mode");
|
||||
}
|
||||
xprintf(")\r\n");
|
||||
|
||||
xprintf("vector = %02x (", vector);
|
||||
switch (vector)
|
||||
{
|
||||
case 2:
|
||||
xprintf("access error");
|
||||
break;
|
||||
case 3:
|
||||
xprintf("address error");
|
||||
break;
|
||||
case 4:
|
||||
xprintf("illegal instruction");
|
||||
break;
|
||||
case 5:
|
||||
xprintf("divide by zero");
|
||||
break;
|
||||
case 8:
|
||||
xprintf("privilege violation");
|
||||
break;
|
||||
case 9:
|
||||
xprintf("trace");
|
||||
break;
|
||||
case 10:
|
||||
xprintf("unimplemented line-a opcode");
|
||||
break;
|
||||
case 11:
|
||||
xprintf("unimplemented line-f opcode");
|
||||
break;
|
||||
case 12:
|
||||
xprintf("non-PC breakpoint debug interrupt");
|
||||
break;
|
||||
case 13:
|
||||
xprintf("PC breakpoint debug interrupt");
|
||||
break;
|
||||
case 14:
|
||||
xprintf("format error");
|
||||
break;
|
||||
case 24:
|
||||
xprintf("spurious interrupt");
|
||||
break;
|
||||
default:
|
||||
if ( ((fault_status >= 6) && (fault_status <= 7)) ||
|
||||
((fault_status >= 16) && (fault_status <= 23)))
|
||||
{
|
||||
xprintf("reserved");
|
||||
}
|
||||
else if ((fault_status >= 25) && (fault_status <= 31))
|
||||
{
|
||||
xprintf("level %d autovectored interrupt", fault_status - 24);
|
||||
}
|
||||
else if ((fault_status >= 32) && (fault_status <= 47))
|
||||
{
|
||||
xprintf("trap #%d", fault_status - 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
xprintf("unknown fault status");
|
||||
}
|
||||
}
|
||||
xprintf(")\r\n");
|
||||
xprintf("sr=%4x\r\n", sr);
|
||||
}
|
||||
|
||||
void __attribute__((interrupt)) handler(void)
|
||||
{
|
||||
/*
|
||||
* Prepare exception stack contents so it can be handled by a C routine.
|
||||
*
|
||||
* For standard routines, we'd have to save registers here.
|
||||
* Since we do not intend to return anyway, we just ignore that requirement.
|
||||
*/
|
||||
__asm__ __volatile__("move.l (sp),-(sp)\n\t"\
|
||||
"move.l 8(sp),-(sp)\n\t"\
|
||||
"bsr _fault_handler\n\t"\
|
||||
"halt\n\t"\
|
||||
: : : "memory");
|
||||
}
|
||||
|
||||
void setup_vectors(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
xprintf("\r\ninstall early exception vector table:");
|
||||
|
||||
for (i = 8; i < 256; i++)
|
||||
{
|
||||
SDRAM_VECTOR_TABLE[i] = &handler;
|
||||
}
|
||||
|
||||
/*
|
||||
* make sure VBR points to our table
|
||||
*/
|
||||
__asm__ __volatile__("clr.l d0\n\t"\
|
||||
"movec.l d0,VBR\n\t"\
|
||||
"nop\n\t"\
|
||||
"move.l d0,_rt_vbr" ::: "d0", "memory");
|
||||
|
||||
xprintf("finished.\r\n");
|
||||
}
|
||||
4158
BaS_gcc/sources/ff.c
Normal file
4158
BaS_gcc/sources/ff.c
Normal file
File diff suppressed because it is too large
Load Diff
111
BaS_gcc/sources/flash.c
Normal file
111
BaS_gcc/sources/flash.c
Normal 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_ */
|
||||
42
BaS_gcc/sources/illegal_instruction.S
Normal file
42
BaS_gcc/sources/illegal_instruction.S
Normal 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
|
||||
168
BaS_gcc/sources/init_fpga.c
Normal file
168
BaS_gcc/sources/init_fpga.c
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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"
|
||||
#include "bas_printf.h"
|
||||
#include "wait.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 uint8_t _FPGA_FLASH_DATA[];
|
||||
#define FPGA_FLASH_DATA &_FPGA_FLASH_DATA[0]
|
||||
extern uint8_t _FPGA_FLASH_DATA_SIZE[];
|
||||
#define FPGA_FLASH_DATA_SIZE ((uint32_t) &_FPGA_FLASH_DATA_SIZE[0])
|
||||
|
||||
|
||||
void test_longword(void)
|
||||
{
|
||||
uint32_t *fpga_data = (uint32_t *) FPGA_FLASH_DATA;
|
||||
const uint32_t *fpga_flash_data_end = (uint32_t *) FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
|
||||
do
|
||||
{
|
||||
uint32_t value = *fpga_data++;
|
||||
xprintf("LONGWORDS: addr=%p, value=%08x\r", fpga_data, value);
|
||||
} while (fpga_data < fpga_flash_data_end);
|
||||
xprintf("finished. \r\n");
|
||||
}
|
||||
|
||||
void test_word(void)
|
||||
{
|
||||
uint16_t *fpga_data = (uint16_t *) FPGA_FLASH_DATA;
|
||||
const uint16_t *fpga_flash_data_end = (uint16_t *) FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
|
||||
|
||||
do
|
||||
{
|
||||
uint16_t value = *fpga_data++;
|
||||
xprintf("WORDS: addr=%p, value=%04x\r", fpga_data, value);
|
||||
} while (fpga_data < fpga_flash_data_end);
|
||||
xprintf("finished. \r\n");
|
||||
}
|
||||
|
||||
void test_byte(void)
|
||||
{
|
||||
uint8_t *fpga_data = (uint8_t *) FPGA_FLASH_DATA;
|
||||
const uint8_t *fpga_flash_data_end = (uint8_t *) FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
|
||||
|
||||
do
|
||||
{
|
||||
uint8_t value = *fpga_data++;
|
||||
xprintf("LONGWORDS: addr=%p, value=%08x\r", fpga_data, value);
|
||||
} while (fpga_data < fpga_flash_data_end);
|
||||
xprintf("finished. \r\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* load FPGA
|
||||
*/
|
||||
void init_fpga(void)
|
||||
{
|
||||
uint8_t *fpga_data;
|
||||
int i;
|
||||
|
||||
xprintf("MCF_FBCS0_CSAR: %08x\r\n", MCF_FBCS0_CSAR);
|
||||
xprintf("MCF_FBCS0_CSCR: %08x\r\n", MCF_FBCS0_CSCR);
|
||||
xprintf("MCF_FBCS0_CSMR: %08x\r\n", MCF_FBCS0_CSMR);
|
||||
|
||||
xprintf("FPGA load config... ");
|
||||
|
||||
//test_longword();
|
||||
//test_word();
|
||||
//test_byte();
|
||||
|
||||
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK; /* FPGA clock => low */
|
||||
|
||||
/* pulling FPGA_CONFIG to low resets the FPGA */
|
||||
MCF_GPIO_PODR_FEC1L &= ~FPGA_CONFIG; /* FPGA config => low */
|
||||
wait(10); /* give it some time to do its reset stuff */
|
||||
|
||||
while ((MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS) && (MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE));
|
||||
|
||||
MCF_GPIO_PODR_FEC1L |= FPGA_CONFIG; /* pull FPGA_CONFIG high to start config cycle */
|
||||
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.
|
||||
*/
|
||||
|
||||
const uint8_t *fpga_flash_data_end = FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
|
||||
|
||||
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 < fpga_flash_data_end));
|
||||
|
||||
if (fpga_data < fpga_flash_data_end)
|
||||
{
|
||||
while (fpga_data++ < 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");
|
||||
}
|
||||
}
|
||||
78
BaS_gcc/sources/interrupts.c
Normal file
78
BaS_gcc/sources/interrupts.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Interrupts
|
||||
*
|
||||
* Handle interrupts, the levels.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "bas_utils.h"
|
||||
#include "interrupts.h"
|
||||
#include "MCF5475.h"
|
||||
|
||||
extern uint8_t _rtl_vbr[];
|
||||
#define VBR ((uint32_t **) &_rtl_vbr[0])
|
||||
|
||||
/*
|
||||
* register an interrupt handler at the Coldfire interrupt controller and add the handler to the interrupt vector table
|
||||
*/
|
||||
int register_handler(uint8_t priority, uint8_t intr, void (*func)())
|
||||
{
|
||||
int i;
|
||||
uint8_t level = 0b01111111;
|
||||
uint32_t **adr = VBR;
|
||||
|
||||
intr &= 63;
|
||||
priority &= 7;
|
||||
|
||||
if (intr <= 0)
|
||||
return -1;
|
||||
|
||||
for (i = 1; i < 64; i++)
|
||||
if (i != intr)
|
||||
{
|
||||
if ((MCF_INTC_ICR(i) & 7) == priority)
|
||||
CLEAR_BIT_NO(level, (MCF_INTC_ICR(i) >> 3) & 7);
|
||||
}
|
||||
|
||||
for (i = 0; 1 < 7; i++)
|
||||
if (level & (1 << i))
|
||||
break;
|
||||
|
||||
if (i >= 7)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Make sure priority level is high, before changing registers
|
||||
*/
|
||||
__asm__ volatile (
|
||||
"move.w sr,d0\n\t"
|
||||
"move.w d0,-(sp) \n\t"
|
||||
"move.w #0x2700,sr\n\t"
|
||||
:
|
||||
:
|
||||
: "sp","d0","memory"
|
||||
);
|
||||
|
||||
if (intr < 32)
|
||||
CLEAR_BIT(MCF_INTC_IMRL, (1 << intr));
|
||||
else
|
||||
CLEAR_BIT(MCF_INTC_IMRH, (1 << (intr - 32)));
|
||||
|
||||
MCF_INTC_ICR(intr) = MCF_INTC_ICR_IP(priority) | MCF_INTC_ICR_IL(i);
|
||||
|
||||
adr[64 + intr] = (uint32_t *) func; /* first 64 vectors are system exceptions */
|
||||
|
||||
/*
|
||||
* Return the saved priority level
|
||||
*/
|
||||
__asm__ volatile (
|
||||
"move.w (sp)+,d2\n\t"
|
||||
"move.w d2,sr\n\t"
|
||||
:
|
||||
:
|
||||
: "sp","d2","memory"
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
100
BaS_gcc/sources/main.c
Normal file
100
BaS_gcc/sources/main.c
Normal 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 */
|
||||
}
|
||||
802
BaS_gcc/sources/mmc.c
Normal file
802
BaS_gcc/sources/mmc.c
Normal file
@@ -0,0 +1,802 @@
|
||||
#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_LOW() { dspi_fifo_val |= MCF_DSPI_DTFR_CS5; }
|
||||
#define CS_HIGH() { dspi_fifo_val &= ~MCF_DSPI_DTFR_CS5; }
|
||||
|
||||
/*
|
||||
* DCTAR_PBR (baud rate prescaler) and DCTAR_BR (baud rate scaler) together determine the SPI baud rate. The forumula is
|
||||
*
|
||||
* baud rate = system clock / DCTAR_PBR * 1 / DCTAR_BR.
|
||||
*
|
||||
* System clock for the Firebee is 133 MHZ.
|
||||
*
|
||||
* The SPICLK_FAST() example calculates as follows: baud rate = 133 MHz / 3 * 1 / 2 = 22,16 MHz
|
||||
* SPICLK_SLOW() should be between 100 and 400 kHz: 133 MHz / 1 * 1 / 1024 = 129 kHz
|
||||
*/
|
||||
#define SPICLK_FAST() { MCF_DSPI_DCTAR0 = MCF_DSPI_DCTAR_TRSZ(0b0111) | /* 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_1CLK | /* 3 clock baudrate prescaler */ \
|
||||
MCF_DSPI_DCTAR_CSSCK(1) | /* delay scaler * 4 */\
|
||||
MCF_DSPI_DCTAR_ASC(0b0001) | /* 2 */ \
|
||||
MCF_DSPI_DCTAR_DT(0b0010) | /* 2 */ \
|
||||
MCF_DSPI_DCTAR_BR(0b0001); } /* 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 | /* 1 clock baudrate prescaler */ \
|
||||
MCF_DSPI_DCTAR_CSSCK(8) | /* delay scaler * 512 */\
|
||||
MCF_DSPI_DCTAR_ASC(8) | /* 2 */ \
|
||||
MCF_DSPI_DCTAR_DT(9) | /* 2 */ \
|
||||
MCF_DSPI_DCTAR_BR(7); \
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
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 */
|
||||
|
||||
|
||||
static uint32_t dspi_fifo_val = MCF_DSPI_DTFR_CTCNT;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Send/Receive data to the MMC (Platform dependent) */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Exchange a byte. If last is false (0), there will be more bytes to follow (EOQ flag in DTFR left unset)
|
||||
*/
|
||||
static uint8_t xchg_spi(uint8_t byte, int last)
|
||||
{
|
||||
uint32_t fifo;
|
||||
uint8_t res;
|
||||
|
||||
fifo = dspi_fifo_val | (byte & 0xff); /* transfer bytes only */
|
||||
//fifo |= (last ? MCF_DSPI_DTFR_EOQ : 0); /* mark last transfer */
|
||||
MCF_DSPI_DTFR = fifo;
|
||||
while (! (MCF_DSPI_DSR & MCF_DSPI_DSR_TCF)); /* wait until DSPI transfer complete */
|
||||
fifo = MCF_DSPI_DRFR; /* read transferred word */
|
||||
|
||||
MCF_DSPI_DSR = -1; /* clear DSPI status register */
|
||||
|
||||
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 - 1; i++)
|
||||
*buff++ = xchg_spi(0xff, 0);
|
||||
*buff++ = xchg_spi(0xff, 1); /* transfer last byte and stop transmission */
|
||||
}
|
||||
|
||||
|
||||
#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 - 1; i++)
|
||||
xchg_spi(*buff++, 0);
|
||||
xchg_spi(*buff++, 1); /* transfer last byte and indicate end of transmission */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static bool card_ready(void)
|
||||
{
|
||||
uint8_t d;
|
||||
|
||||
d = xchg_spi(0xff, 1);
|
||||
return (d == 0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for card ready
|
||||
*
|
||||
* wt: timeout in ns
|
||||
* returns 1: ready, 0: timeout
|
||||
*/
|
||||
static int wait_ready(uint32_t wt)
|
||||
{
|
||||
return waitfor(wt * 1000, card_ready);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Deselect card and release SPI
|
||||
*/
|
||||
static void deselect(void)
|
||||
{
|
||||
CS_HIGH();
|
||||
wait_ready(50); /* 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();
|
||||
|
||||
if (wait_ready(500))
|
||||
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 */
|
||||
dspi_fifo_val = MCF_DSPI_DTFR_CTCNT;
|
||||
/*
|
||||
* 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_CSIS0 | /* CS0 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 */
|
||||
SPICLK_SLOW();
|
||||
|
||||
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(uint8_t *buff, uint32_t btr)
|
||||
{
|
||||
uint8_t token;
|
||||
int32_t target = MCF_SLT_SCNT(0) - (20000L * 100L * 132L);
|
||||
|
||||
do { /* Wait for DataStart token in timeout of 200ms */
|
||||
token = xchg_spi(0xFF, 0);
|
||||
} while ((token == 0xFF) && MCF_SLT_SCNT(0) - target > 0);
|
||||
|
||||
if (token == 0xff)
|
||||
{
|
||||
xprintf("no data start token received after 2000ms in rcvr_datablock\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (token != 0xFE)
|
||||
{
|
||||
xprintf("invalid token (%x) in rcvr_datablock()!\r\n", token);
|
||||
return 0; /* Function fails if invalid DataStart token or timeout */
|
||||
}
|
||||
|
||||
rcvr_spi_multi(buff, btr); /* Store trailing data to the buffer */
|
||||
|
||||
xchg_spi(0xFF, 1);
|
||||
xchg_spi(0xFF, 1); /* Discard CRC */
|
||||
|
||||
return 1; /* Function succeeded */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Send a data packet to the MMC */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
#if _USE_WRITE
|
||||
static int xmit_datablock(const uint8_t *buff, uint8_t token)
|
||||
{
|
||||
uint8_t resp;
|
||||
|
||||
|
||||
if (!wait_ready(500))
|
||||
{
|
||||
xprintf("card did not respond ready after 500 ms in xmit_datablock()\r\n");
|
||||
return 0; /* Wait for card ready */
|
||||
}
|
||||
|
||||
xchg_spi(token, 1); /* Send token */
|
||||
if (token != 0xFD) { /* Send data if token is other than StopTran */
|
||||
xmit_spi_multi(buff, 512); /* Data */
|
||||
xchg_spi(0xFF, 1);
|
||||
xchg_spi(0xFF, 1); /* Dummy CRC */
|
||||
|
||||
resp = xchg_spi(0xFF, 1); /* Receive data resp */
|
||||
if ((resp & 0x1F) != 0x05) /* Function fails if the data packet was not accepted */
|
||||
{
|
||||
xprintf("card did not accept data packet in xmit_datablock() (resp = %x)\r\n", resp & 0x1F);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
wait_ready(3000);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Send a command packet to the MMC */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
static uint8_t send_cmd(uint8_t cmd, uint32_t arg)
|
||||
{
|
||||
int n;
|
||||
int 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())
|
||||
{
|
||||
xprintf("card could not be selected in send_cmd()\r\n");
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
if (!wait_ready(5000))
|
||||
{
|
||||
xprintf("card did not respond ready after 5000 ms in send_cmd()\r\n");
|
||||
return 0xff; /* Wait for card ready */
|
||||
}
|
||||
|
||||
/* Send command packet */
|
||||
xchg_spi(0x40 | cmd, 0); /* Start + command index */
|
||||
xchg_spi((uint8_t)(arg >> 24), 0); /* Argument[31..24] */
|
||||
xchg_spi((uint8_t)(arg >> 16), 0); /* Argument[23..16] */
|
||||
xchg_spi((uint8_t)(arg >> 8), 0); /* Argument[15..8] */
|
||||
xchg_spi((uint8_t)arg, 1); /* 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, 0);
|
||||
|
||||
/* Receive command resp */
|
||||
if (cmd == CMD12)
|
||||
{
|
||||
xchg_spi(0xFF, 0); /* Discard following one byte when CMD12 */
|
||||
}
|
||||
|
||||
n = 10000000; /* Wait for response (1000 bytes max) */
|
||||
do
|
||||
res = xchg_spi(0xFF, 1);
|
||||
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, card_type, ocr[4];
|
||||
uint8_t buff[16];
|
||||
int res;
|
||||
|
||||
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, 1); /* Send 80 dummy clocks */
|
||||
|
||||
card_type = 0;
|
||||
if (send_cmd(CMD0, 0) == 1)
|
||||
{
|
||||
/* Put the card SPI/Idle state */
|
||||
int32_t target;
|
||||
|
||||
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */
|
||||
for (n = 0; n < 4; n++)
|
||||
ocr[n] = xchg_spi(0xFF, 1); /* Get 32 bit return value of R7 resp */
|
||||
if (ocr[2] == 0x01 && ocr[3] == 0xAA)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* Is the card supports vcc of 2.7-3.6V? */
|
||||
target = MCF_SLT_SCNT(0) - (1000L * 1000L * 132); /* 1 sec */
|
||||
while (MCF_SLT_SCNT(0) - target > 0)
|
||||
{
|
||||
res = send_cmd(ACMD41, 1UL << 30); /* Wait for end of initialization with ACMD41(HCS) */
|
||||
if (res != 0xff)
|
||||
break;
|
||||
}
|
||||
xprintf("res = %d\r\n", res);
|
||||
|
||||
target = MCF_SLT_SCNT(0) - (1000L * 1000L * 132); /* 1 sec */
|
||||
while (MCF_SLT_SCNT(0) - target > 0)
|
||||
{
|
||||
res = send_cmd(CMD58, 0); /* Check CCS bit in the OCR */
|
||||
if (res != 0xff)
|
||||
break;
|
||||
}
|
||||
xprintf("res = %d\r\n", res);
|
||||
for (n = 0; n < 4; n++)
|
||||
ocr[n] = xchg_spi(0xFF, 1);
|
||||
card_type = (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? */
|
||||
card_type = CT_SD1;
|
||||
cmd = ACMD41; /* SDv1 (ACMD41(0)) */
|
||||
} else {
|
||||
card_type = CT_MMC;
|
||||
cmd = CMD1; /* MMCv3 (CMD1(0)) */
|
||||
}
|
||||
target = MCF_SLT_SCNT(0) - (1000L * 1000L * 132); /* 1 sec */
|
||||
while (MCF_SLT_SCNT(0) - target > 0 && send_cmd(cmd, 0)); /* Wait for end of initialization */
|
||||
|
||||
if (send_cmd(CMD16, 512) != 0) /* Set block length: 512 */
|
||||
card_type = 0;
|
||||
}
|
||||
}
|
||||
CardType = card_type; /* Card type */
|
||||
|
||||
res = disk_ioctl(0, MMC_GET_CSD, buff);
|
||||
if (res == RES_OK)
|
||||
{
|
||||
xprintf("CSD of card:\r\n");
|
||||
hexdump(buff, 16);
|
||||
}
|
||||
deselect();
|
||||
|
||||
if (card_type)
|
||||
{
|
||||
/* OK */
|
||||
|
||||
SPICLK_FAST(); /* Set fast clock */
|
||||
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT flag */
|
||||
xprintf("card type: %d\r\n", card_type);
|
||||
res = disk_ioctl(0, MMC_GET_CSD, buff);
|
||||
if (res == RES_OK)
|
||||
{
|
||||
xprintf("CSD of card now:\r\n");
|
||||
hexdump(buff, 16);
|
||||
}
|
||||
deselect();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Failed */
|
||||
xprintf("no card type detected in disk_initialize()\r\n");
|
||||
power_off();
|
||||
Stat = STA_NOINIT;
|
||||
}
|
||||
|
||||
return Stat;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Get disk status */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DSTATUS disk_status(uint8_t drv)
|
||||
{
|
||||
if (drv) return STA_NOINIT; /* Supports only drive 0 */
|
||||
|
||||
return Stat; /* Return disk status */
|
||||
}
|
||||
|
||||
DSTATUS disk_reset(uint8_t drv)
|
||||
{
|
||||
if (drv) return STA_NOINIT;
|
||||
|
||||
deselect();
|
||||
disk_initialize(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Read sector(s) */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DRESULT disk_read(uint8_t drv, uint8_t *buff, uint32_t sector, uint8_t count)
|
||||
{
|
||||
if (drv)
|
||||
{
|
||||
xprintf("wrong drive in disk_read()\r\n");
|
||||
return RES_PARERR; /* Check parameter */
|
||||
}
|
||||
|
||||
if (! count)
|
||||
{
|
||||
xprintf("wrong count in disk_read()\r\n");
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
if (Stat & STA_NOINIT)
|
||||
{
|
||||
xprintf("drive not ready in disk_read()\r\n");
|
||||
return RES_NOTRDY; /* Check if drive is ready */
|
||||
}
|
||||
|
||||
if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA or BA conversion (byte addressing cards) */
|
||||
|
||||
if (count == 1) { /* Single sector read */
|
||||
if ((send_cmd(CMD17, sector) == 0)) /* READ_SINGLE_BLOCK */
|
||||
if (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, const uint8_t *buff, uint32_t sector, uint8_t count)
|
||||
{
|
||||
int res;
|
||||
|
||||
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 */
|
||||
res = send_cmd(CMD24, sector);
|
||||
if (res == 0)
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
else
|
||||
xprintf("send_cmd(CMD24, ...) failed in disk_write()\r\n");
|
||||
|
||||
if (xmit_datablock(buff, 0xFE))
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
xprintf("xmit_datablock(buff, ...) failed in disk_write()\r\n");
|
||||
}
|
||||
}
|
||||
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();
|
||||
|
||||
if (count) /* we had an error, try a reinit */
|
||||
{
|
||||
xprintf("disk_write() failed (count=%d)\r\n", count);
|
||||
}
|
||||
|
||||
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, uint8_t ctrl, void *buff)
|
||||
{
|
||||
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))
|
||||
{
|
||||
if (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) */
|
||||
* (uint32_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, 1);
|
||||
if (rcvr_datablock(csd, 16)) { /* Read partial block */
|
||||
for (n = 64 - 16; n; n--) xchg_spi(0xFF, 1); /* 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))
|
||||
{
|
||||
if (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)
|
||||
{
|
||||
if (send_cmd(CMD33, ed) == 0)
|
||||
if (send_cmd(CMD38, 0) == 0)
|
||||
if (wait_ready(30))
|
||||
; /* 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, 1);
|
||||
res = RES_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case MMC_GET_SDSTAT : /* Read SD status (64 bytes) */
|
||||
if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
|
||||
xchg_spi(0xFF, 1);
|
||||
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_ */
|
||||
217
BaS_gcc/sources/mmu.S
Normal file
217
BaS_gcc/sources/mmu.S
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* 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 writethrough_mmudr (MCF_MMU_MMUDR_SZ(00)|MCF_MMU_MMUDR_CM(00)|MCF_MMU_MMUDR_R|MCF_MMU_MMUDR_W|MCF_MMU_MMUDR_X)
|
||||
#define copyback_mmudr (MCF_MMU_MMUDR_SZ(00)|MCF_MMU_MMUDR_CM(01)|MCF_MMU_MMUDR_R|MCF_MMU_MMUDR_W|MCF_MMU_MMUDR_X)
|
||||
#define nocache_precise_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
|
||||
|
||||
//
|
||||
// to avoid chicken and egg situations, we need to make sure that MMU TLB miss exceptions do not end up in a memory
|
||||
// area that in turn cause a TLB miss exception themself after the MMU is enabled. At least the exception handler must live
|
||||
// in an area that's either covered by one of the ACR's or a locked MMU TLB entry. This is especially important when we link
|
||||
// BaS for RAM.
|
||||
//
|
||||
.text
|
||||
_mmu_init:
|
||||
move.l d3,-(sp) // Backup registers
|
||||
move.l d2,-(sp)
|
||||
|
||||
clr.l d0
|
||||
movec d0,ASID // ASID always 0
|
||||
move.l d0,_rt_asid // save shadow register
|
||||
|
||||
move.l #0xC03FC040,d0 // data r/w precise c000'0000-ffff'ffff
|
||||
movec d0,ACR0
|
||||
move.l d0,_rt_acr0 // save shadow register
|
||||
|
||||
move.l #0x601FC000,d0 // data r/w wt 6000'0000-7fff'ffff
|
||||
movec d0,ACR1
|
||||
move.l d0,_rt_acr1 // save shadow register
|
||||
|
||||
move.l #0xe007C400,d0 // instruction r wt e000'0000-e07f'ffff
|
||||
movec d0,ACR2
|
||||
move.l d0,_rt_acr2 // save shadow register
|
||||
|
||||
clr.l d0 // acr3 off
|
||||
movec d0,ACR3
|
||||
move.l d0,_rt_acr3 // save shadow register
|
||||
|
||||
move.l #__MMUBAR+1,d0
|
||||
movec d0,MMUBAR // set MMUBAR
|
||||
move.l d0,_rt_mmubar // save shadow register
|
||||
|
||||
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|copyback_mmudr|MCF_MMU_MMUDR_LK,d1
|
||||
moveq.l #mmuord_d,d2 // MMU update data
|
||||
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 data
|
||||
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|writethrough_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 data
|
||||
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
|
||||
|
||||
|
||||
// create locked TLB entries which must be available as soon as the MMU gets enabled
|
||||
// Make the TOS (in SDRAM) read-only
|
||||
move.l #__TOS+std_mmutr,d0
|
||||
move.l #__TOS+copyback_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|nocache_precise_mmudr|MCF_MMU_MMUDR_LK,d1
|
||||
move.l d0,MCF_MMU_MMUTR
|
||||
move.l d1,MCF_MMU_MMUDR
|
||||
move.l d2,MCF_MMU_MMUOR // mapped to ffffxxx, precise,
|
||||
move.l d3,MCF_MMU_MMUOR // mapped to ffffxxx, precise,
|
||||
|
||||
// 1ff0'0000 locked
|
||||
move.l #0x1FF00000|std_mmutr,d0 // last megabyte of RAM. Reserved for BaS
|
||||
move.l #0x1FF00000|copyback_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|copyback_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 add on miss
|
||||
*/
|
||||
_mmutr_miss:
|
||||
lea -8 * 4(sp),sp
|
||||
movem.l d0-d3/a0-a3,(sp)
|
||||
|
||||
move.l d0,-(sp)
|
||||
pea MISS_text
|
||||
jsr _xprintf
|
||||
addq.l #8,sp
|
||||
|
||||
movem.l (sp),d0-d3/a0-a3
|
||||
lea 8 * 4(sp),sp
|
||||
|
||||
bsr cpusha // clear caches
|
||||
|
||||
and.l #0xFFF00000,d0 // d0 is the address not found (MMUAR at the time of the exception)
|
||||
or.l #std_mmutr,d0 // mark shared and valid
|
||||
move.l d0,MCF_MMU_MMUTR // add to TLB
|
||||
and.l #0xFFF00000,d0 // mask out page
|
||||
or.l #copyback_mmudr,d0 // 1MB page size, cachable copyback, read, write, execute
|
||||
move.l d0,MCF_MMU_MMUDR // add to TLB
|
||||
moveq.l #mmuord_d,d0 // MMU update data
|
||||
move.l d0,MCF_MMU_MMUOR // set
|
||||
moveq.l #mmuord_i,d0 // MMU update instruction
|
||||
move.l d0,MCF_MMU_MMUOR // set
|
||||
|
||||
move.l (sp)+,d0 // restore register saved in acess
|
||||
rte
|
||||
|
||||
.data
|
||||
MISS_text:
|
||||
.ascii "MMU TLB MISS at %p"
|
||||
.byte 13, 10, 0
|
||||
109
BaS_gcc/sources/pci.c
Normal file
109
BaS_gcc/sources/pci.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* pci.c
|
||||
*
|
||||
* Created on: 08.01.2013
|
||||
* Author: Markus Froeschle
|
||||
*/
|
||||
|
||||
#include <MCF5475.h>
|
||||
#include "pci.h"
|
||||
#include "stdint.h"
|
||||
|
||||
void init_eport(void)
|
||||
{
|
||||
/* concigure IRQ1-7 pins on EPORT falling edge triggered */
|
||||
MCF_EPORT_EPPAR = MCF_EPORT_EPPAR_EPPA7(MCF_EPORT_EPPAR_FALLING) +
|
||||
MCF_EPORT_EPPAR_EPPA6(MCF_EPORT_EPPAR_FALLING) +
|
||||
MCF_EPORT_EPPAR_EPPA5(MCF_EPORT_EPPAR_FALLING) +
|
||||
MCF_EPORT_EPPAR_EPPA4(MCF_EPORT_EPPAR_FALLING) +
|
||||
MCF_EPORT_EPPAR_EPPA3(MCF_EPORT_EPPAR_FALLING) +
|
||||
MCF_EPORT_EPPAR_EPPA2(MCF_EPORT_EPPAR_FALLING) +
|
||||
MCF_EPORT_EPPAR_EPPA1(MCF_EPORT_EPPAR_FALLING);
|
||||
MCF_EPORT_EPDDR = 0; /* clear data direction register. All pins as input */
|
||||
MCF_EPORT_EPFR = 0; /* clear all EPORT interrupt flags */
|
||||
MCF_EPORT_EPIER = 0; /* disable all EPORT interrupts (for now) */
|
||||
}
|
||||
|
||||
void init_xlbus_arbiter(void)
|
||||
{
|
||||
uint8_t clock_ratio;
|
||||
|
||||
/* setup XL bus arbiter */
|
||||
clock_ratio = (MCF_PCI_PCIGSCR >> 24) & 0x07;
|
||||
if (clock_ratio == 4)
|
||||
{
|
||||
/* device errata 26: Flexbus hang up in 4:1 clock ratio */
|
||||
MCF_PCI_PCIGSCR |= 0x80000000; /* disable pipeline */
|
||||
}
|
||||
/* FIXME: Firetos (boot2.S, l. 719) looks pretty strange at this place - is this a typo? */
|
||||
}
|
||||
|
||||
void init_pci(void)
|
||||
{
|
||||
/*
|
||||
* assert /PCIRESET (reset cards on bus). FIXME: According to documentation,
|
||||
* this should be done last during PCI initialization
|
||||
*/
|
||||
MCF_PCI_PCIGSCR = MCF_PCI_PCIGSCR_PR;
|
||||
|
||||
/*
|
||||
* setup the PCI arbiter.
|
||||
*/
|
||||
|
||||
/* PCI Arbiter Control Register (PACR) */
|
||||
MCF_PCIARB_PACR = MCF_PCIARB_PACR_INTMPRI /* internal master priority level high */
|
||||
+ MCF_PCIARB_PACR_EXTMPRI(0x1f) /* external master priority levels all high */
|
||||
+ MCF_PCIARB_PACR_INTMINTEN /* generate interrupt if internal master timeout */
|
||||
+ MCF_PCIARB_PACR_EXTMINTEN(0x1f); /* generate interrupt if external master timeout */
|
||||
/* configure all 5 PCI Bus Grant pins for PCI */
|
||||
MCF_PAD_PAR_PCIBG = 0x3ff;
|
||||
/* configure all 5 PCI Bus Request pins for PCI */
|
||||
MCF_PAD_PAR_PCIBR = 0x3ff;
|
||||
|
||||
/* PCI Status/Command Register PCISCR */
|
||||
MCF_PCI_PCISCR = MCF_PCI_PCISCR_M /* recognize memory accesses */
|
||||
+ MCF_PCI_PCISCR_B /* bus master enable for controller */
|
||||
+ MCF_PCI_PCISCR_MW; /* controller can generate memory write and invalidate command */
|
||||
|
||||
/* Configuration 1 Register PCICR1 */
|
||||
MCF_PCI_PCICR1 = MCF_PCI_PCICR1_CACHELINESIZE(8) /* cache line size in units of DWORDs */
|
||||
+ MCF_PCI_PCICR1_LATTIMER(32); /* 256 PCI clocks (?) latency */
|
||||
/* Configuration 2 Register PCICR2 */
|
||||
MCF_PCI_PCICR2 = MCF_PCI_PCICR2_MINGNT(1) /* specifies how long the Coldfire processor retains bus ownership as master */
|
||||
+ MCF_PCI_PCICR2_MAXLAT(1); /* specifies (in units of 1/4 microseconds) how often the Coldfire */
|
||||
/* processor needs access to the bus as PCI master */
|
||||
/* Initiator Control Register: turn on error signaling */
|
||||
MCF_PCI_PCIICR = MCF_PCI_PCIICR_TAE + /* target abort enable: CPU generates an interrupt if target terminates a transaction */
|
||||
MCF_PCI_PCIICR_IAE /* the same for the initiator */
|
||||
/* + MCF_PCI_PCIICR_REE */ ; /* the same for retry errors */
|
||||
/* Global Status/Control Register */
|
||||
MCF_PCI_PCIGSCR |= MCF_PCI_PCIGSCR_SEE; /* generate interrupt if /PCISERR is asserted (PCI system error) */
|
||||
|
||||
/* configure initiator windows */
|
||||
|
||||
|
||||
/* Initiator Window 0 Base / Translation Address Register */
|
||||
#ifdef SAME_CPU_PCI_MEM_ADDR
|
||||
MCF_PCI_PCIIW0BTAR = (PCI_MEMORY_OFFSET + ((PCI_MEMORY_SIZE - 1) >> 8) & 0xFFFF0000) | (PCI_MEMORY_OFFSET >> 16 & 0xFFFF)
|
||||
#else
|
||||
MCF_PCI_PCIIW0BTAR = PCI_MEMORY_OFFSET + ((PCI_MEMORY_SIZE - 1) >> 8) & 0xFFFF0000;
|
||||
#endif /* SAME_CPU_PCI_MEM_ADDR */
|
||||
|
||||
/* Initiator Window 1 Base / Translation Address 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 */
|
||||
|
||||
MCF_PCI_PCIIWCR = MCF_PCI_PCIIWCR_WINCTRL0_MEMRDLINE
|
||||
+ MCF_PCI_PCIIWCR_WINCTRL1_IO;
|
||||
|
||||
/* target zones */
|
||||
}
|
||||
|
||||
void init(void)
|
||||
{
|
||||
init_eport();
|
||||
init_xlbus_arbiter();
|
||||
init_pci();
|
||||
}
|
||||
36
BaS_gcc/sources/printf_helper.S
Normal file
36
BaS_gcc/sources/printf_helper.S
Normal 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
|
||||
418
BaS_gcc/sources/s19reader.c
Normal file
418
BaS_gcc/sources/s19reader.c
Normal file
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* 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 "bas_printf.h"
|
||||
#include "bas_string.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]));
|
||||
}
|
||||
|
||||
#ifdef _NOT_USED_
|
||||
/*
|
||||
* 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]);
|
||||
}
|
||||
#endif /* _NOT_USED_ */
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _NOT_USED_
|
||||
static err_t flash(uint8_t *dst, uint8_t *src, uint32_t length)
|
||||
{
|
||||
err_t ret = OK;
|
||||
|
||||
/* TODO: do the actual flash */
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* _NOT_USED_ */
|
||||
|
||||
|
||||
/*
|
||||
* 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");
|
||||
}
|
||||
}
|
||||
|
||||
121
BaS_gcc/sources/sd_card.c
Normal file
121
BaS_gcc/sources/sd_card.c
Normal 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;
|
||||
int32_t start_time = MCF_SLT_SCNT(0);
|
||||
int32_t end_time;
|
||||
int32_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 */
|
||||
}
|
||||
}
|
||||
64
BaS_gcc/sources/startcf.S
Normal file
64
BaS_gcc/sources/startcf.S
Normal file
@@ -0,0 +1,64 @@
|
||||
/* 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 SRAM */
|
||||
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
|
||||
565
BaS_gcc/sources/supervisor.S
Normal file
565
BaS_gcc/sources/supervisor.S
Normal 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
|
||||
|
||||
1020
BaS_gcc/sources/sysinit.c
Normal file
1020
BaS_gcc/sources/sysinit.c
Normal file
File diff suppressed because it is too large
Load Diff
17
BaS_gcc/sources/unicode.c
Normal file
17
BaS_gcc/sources/unicode.c
Normal 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
|
||||
31
BaS_gcc/sources/wait.c
Normal file
31
BaS_gcc/sources/wait.c
Normal 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>
|
||||
314
BaS_gcc/sources/xhdi_interface.c
Normal file
314
BaS_gcc/sources/xhdi_interface.c
Normal file
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* xhdi_sd.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/>.
|
||||
*
|
||||
* Created on: 01.05.2013
|
||||
* Copyright 2012: M. Fröschle
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "xhdi_sd.h"
|
||||
#include "bas_printf.h"
|
||||
|
||||
|
||||
unsigned long xhdi_call(uint16_t *stack)
|
||||
{
|
||||
uint16_t opcode = *stack;
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case XHDI_VERSION:
|
||||
return xhdi_version();
|
||||
break;
|
||||
|
||||
case XHDI_INQUIRE_TARGET:
|
||||
{
|
||||
struct XHINQTARGET_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
uint32_t *blocksize;
|
||||
uint32_t *deviceflags;
|
||||
char *productname;
|
||||
} *args = (struct XHINQTARGET_args *) stack;
|
||||
|
||||
return xhdi_inquire_target(args->major, args->minor, args->blocksize,
|
||||
args->deviceflags, args->productname);
|
||||
}
|
||||
break;
|
||||
|
||||
case XHDI_RESERVE:
|
||||
{
|
||||
struct XHRESERVE_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
uint16_t do_reserve;
|
||||
uint16_t key;
|
||||
} *args = (struct XHRESERVE_args *) stack;
|
||||
|
||||
return xhdi_reserve(args->major, args->minor, args->do_reserve, args->key);
|
||||
}
|
||||
|
||||
case XHDI_LOCK:
|
||||
{
|
||||
struct XHLOCK_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
uint16_t do_lock;
|
||||
uint16_t key;
|
||||
} *args = (struct XHLOCK_args *) stack;
|
||||
|
||||
return xhdi_lock(args->major, args->minor, args->do_lock, args->key);
|
||||
}
|
||||
|
||||
case XHDI_STOP:
|
||||
{
|
||||
struct XHSTOP_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
uint16_t do_stop;
|
||||
uint16_t key;
|
||||
} *args = (struct XHSTOP_args *) stack;
|
||||
|
||||
return xhdi_stop(args->major, args->minor, args->do_stop, args->key);
|
||||
}
|
||||
|
||||
case XHDI_EJECT:
|
||||
{
|
||||
struct XHEJECT_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
uint16_t do_eject;
|
||||
uint16_t key;
|
||||
} *args = (struct XHEJECT_args *) stack;
|
||||
|
||||
return xhdi_eject(args->major, args->minor, args->do_eject, args->key);
|
||||
}
|
||||
|
||||
case XHDI_DRIVEMAP:
|
||||
{
|
||||
return xhdi_drivemap();
|
||||
}
|
||||
|
||||
case XHDI_INQUIRE_DEVICE:
|
||||
{
|
||||
struct XHINQDEV_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t drv;
|
||||
uint16_t *major;
|
||||
uint16_t *minor;
|
||||
uint32_t *start;
|
||||
BPB *bpb;
|
||||
} *args = (struct XHINQDEV_args *) stack;
|
||||
|
||||
return xhdi_inquire_device(args->drv, args->major, args->minor, args->start,
|
||||
args->bpb);
|
||||
}
|
||||
|
||||
case XHDI_INQUIRE_DRIVER:
|
||||
{
|
||||
struct XHINQDRIVER_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t dev;
|
||||
char *name;
|
||||
char *version;
|
||||
char *company;
|
||||
uint16_t *ahdi_version;
|
||||
uint16_t *maxIPL;
|
||||
} *args = (struct XHINQDRIVER_args *) stack;
|
||||
|
||||
return xhdi_inquire_driver(args->dev, args->name, args->version, args->company,
|
||||
args->ahdi_version, args->maxIPL);
|
||||
}
|
||||
|
||||
case XHDI_NEW_COOKIE:
|
||||
{
|
||||
struct XHNEWCOOKIE_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint32_t newcookie;
|
||||
} *args = (struct XHNEWCOOKIE_args *) stack;
|
||||
|
||||
return xhdi_new_cookie(args->newcookie);
|
||||
}
|
||||
|
||||
case XHDI_READ_WRITE:
|
||||
{
|
||||
struct XHREADWRITE_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
uint16_t rw;
|
||||
uint32_t sector;
|
||||
uint16_t count;
|
||||
void *buf;
|
||||
} *args = (struct XHREADWRITE_args *) stack;
|
||||
|
||||
return xhdi_read_write(args->major, args->minor,
|
||||
args->rw, args->sector,
|
||||
args->count, args->buf);
|
||||
}
|
||||
|
||||
case XHDI_INQUIRE_TARGET2:
|
||||
{
|
||||
struct XHINQTARGET2_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
uint32_t *blocksize;
|
||||
uint32_t *deviceflags;
|
||||
char *productname;
|
||||
uint16_t stringlen;
|
||||
} *args = (struct XHINQTARGET2_args *) stack;
|
||||
|
||||
return xhdi_inquire_target2(args->major, args->minor, args->blocksize,
|
||||
args->deviceflags, args->productname, args->stringlen);
|
||||
}
|
||||
|
||||
case XHDI_INQUIRE_DEVICE2:
|
||||
{
|
||||
struct XHINQDEV2_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t drv;
|
||||
uint16_t *major;
|
||||
uint16_t *minor;
|
||||
uint32_t *start;
|
||||
BPB *bpb;
|
||||
uint32_t *blocks;
|
||||
char *partid;
|
||||
} *args = (struct XHINQDEV2_args *) stack;
|
||||
|
||||
return xhdi_inquire_device2(args->drv, args->major, args->minor, args->start,
|
||||
args->bpb, args->blocks, args->partid);
|
||||
}
|
||||
|
||||
case XHDI_DRIVER_SPECIAL:
|
||||
{
|
||||
struct XHDRIVERSPECIAL_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint32_t key1;
|
||||
uint32_t key2;
|
||||
uint16_t subopcode;
|
||||
void *data;
|
||||
} *args = (struct XHDRIVERSPECIAL_args *) stack;
|
||||
|
||||
return xhdi_driver_special(args->key1, args->key2, args->subopcode,
|
||||
args->data);
|
||||
}
|
||||
|
||||
case XHDI_GET_CAPACITY:
|
||||
{
|
||||
struct XHGETCAPACITY_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
uint32_t *blocks;
|
||||
uint32_t *blocksize;
|
||||
} *args = (struct XHGETCAPACITY_args *) stack;
|
||||
|
||||
return xhdi_get_capacity(args->major, args->minor, args->blocks,
|
||||
args->blocksize);
|
||||
}
|
||||
|
||||
case XHDI_MEDIUM_CHANGED:
|
||||
{
|
||||
struct XHMEDIUMCHANGED_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
} *args = (struct XHMEDIUMCHANGED_args *) stack;
|
||||
|
||||
return xhdi_medium_changed(args->major, args->minor);
|
||||
}
|
||||
|
||||
case XHDI_MINT_INFO:
|
||||
{
|
||||
struct XHMINTINFO_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t subopcode;
|
||||
void *data;
|
||||
} *args = (struct XHMINTINFO_args *) stack;
|
||||
|
||||
return xhdi_mint_info(args->subopcode, args->data);
|
||||
}
|
||||
|
||||
case XHDI_DOS_LIMITS:
|
||||
{
|
||||
struct XHDOSLIMITS_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t which;
|
||||
uint32_t limit;
|
||||
} *args = (struct XHDOSLIMITS_args *) stack;
|
||||
|
||||
return xhdi_dos_limits(args->which, args->limit);
|
||||
}
|
||||
|
||||
case XHDI_LAST_ACCESS:
|
||||
{
|
||||
struct XHLASTACCESS_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
uint32_t *ms;
|
||||
} *args = (struct XHLASTACCESS_args *) stack;
|
||||
|
||||
return xhdi_last_access(args->major, args->minor, args->ms);
|
||||
}
|
||||
|
||||
case XHDI_REACCESS:
|
||||
{
|
||||
struct XHREACCESS_args
|
||||
{
|
||||
uint16_t opcode;
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
} *args = (struct XHREACCESS_args *) stack;
|
||||
|
||||
return xhdi_reaccess(args->major, args->minor);
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
xprintf("unknown XHDI function 0x%x\r\n", opcode);
|
||||
return EINVFN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
242
BaS_gcc/sources/xhdi_sd.c
Normal file
242
BaS_gcc/sources/xhdi_sd.c
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* xhdi_sd.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/>.
|
||||
*
|
||||
* Created on: 01.05.2013
|
||||
* Copyright 2012 M. Fröschle
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "xhdi_sd.h"
|
||||
#include "bas_printf.h"
|
||||
#include "bas_string.h"
|
||||
#include "diskio.h"
|
||||
|
||||
#define DRIVER_VERSION 0x130
|
||||
|
||||
#define MY_MAJOR 7
|
||||
#define MY_MINOR 0
|
||||
|
||||
uint16_t xhdi_version(void)
|
||||
{
|
||||
return DRIVER_VERSION;
|
||||
}
|
||||
|
||||
uint32_t xhdi_inquire_target(uint16_t major, uint16_t minor, uint32_t *block_size, uint32_t *flags,
|
||||
char *product_name)
|
||||
{
|
||||
return xhdi_inquire_target2(major, minor, block_size, flags, product_name, 33);
|
||||
}
|
||||
|
||||
uint32_t xhdi_reserve(uint16_t major, uint16_t minor, uint16_t do_reserve, uint16_t key)
|
||||
{
|
||||
if (major == MY_MAJOR)
|
||||
return ERROR; /* device cannot be reserved */
|
||||
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_lock(uint16_t major, uint16_t minor, uint16_t do_lock, uint16_t key)
|
||||
{
|
||||
if (major == MY_MAJOR)
|
||||
return ERROR; /* device cannot be locked */
|
||||
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_stop(uint16_t major, uint16_t minor, uint16_t do_stop, uint16_t key)
|
||||
{
|
||||
if (major == MY_MAJOR)
|
||||
return ERROR; /* device cannot be locked */
|
||||
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_eject(uint16_t major, uint16_t minor, uint16_t do_eject, uint16_t key)
|
||||
{
|
||||
if (major == MY_MAJOR)
|
||||
return ERROR; /* device cannot be ejected */
|
||||
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_drivemap(void)
|
||||
{
|
||||
long map = (1 << ('S' - 'A'));
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
uint32_t xhdi_inquire_device(uint16_t bios_device, uint16_t *major, uint16_t *minor,
|
||||
uint32_t *start_sector, /* BPB */ void *bpb)
|
||||
{
|
||||
if (major != NULL) *major = MY_MAJOR;
|
||||
if (minor != NULL) *minor = MY_MINOR;
|
||||
if (start_sector != NULL) *start_sector = 0;
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
uint32_t xhdi_inquire_driver(uint16_t bios_device, char *name, char *version,
|
||||
char *company, uint16_t *ahdi_version, uint16_t *maxIPL)
|
||||
{
|
||||
if (bios_device == 'S' - 'A')
|
||||
{
|
||||
if (name != NULL) strcpy(name, "BaS SD-card driver");
|
||||
if (version != NULL) strcpy(version, "0.1");
|
||||
if (company != NULL) strcpy(company, "Markus Fröschle");
|
||||
if (ahdi_version != NULL) *ahdi_version = 300;
|
||||
if (maxIPL != NULL) *maxIPL = 7;
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_new_cookie(uint32_t newcookie)
|
||||
{
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_read_write(uint16_t major, uint16_t minor, uint16_t rwflag,
|
||||
uint32_t recno, uint16_t count, void *buf)
|
||||
{
|
||||
int ret;
|
||||
uint16_t num_sectors;
|
||||
int16_t s_count = count;
|
||||
uint16_t retries;
|
||||
const uint16_t max_retries = 50;
|
||||
|
||||
if (major == MY_MAJOR)
|
||||
{
|
||||
do {
|
||||
num_sectors = ((s_count > 63) ? 63 : s_count);
|
||||
|
||||
retries = 0;
|
||||
do {
|
||||
ret = ((rwflag & 1) ? disk_write(0, buf, recno, num_sectors) : disk_read(0, buf, recno, num_sectors));
|
||||
if (ret != RES_OK)
|
||||
{
|
||||
disk_reset(0);
|
||||
retries++;
|
||||
if (retries < max_retries) continue;
|
||||
|
||||
xprintf("SD card %s error at sector %lx: %d\r\n", (rwflag & 1) ? "write" : "read", recno, ret);
|
||||
return ERROR;
|
||||
}
|
||||
} while (retries < max_retries && ret != RES_OK);
|
||||
|
||||
buf += num_sectors * 512;
|
||||
recno += num_sectors;
|
||||
s_count -= num_sectors;
|
||||
} while (s_count > 0);
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_inquire_target2(uint16_t major, uint16_t minor, uint32_t *block_size,
|
||||
uint32_t *device_flags, char *product_name, uint16_t stringlen)
|
||||
{
|
||||
if (major == MY_MAJOR)
|
||||
{
|
||||
if (block_size != NULL) *block_size = 512;
|
||||
if (device_flags != NULL) *device_flags = XH_TARGET_REMOVABLE;
|
||||
if (product_name != NULL) strncpy(product_name, "BaS SD driver", stringlen);
|
||||
|
||||
return E_OK;
|
||||
|
||||
}
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_inquire_device2(uint16_t bios_device, uint16_t *major, uint16_t *minor,
|
||||
uint32_t *start_sector, BPB *bpb, uint32_t *blocks, char *partid)
|
||||
{
|
||||
|
||||
if (bios_device == 'S' - 'A')
|
||||
{
|
||||
return E_OK;
|
||||
}
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_driver_special(uint32_t key1, uint32_t key2, uint16_t subopcode, void *data)
|
||||
{
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_get_capacity(uint16_t major, uint16_t minor, uint32_t *blocks, uint32_t *bs)
|
||||
{
|
||||
if (major == MY_MAJOR)
|
||||
{
|
||||
if (blocks != 0)
|
||||
{
|
||||
if (disk_ioctl(0, GET_SECTOR_COUNT, blocks) != RES_OK)
|
||||
{
|
||||
xprintf("disk_ioctl(0, GET_SECTOR_COUNT, %p) failed at %s:%d\r\n", blocks, __FILE__, __LINE__);
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
xprintf("%s:%d: determined sector count to %ld\r\n", __FILE__, __LINE__, *blocks);
|
||||
}
|
||||
|
||||
if (bs != 0)
|
||||
{
|
||||
if (disk_ioctl(0, GET_SECTOR_SIZE, bs) != RES_OK)
|
||||
{
|
||||
xprintf("disk_ioctl(0, GET_SECTOR_SIZE, %p) failed at %s:%dr\n", bs, __FILE__, __LINE__);
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
xprintf("%s:%d: determined sector size to %ld\r\n", __FILE__, __LINE__, *bs);
|
||||
}
|
||||
return E_OK;
|
||||
}
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_medium_changed(uint16_t major, uint16_t minor)
|
||||
{
|
||||
if (major == MY_MAJOR)
|
||||
return 1; /* may have changed */
|
||||
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_mint_info(uint16_t opcode, void *data)
|
||||
{
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_dos_limits(uint16_t which, uint32_t limit)
|
||||
{
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_last_access(uint16_t major, uint16_t minor, uint32_t *ms)
|
||||
{
|
||||
return EUNDEV;
|
||||
}
|
||||
|
||||
uint32_t xhdi_reaccess(uint16_t major, uint16_t minor)
|
||||
{
|
||||
return EUNDEV;
|
||||
}
|
||||
40
BaS_gcc/sources/xhdi_vec.S
Normal file
40
BaS_gcc/sources/xhdi_vec.S
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// XHDI entry point
|
||||
//
|
||||
.extern _xhdi_call
|
||||
|
||||
.globl _xhdi_vec
|
||||
.globl _xhdi_sd_install
|
||||
|
||||
//
|
||||
// this is where the XHDI cookie points to:
|
||||
//
|
||||
|
||||
.text
|
||||
_xhdi_vec:
|
||||
lea -12(sp),sp // save all used registers according to XHDI spec
|
||||
movem.l d1/a0-a1,(sp)
|
||||
|
||||
pea 16(sp) // forward address of parameters on stack
|
||||
jsr _xhdi_call // to internal routine
|
||||
addq.l #4,sp // correct stack
|
||||
|
||||
movem.l (sp),d1/a0-a1 // restore registers
|
||||
lea 12(sp),sp
|
||||
rts
|
||||
|
||||
.data
|
||||
_old_vector:
|
||||
.ds.l 1
|
||||
|
||||
.text
|
||||
|
||||
//
|
||||
// trap #0 handler to bring the address of the disk routines into TOS
|
||||
//
|
||||
_xhdi_sd_install:
|
||||
move.l 4(sp),d0 // address of the old XHDI vector
|
||||
move.l d0,_old_vector // save it - just in case we need it later
|
||||
move.l #_xhdi_vec,d0 // return our BaS vector to TOS
|
||||
move.l d0,a0 //
|
||||
rte
|
||||
Reference in New Issue
Block a user