fixed errornous deactivation of FPGA load
This commit is contained in:
@@ -236,6 +236,8 @@ SECTIONS
|
|||||||
* and shouldn't be overwritten on boot
|
* and shouldn't be overwritten on boot
|
||||||
*/
|
*/
|
||||||
__FPGA_JTAG_LOADED = __RAMBAR1;
|
__FPGA_JTAG_LOADED = __RAMBAR1;
|
||||||
|
__FPGA_JTAG_VALID = __FPGA_JTAG_LOADED + 4;
|
||||||
|
|
||||||
/* system variables */
|
/* system variables */
|
||||||
|
|
||||||
/* RAMBAR0 0 to 0x7FF -> exception vectors */
|
/* RAMBAR0 0 to 0x7FF -> exception vectors */
|
||||||
|
|||||||
206
sys/init_fpga.c
206
sys/init_fpga.c
@@ -40,39 +40,42 @@ extern uint8_t _FPGA_CONFIG_SIZE[];
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* flag located in processor SRAM1 that indicates that the FPGA configuration has
|
* flag located in processor SRAM1 that indicates that the FPGA configuration has
|
||||||
* been loaded through JTAG. init_fpga() will honour this and not overwrite config.
|
* been loaded through the onboard JTAG interface.
|
||||||
|
* init_fpga() will honour this and not overwrite config.
|
||||||
*/
|
*/
|
||||||
extern int32_t _FPGA_JTAG_LOADED;
|
extern int32_t _FPGA_JTAG_LOADED;
|
||||||
|
extern int32_t _FPGA_JTAG_VALID;
|
||||||
|
#define VALID_JTAG 0xaffeaffe
|
||||||
|
|
||||||
void config_gpio_for_fpga_config(void)
|
void config_gpio_for_fpga_config(void)
|
||||||
{
|
{
|
||||||
#if defined(MACHINE_FIREBEE)
|
#if defined(MACHINE_FIREBEE)
|
||||||
/*
|
/*
|
||||||
* Configure GPIO FEC1L port directions (needed to load FPGA configuration)
|
* Configure GPIO FEC1L port directions (needed to load FPGA configuration)
|
||||||
*/
|
*/
|
||||||
MCF_GPIO_PDDR_FEC1L = 0 | /* bit 7 = input */
|
MCF_GPIO_PDDR_FEC1L = 0 | /* bit 7 = input */
|
||||||
0 | /* bit 6 = input */
|
0 | /* bit 6 = input */
|
||||||
0 | /* bit 5 = input */
|
0 | /* bit 5 = input */
|
||||||
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4 | /* bit 4 = LED => output */
|
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4 | /* bit 4 = LED => output */
|
||||||
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L3 | /* bit 3 = PRG_DQ0 => output */
|
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L3 | /* bit 3 = PRG_DQ0 => output */
|
||||||
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L2 | /* bit 2 = FPGA_CONFIG => output */
|
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L2 | /* bit 2 = FPGA_CONFIG => output */
|
||||||
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L1 | /* bit 1 = PRG_CLK (FPGA) => output */
|
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L1 | /* bit 1 = PRG_CLK (FPGA) => output */
|
||||||
0; /* bit 0 => input */
|
0; /* bit 0 => input */
|
||||||
#endif /* MACHINE_FIREBEE */
|
#endif /* MACHINE_FIREBEE */
|
||||||
}
|
}
|
||||||
|
|
||||||
void config_gpio_for_jtag_config(void)
|
void config_gpio_for_jtag_config(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* configure FEC1L port directions to enable external JTAG configuration download to FPGA
|
* configure FEC1L port directions to enable external JTAG configuration download to FPGA
|
||||||
*/
|
*/
|
||||||
MCF_GPIO_PDDR_FEC1L = 0 |
|
MCF_GPIO_PDDR_FEC1L = 0 |
|
||||||
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4; /* bit 4 = LED => output */
|
MCF_GPIO_PDDR_FEC1L_PDDR_FEC1L4; /* bit 4 = LED => output */
|
||||||
/* all other bits = input */
|
/* all other bits = input */
|
||||||
/*
|
/*
|
||||||
* unfortunately, the GPIO module cannot trigger interrupts. That means FPGA_CONFIG needs to be polled to detect
|
* unfortunately, the GPIO module cannot trigger interrupts. That means FPGA_CONFIG needs to be polled to detect
|
||||||
* external FPGA (re)configuration and reset the system in that case. Could be done from the OS as well...
|
* external FPGA (re)configuration and reset the system in that case. Could be done from the OS as well...
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -80,96 +83,99 @@ void config_gpio_for_jtag_config(void)
|
|||||||
*/
|
*/
|
||||||
bool init_fpga(void)
|
bool init_fpga(void)
|
||||||
{
|
{
|
||||||
uint8_t *fpga_data;
|
uint8_t *fpga_data;
|
||||||
volatile int32_t time, start, end;
|
volatile int32_t time, start, end;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
xprintf("FPGA load config (_FPGA_JTAG_LOADED = %x)...", _FPGA_JTAG_LOADED);
|
xprintf("FPGA load config (_FPGA_JTAG_LOADED = %x, _FPGA_JTAG_VALID = %x)...", _FPGA_JTAG_LOADED, _FPGA_JTAG_VALID);
|
||||||
if (_FPGA_JTAG_LOADED == 1)
|
if (_FPGA_JTAG_LOADED == 1 && _FPGA_JTAG_VALID == VALID_JTAG)
|
||||||
{
|
{
|
||||||
xprintf("detected _FPGA_JTAG_LOADED flag. Not overwriting FPGA config.\r\n");
|
xprintf("detected _FPGA_JTAG_LOADED flag. Not overwriting FPGA config.\r\n");
|
||||||
|
|
||||||
/* reset the flag so that next boot will load config again from flash */
|
/* reset the flag so that next boot will load config again from flash */
|
||||||
_FPGA_JTAG_LOADED = 0;
|
_FPGA_JTAG_LOADED = 0;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
start = MCF_SLT0_SCNT;
|
|
||||||
|
|
||||||
config_gpio_for_fpga_config();
|
return true;
|
||||||
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK; /* FPGA clock => low */
|
}
|
||||||
|
start = MCF_SLT0_SCNT;
|
||||||
|
|
||||||
/* pulling FPGA_CONFIG to low resets the FPGA */
|
config_gpio_for_fpga_config();
|
||||||
MCF_GPIO_PODR_FEC1L &= ~FPGA_CONFIG; /* FPGA config => low */
|
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK; /* FPGA clock => 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));
|
/* 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 */
|
||||||
|
|
||||||
MCF_GPIO_PODR_FEC1L |= FPGA_CONFIG; /* pull FPGA_CONFIG high to start config cycle */
|
while ((MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS) && (MCF_GPIO_PPDSDR_FEC1L & FPGA_CONF_DONE));
|
||||||
while (!(MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS)); /* wait until status becomes high */
|
|
||||||
|
|
||||||
/*
|
MCF_GPIO_PODR_FEC1L |= FPGA_CONFIG; /* pull FPGA_CONFIG high to start config cycle */
|
||||||
* excerpt from an Altera configuration manual:
|
while (!(MCF_GPIO_PPDSDR_FEC1L & FPGA_STATUS))
|
||||||
*
|
; /* wait until status becomes high */
|
||||||
* 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;
|
/*
|
||||||
|
* excerpt from an Altera configuration manual:
|
||||||
|
*
|
||||||
|
* The low-to-high transition of nCONFIG on the FPGA begins the configuration cycle. The
|
||||||
|
* configuration cycle consists of 3 stages<65>reset, configuration, and initialization.
|
||||||
|
* While nCONFIG is low, the device is in reset. When the device comes out of reset,
|
||||||
|
* nCONFIG must be at a logic high level in order for the device to release the open-drain
|
||||||
|
* nSTATUS pin. After nSTATUS is released, it is pulled high by a pull-up resistor and the FPGA
|
||||||
|
* is ready to receive configuration data. Before and during configuration, all user I/O pins
|
||||||
|
* are tri-stated. Stratix series, Arria series, and Cyclone series have weak pull-up resistors
|
||||||
|
* on the I/O pins which are on, before and during configuration.
|
||||||
|
*
|
||||||
|
* To begin configuration, nCONFIG and nSTATUS must be at a logic high level. You can delay
|
||||||
|
* configuration by holding the nCONFIG low. The device receives configuration data on its
|
||||||
|
* DATA0 pins. Configuration data is latched into the FPGA on the rising edge of DCLK. After
|
||||||
|
* the FPGA has received all configuration data successfully, it releases the CONF_DONE pin,
|
||||||
|
* which is pulled high by a pull-up resistor. A low to high transition on CONF_DONE indicates
|
||||||
|
* configuration is complete and initialization of the device can begin.
|
||||||
|
*/
|
||||||
|
|
||||||
fpga_data = (uint8_t *) FPGA_FLASH_DATA;
|
const uint8_t *fpga_flash_data_end = FPGA_FLASH_DATA + FPGA_FLASH_DATA_SIZE;
|
||||||
do
|
|
||||||
{
|
|
||||||
uint8_t value = *fpga_data++;
|
|
||||||
for (i = 0; i < 8; i++, value >>= 1)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (value & 1)
|
fpga_data = (uint8_t *) FPGA_FLASH_DATA;
|
||||||
{
|
do
|
||||||
/* bit set -> toggle DATA0 to high */
|
{
|
||||||
MCF_GPIO_PODR_FEC1L |= FPGA_DATA0;
|
uint8_t value = *fpga_data++;
|
||||||
}
|
for (i = 0; i < 8; i++, value >>= 1)
|
||||||
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)
|
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)
|
||||||
|
{
|
||||||
#ifdef _NOT_USED_
|
#ifdef _NOT_USED_
|
||||||
while (fpga_data++ < fpga_flash_data_end)
|
while (fpga_data++ < fpga_flash_data_end)
|
||||||
{
|
{
|
||||||
/* toggle a little more since it's fun ;) */
|
/* toggle a little more since it's fun ;) */
|
||||||
MCF_GPIO_PODR_FEC1L |= FPGA_CLOCK;
|
MCF_GPIO_PODR_FEC1L |= FPGA_CLOCK;
|
||||||
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK;
|
MCF_GPIO_PODR_FEC1L &= ~FPGA_CLOCK;
|
||||||
}
|
}
|
||||||
#endif /* _NOT_USED_ */
|
#endif /* _NOT_USED_ */
|
||||||
end = MCF_SLT0_SCNT;
|
end = MCF_SLT0_SCNT;
|
||||||
time = (start - end) / (SYSCLK / 1000) / 1000;
|
time = (start - end) / (SYSCLK / 1000) / 1000;
|
||||||
|
|
||||||
xprintf("finished (took %f seconds).\r\n", time / 1000.0);
|
xprintf("finished (took %f seconds).\r\n", time / 1000.0);
|
||||||
config_gpio_for_jtag_config();
|
config_gpio_for_jtag_config();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
xprintf("FAILED!\r\n");
|
xprintf("FAILED!\r\n");
|
||||||
config_gpio_for_jtag_config();
|
config_gpio_for_jtag_config();
|
||||||
return false;
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user