support for JTAGWAIT.PRG (configure FPGA from JTAG port) implemented
This commit is contained in:
@@ -229,3 +229,6 @@ COPYING.LESSER
|
||||
dump.bdm
|
||||
mcf5474.gdb
|
||||
Makefile
|
||||
tos/jtagwait/Makefile
|
||||
tos/jtagwait/sources/jtagwait.c
|
||||
tos/jtagwait/include/driver_vec.h
|
||||
|
||||
@@ -236,6 +236,7 @@ SECTIONS
|
||||
* and shouldn't be overwritten on boot
|
||||
*/
|
||||
__FPGA_JTAG_LOADED = __RAMBAR1;
|
||||
__FPGA_JTAG_VALID = __RAMBAR1 + 4;
|
||||
/* system variables */
|
||||
|
||||
/* RAMBAR0 0 to 0x7FF -> exception vectors */
|
||||
|
||||
@@ -50,6 +50,8 @@ extern uint8_t _FPGA_CONFIG_SIZE[];
|
||||
* been loaded through JTAG. init_fpga() will honour this and not overwrite config.
|
||||
*/
|
||||
extern bool _FPGA_JTAG_LOADED;
|
||||
extern long _FPGA_JTAG_VALID;
|
||||
#define VALID_JTAG 0xaffeaffe
|
||||
|
||||
void config_gpio_for_fpga_config(void)
|
||||
{
|
||||
@@ -91,10 +93,10 @@ bool init_fpga(void)
|
||||
volatile int32_t time, start, end;
|
||||
int i;
|
||||
|
||||
dbg("FPGA load config (_FPGA_JTAG_LOADED = %x)...", _FPGA_JTAG_LOADED);
|
||||
if (_FPGA_JTAG_LOADED == 1)
|
||||
dbg("FPGA load config\r\n(_FPGA_JTAG_LOADED = %x, _FPGA_JTAG_VALID = %x)...\r\n", _FPGA_JTAG_LOADED, _FPGA_JTAG_VALID);
|
||||
if (_FPGA_JTAG_LOADED == true)
|
||||
{
|
||||
dbg("detected _FPGA_JTAG_LOADED flag. Not overwriting FPGA config.\r\n");
|
||||
dbg("detected _FPGA_JTAG_LOADED flag. Not overwriting FPGA config.\r\n");
|
||||
|
||||
/* reset the flag so that next boot will load config again from flash */
|
||||
_FPGA_JTAG_LOADED = 0;
|
||||
|
||||
@@ -244,7 +244,7 @@ void init_serial(void)
|
||||
MCF_PSC0_PSCOPSET = 0x01;
|
||||
MCF_PSC0_PSCCR = 0x05;
|
||||
|
||||
#ifdef MACHINE_FIREBEE /* PSC3 is not connected to anything on the LITE board */
|
||||
#if defined(MACHINE_FIREBEE) /* PSC3 is not connected to anything on the LITE board */
|
||||
/* PSC3: PIC */
|
||||
MCF_PSC3_PSCSICR = 0; // UART
|
||||
MCF_PSC3_PSCCSR = 0xDD;
|
||||
@@ -480,7 +480,11 @@ void wait_pll(void)
|
||||
} while ((* (volatile int16_t *) 0xf0000800 < 0) && MCF_SLT0_SCNT > trgt);
|
||||
}
|
||||
|
||||
static volatile uint8_t *pll_base = (volatile uint8_t *) 0xf0000600;
|
||||
|
||||
volatile uint8_t *pll_base = (volatile uint8_t *) 0xf0000600;
|
||||
|
||||
//#define _OLD_CODE_ /* use old PLL initialization code */
|
||||
#ifndef _OLD_CODE_
|
||||
|
||||
/*
|
||||
* the altpll_reconfig component is connected to the Bus as follows:
|
||||
@@ -562,7 +566,7 @@ struct pll_init
|
||||
int data;
|
||||
};
|
||||
|
||||
static struct pll_init pll_values[] =
|
||||
struct pll_init pll_values[] =
|
||||
{
|
||||
{ PLL_COUNTER_TYPE_CPLF, PLL_COUNTER_PARAM_LF_R, 27 }, /* loopfilter R */
|
||||
{ PLL_COUNTER_TYPE_CPLF, PLL_COUNTER_PARAM_LF_C, 1 }, /* charge pump 1 */
|
||||
@@ -576,9 +580,9 @@ static struct pll_init pll_values[] =
|
||||
{ PLL_COUNTER_TYPE_M, PLL_COUNTER_PARAM_MODE, 1 }, /* M odd division */
|
||||
{ PLL_COUNTER_TYPE_M, PLL_COUNTER_PARAM_LC, 1 }, /* M low = 1 */
|
||||
{ PLL_COUNTER_TYPE_M, PLL_COUNTER_PARAM_HC, 145 } /* M high = 145 = 146 MHz */
|
||||
|
||||
};
|
||||
static int num_pll_values = sizeof(pll_values) / sizeof(struct pll_init);
|
||||
int num_pll_values = sizeof(pll_values) / sizeof(struct pll_init);
|
||||
#endif /* _OLD_CODE_ */
|
||||
|
||||
void init_pll(void)
|
||||
{
|
||||
@@ -586,11 +590,52 @@ void init_pll(void)
|
||||
|
||||
xprintf("FPGA PLL initialization: ");
|
||||
|
||||
#ifndef _OLD_CODE_
|
||||
for (i = 0; i < num_pll_values; i++)
|
||||
{
|
||||
pll_write(pll_values[i].type, pll_values[i].param, pll_values[i].data);
|
||||
}
|
||||
|
||||
#else /* _OLD_CODE_ */
|
||||
wait_pll();
|
||||
* (volatile uint16_t *) (pll_base + 0x48) = 27; /* loopfilter r */
|
||||
|
||||
wait_pll();
|
||||
* (volatile uint16_t *) (pll_base + 0x08) = 1; /* charge pump 1 */
|
||||
|
||||
wait_pll();
|
||||
* (volatile uint16_t *) (pll_base + 0x00) = 12; /* N counter high = 12 */
|
||||
|
||||
wait_pll();
|
||||
* (volatile uint16_t *) (pll_base + 0x40) = 12; /* N counter low = 12 */
|
||||
|
||||
wait_pll();
|
||||
* (volatile uint16_t *) (pll_base + 0x114) = 1; /* ck1 bypass */
|
||||
|
||||
wait_pll();
|
||||
* (volatile uint16_t *) (pll_base + 0x118) = 1; /* ck2 bypass */
|
||||
|
||||
wait_pll();
|
||||
* (volatile uint16_t *) (pll_base + 0x11c) = 1; /* ck3 bypass */
|
||||
|
||||
wait_pll();
|
||||
* (volatile uint16_t *) (pll_base + 0x10) = 1; /* ck0 high = 1 */
|
||||
|
||||
wait_pll();
|
||||
* (volatile uint16_t *) (pll_base + 0x50) = 1; /* ck0 low = 1 */
|
||||
|
||||
wait_pll();
|
||||
* (volatile uint16_t *) (pll_base + 0x144) = 1; /* M odd division */
|
||||
|
||||
wait_pll();
|
||||
* (volatile uint16_t *) (pll_base + 0x44) = 1; /* M low = 1 */
|
||||
|
||||
wait_pll();
|
||||
* (volatile uint16_t *) (pll_base + 0x04) = 145; /* M high = 145 = 146 MHz */
|
||||
|
||||
wait_pll();
|
||||
#endif /* _OLD_CODE_ */
|
||||
|
||||
* (volatile uint8_t *) 0xf0000800 = 0; /* set */
|
||||
|
||||
xprintf("finished\r\n");
|
||||
@@ -629,7 +674,7 @@ void init_video_ddr(void) {
|
||||
_VRAM = 0000070022; /* load MR dll on */
|
||||
NOP();
|
||||
|
||||
* (uint32_t *) 0xf0000400 = 0x01070002; /* fifo on, refresh on, ddrcs und cke on, video dac on */
|
||||
* (uint32_t *) 0xf0000400 = 0x01070002; /* fifo on, refresh on, ddrcs and cke on, video dac on */
|
||||
|
||||
xprintf("finished\r\n");
|
||||
}
|
||||
@@ -655,19 +700,19 @@ void init_usb(void)
|
||||
if (handle > 0)
|
||||
{
|
||||
uint32_t id = 0;
|
||||
uint32_t class = 0;
|
||||
uint32_t pci_class = 0;
|
||||
|
||||
id = pci_read_config_longword(handle, PCIIDR);
|
||||
class = pci_read_config_longword(handle, PCIREV);
|
||||
pci_class = pci_read_config_longword(handle, PCIREV);
|
||||
|
||||
if (PCI_CLASS_CODE(class) == PCI_CLASS_SERIAL_USB)
|
||||
if (PCI_CLASS_CODE(pci_class) == PCI_CLASS_SERIAL_USB)
|
||||
{
|
||||
xprintf("serial USB found at bus=0x%x, dev=0x%x, fnc=0x%x (0x%x)\r\n",
|
||||
PCI_BUS_FROM_HANDLE(handle),
|
||||
PCI_DEVICE_FROM_HANDLE(handle),
|
||||
PCI_FUNCTION_FROM_HANDLE(handle),
|
||||
handle);
|
||||
if (PCI_SUBCLASS(class) == PCI_CLASS_SERIAL_USB_EHCI)
|
||||
if (PCI_SUBCLASS(pci_class) == PCI_CLASS_SERIAL_USB_EHCI)
|
||||
{
|
||||
board = ehci_usb_pci_table;
|
||||
while (board->vendor)
|
||||
@@ -682,7 +727,7 @@ void init_usb(void)
|
||||
board++;
|
||||
}
|
||||
}
|
||||
if (PCI_SUBCLASS(class) == PCI_CLASS_SERIAL_USB_OHCI)
|
||||
if (PCI_SUBCLASS(pci_class) == PCI_CLASS_SERIAL_USB_OHCI)
|
||||
{
|
||||
board = ohci_usb_pci_table;
|
||||
while (board->vendor)
|
||||
@@ -1176,9 +1221,9 @@ void initialize_hardware(void)
|
||||
video_init();
|
||||
|
||||
/* do not try to init USB for now on the Firebee, it hangs the machine */
|
||||
#ifndef MACHINE_FIREBEE
|
||||
//init_usb();
|
||||
#endif
|
||||
//#ifndef MACHINE_FIREBEE
|
||||
init_usb();
|
||||
//#endif
|
||||
|
||||
#if MACHINE_FIREBEE
|
||||
init_ac97();
|
||||
|
||||
@@ -33,9 +33,13 @@ APP=jtagwait.prg
|
||||
TEST_APP=$(APP)
|
||||
|
||||
CFLAGS=\
|
||||
-Os\
|
||||
-O0\
|
||||
-g\
|
||||
-Wl,-Map,mapfile\
|
||||
-Wl,--defsym -Wl,__MBAR=0xff000000\
|
||||
-Wl,--defsym -Wl,__MMUBAR=0xff040000\
|
||||
-Wl,--defsym -Wl,__FPGA_JTAG_LOADED=0xff101000\
|
||||
-Wl,--defsym -Wl,__FPGA_JTAG_VALID=0xff101004\
|
||||
-Wall
|
||||
|
||||
SRCDIR=sources
|
||||
@@ -43,8 +47,10 @@ INCDIR=include
|
||||
INCLUDE+=-I$(INCDIR)
|
||||
|
||||
CSRCS=\
|
||||
$(SRCDIR)/jtagwait.c
|
||||
ASRCS=
|
||||
$(SRCDIR)/jtagwait.c \
|
||||
$(SRCDIR)/bas_printf.c
|
||||
|
||||
ASRCS=$(SRCDIR)/printf_helper.S
|
||||
|
||||
COBJS=$(patsubst $(SRCDIR)/%.o,%.o,$(patsubst %.c,%.o,$(CSRCS)))
|
||||
AOBJS=$(patsubst $(SRCDIR)/%.o,%.o,$(patsubst %.S,%.o,$(ASRCS)))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 3.0.1, 2014-08-04T18:51:58. -->
|
||||
<!-- Written by QtCreator 3.0.1, 2014-08-09T06:49:40. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
|
||||
@@ -3,73 +3,78 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "bas_printf.h"
|
||||
#include "MCF5475.h"
|
||||
#include "driver_vec.h"
|
||||
|
||||
#define FPGA_JTAG_LOADED_FLAG ((volatile bool *) 0xFF101000)
|
||||
extern bool _FPGA_JTAG_LOADED;
|
||||
extern long _FPGA_JTAG_VALID;
|
||||
|
||||
#define VALID_JTAG 0xaffeaffe
|
||||
|
||||
#define _MBAR ((volatile uint8_t *) 0xFF000000)
|
||||
#define MCF_GPIO_PDDR_FEC1L ((volatile uint8_t *)(&_MBAR[0xA17]))
|
||||
#define MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4 (0x10)
|
||||
#define MCF_GPIO_PPDSDR_FEC1L ((volatile uint8_t *)(&_MBAR[0xA27]))
|
||||
#define FPGA_CONFIG (1 << 2)
|
||||
#define FPGA_CONF_DONE (1 << 5)
|
||||
|
||||
static inline uint32_t set_ipl(uint32_t ipl)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" move.w sr,%[ret]\r\n" /* retrieve status register */
|
||||
" andi.l #0x07,%[ipl]\n\t" /* mask out ipl bits on new value */
|
||||
" lsl.l #8,%[ipl]\n\t" /* shift them to position */
|
||||
" move.l %[ret],d0\n\t" /* retrieve original value */
|
||||
" andi.l #0x0000f8ff,d0\n\t" /* clear ipl part */
|
||||
" or.l %[ipl],d0\n\t" /* or in new value */
|
||||
" move.w d0,sr\n\t" /* put it in place */
|
||||
" andi.l #0x0700,%[ret]\r\n" /* mask out ipl bits */
|
||||
" lsr.l #8,%[ret]\r\n" /* shift them to position */
|
||||
: [ret] "=&d" (ret) /* output */
|
||||
: [ipl] "d" (ipl) /* input */
|
||||
: "d0", "cc" /* clobber */
|
||||
);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void wait_for_jtag(void)
|
||||
{
|
||||
set_ipl(7); /* disable interrupts */
|
||||
/*
|
||||
* configure FEC1L port directions to enable external JTAG configuration download to FPGA
|
||||
*/
|
||||
*MCF_GPIO_PDDR_FEC1L = 0 |
|
||||
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4; /* bit 4 = LED => output */
|
||||
/* all other bits = input */
|
||||
/*
|
||||
* now that this GPIO ports have been switched to input, we can poll for FPGA config
|
||||
* started from the JTAG interface (CONFIGn goes high) and finish (CONF_DONE goes high)
|
||||
*/
|
||||
while (*MCF_GPIO_PPDSDR_FEC1L & FPGA_CONFIG); /* wait for JTAG reset */
|
||||
while (!(*MCF_GPIO_PPDSDR_FEC1L & FPGA_CONFIG)); /* wait for JTAG config load starting */
|
||||
while (!(*MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE)); /* wait for JTAG config load finished */
|
||||
int i;
|
||||
|
||||
*FPGA_JTAG_LOADED_FLAG = true; /* indicate jtag loaded FPGA config to BaS */
|
||||
/* set supervisor stack to end of SRAM1 */
|
||||
__asm__ __volatile__ (
|
||||
" move #0x2700,sr\n\t" /* disable interrupts */
|
||||
" move.l #0xff101000 + 0x1000 - 4,d0\n\t" /* 4KB on-chip core SRAM1 */
|
||||
" move.l d0,sp\n\t" /* set stack pointer */
|
||||
:
|
||||
:
|
||||
: "d0", "cc" /* clobber */
|
||||
);
|
||||
|
||||
/*
|
||||
* reboot after configuration finished
|
||||
*/
|
||||
__asm__ __volatile__(
|
||||
"jmp 0xE0000000\n\t"
|
||||
);
|
||||
MCF_EPORT_EPIER = 0x0; /* disable EPORT interrupts */
|
||||
MCF_INTC_IMRL = 0xffffffff;
|
||||
MCF_INTC_IMRH = 0xffffffff; /* disable interrupt controller */
|
||||
|
||||
MCF_MMU_MMUCR &= ~MCF_MMU_MMUCR_EN; /* disable MMU */
|
||||
|
||||
xprintf("relocated supervisor stack, disabled interrupts and disabled MMU\r\n");
|
||||
|
||||
/*
|
||||
* configure FEC1L port directions to enable external JTAG configuration download to FPGA
|
||||
*/
|
||||
MCF_GPIO_PDDR_FEC1L = 0 |
|
||||
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4; /* bit 4 = LED => output */
|
||||
/* all other bits = input */
|
||||
|
||||
xprintf("waiting for JTAG configuration start\r\n");
|
||||
/*
|
||||
* now that this GPIO ports have been switched to input, we can poll for FPGA config
|
||||
* started from the JTAG interface (CONF_DONE goes low) and finish (CONF_DONE goes high)
|
||||
*/
|
||||
while ((MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE)); /* wait for JTAG config load started */
|
||||
|
||||
xprintf("waiting for JTAG configuration finished\r\n");
|
||||
while (!(MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE)); /* wait for JTAG config load finished */
|
||||
|
||||
xprintf("JTAG configuration finished.\r\n");
|
||||
_FPGA_JTAG_LOADED = true; /* indicate jtag loaded FPGA config to BaS */
|
||||
_FPGA_JTAG_VALID = VALID_JTAG;
|
||||
|
||||
/* wait */
|
||||
xprintf("wait a little to let things settle...\r\n");
|
||||
for (i = 0; i < 1000000; i++);
|
||||
|
||||
__asm__ __volatile__(
|
||||
" jmp 0xe0000000\n\t"
|
||||
: : :
|
||||
);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf("\033E\r\nFPGA JTAG configuration support\r\n");
|
||||
printf("You may now savely load a new FPGA configuration through the JTAG interface\r\n"
|
||||
"and your Firebee will reboot once finished using that new configuration.\r\n");
|
||||
Supexec(wait_for_jtag);
|
||||
printf("\033E\r\nFPGA JTAG configuration support\r\n");
|
||||
printf("You may now savely load a new FPGA configuration through the JTAG interface\r\n"
|
||||
"and your Firebee will reboot once finished using that new configuration.\r\n");
|
||||
Supexec(wait_for_jtag);
|
||||
|
||||
return 0; /* just to make the compiler happy, we will never return */
|
||||
return 0; /* just to make the compiler happy, we will never return */
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user