Commit 1e08f1ab authored by Alan Wood's avatar Alan Wood

Cleaned up the ICE40 code

parent 581229c3
......@@ -34,53 +34,52 @@
#define IS_DONE(STATE) (GPIO_ReadInputDataBit(ICE40_PORT, ICE40_CDONE_PIN)==(STATE))
/******************************************************************************
* @Brief Initialiase GPIO pins and SPI peripherals used to program the ICE40 *
******************************************************************************/
void initialise_ice40(void) {
GPIO_InitTypeDef GPIO_Init_S;
SPI_InitTypeDef SPI_Init_S;
//RCC_PCLK2Config(RCC_HCLK_Div2);
/* GPIO clk enable */
// old RCC_AHBPeriphClockCmd(PORT_CLKS, ENABLE);
/* Enble GPIO clks */
RCC_APB2PeriphClockCmd(PORT_CLKS | RCC_APB2Periph_AFIO, ENABLE);
/* SPI clk enable */
//RCC_APB2PeriphClockCmd(ICE40_SPI_CLK, ENABLE);
/* Enable SPI clk */;
RCC_APB1PeriphClockCmd(ICE40_SPI_CLK, ENABLE);
/* Remap JTAG but keep SWD pins, they overlap with outr SPI and LED ports */
//GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
/* Configure pullup pins CS,RESET,Done */
/* Configure ICE40 SPI CS pin*/
GPIO_Init_S.GPIO_Pin = ICE40_SPI_CS_PIN;
GPIO_Init_S.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init_S.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(ICE40_SPI_CS_GPIO_PORT, &GPIO_Init_S);
GPIO_SetBits(ICE40_SPI_CS_GPIO_PORT, ICE40_SPI_CS_PIN);
/* Configure ice40_CRST_PIN pin */
/* Configure ICE40_CRST_PIN pin, used to reset FPGA} */
GPIO_Init_S.GPIO_Pin = ICE40_CRST_PIN;
GPIO_Init(ICE40_PORT , &GPIO_Init_S);
GPIO_SetBits(ICE40_PORT, ICE40_CRST_PIN);
/* leave ice40_CDONE_PIN pin as input with pullup */
/* leave ICE40_CDONE_PIN pin as input with pullup, used to signal FPGA status */
GPIO_Init_S.GPIO_Pin = ICE40_CDONE_PIN;
GPIO_Init_S.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(ICE40_PORT, &GPIO_Init_S);
/* Configure ICE40_SPI pins common features*/
/* Configure ICE40_SPI pins MOSI & SCK*/
GPIO_Init_S.GPIO_Pin = ICE40_SPI_SCK_PIN | ICE40_SPI_MOSI_PIN;
GPIO_Init_S.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init_S.GPIO_Speed = GPIO_Speed_50MHz;
/* Individual pins and init */
GPIO_Init_S.GPIO_Pin = ICE40_SPI_SCK_PIN | ICE40_SPI_MOSI_PIN;
GPIO_Init(ICE40_PORT, &GPIO_Init_S);
/* Configure ICE40 SPI MISO input floating */
GPIO_Init_S.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init_S.GPIO_Pin = ICE40_SPI_MISO_PIN;
GPIO_Init(ICE40_PORT, &GPIO_Init_S);
/* Configure ICE40_SPI operation */
/* Configure and initialise ICE40_SPI operation */
SPI_Init_S.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_Init_S.SPI_Mode = SPI_Mode_Master;
SPI_Init_S.SPI_DataSize = SPI_DataSize_8b;
......@@ -95,144 +94,119 @@ void initialise_ice40(void) {
SPI_Cmd(ICE40_SPI, ENABLE);
}
int spiReadWrite(SPI_TypeDef* SPIx, uint8_t *rbuf,
uint8_t *tbuf, int cnt) {
int spi_read_write(SPI_TypeDef* SPIx, uint8_t *rbuf, uint8_t *tbuf, int cnt) {
int i;
for (i = 0; i < cnt; i++){
while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
if (tbuf) {
if (tbuf)
SPI_I2S_SendData(SPIx, *tbuf++);
} else {
else
SPI_I2S_SendData(SPIx, ANY);
}
// while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
// if (rbuf) {
// *rbuf++ = SPI_I2S_ReceiveData(SPIx);
// } else {
// SPI_I2S_ReceiveData(SPIx);
// }
while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
if (rbuf)
*rbuf++ = SPI_I2S_ReceiveData(SPIx);
else
SPI_I2S_ReceiveData(SPIx);
}
return i;
}
void spiDummy(SPI_TypeDef* SPIx, int cnt) {
for (int i = 0; i < cnt; i++){
while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPIx);
}
}
int spi_write(SPI_TypeDef* SPIx, uint8_t *tbuf, int cnt) {
int i;
uint16_t ice40_spi_write(uint8_t data) {
WAIT_SPI_BUFFER_EMPTY();
ICE40_SPI->DR = data;
WAIT_SPI_BUFFER_RECIEVE();
return ICE40_SPI->DR;
for (i = 0; i < cnt; i++){
while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
if (tbuf)
SPI_I2S_SendData(SPIx, *tbuf++);
else
SPI_I2S_SendData(SPIx, ANY);
}
return i;
}
/******************************************************************************
* @Brief Reset ICE40 and boot into slave mode ready for programing over SPI *
******************************************************************************/
uint8_t ice40_reset(void) {
/* Timing variables */
uint64_t elapsed = 0;
uint32_t timeout = 100;
/* Pull reset low */
/* Pull ICE40 CRESET low to reset FPGA */
GPIO_ResetBits(ICE40_PORT, ICE40_CRST_PIN);
/* Hold SPI CS low whilst resettingice40 */
/* Pull ICE40 SPI CS low whilst resetting FPGA */
GPIO_ResetBits(ICE40_SPI_CS_GPIO_PORT, ICE40_SPI_CS_PIN);
/* Wait for a millisec */
/* Wait for a millisecond */
while(TICK_elapsed_ms(elapsed) < 1);
elapsed = TICK_get_cur();
// Release reset */
// Release ICE40 reset to boot into Slave mode */
GPIO_SetBits(ICE40_PORT, ICE40_CRST_PIN);
/* Makesure CDONE is pulleed down */
/* Makesure ICE40 CDONE has been pulleed low by FPGA in response */
while(timeout && IS_DONE(Bit_SET))
timeout--;
/* Make sure CDONE responded before timeout if not return TIMEOUT error */
if(!timeout) {
/* No CDONE response, tale CS back high*/
/* No CDONE response, take CS back high, then return error*/
GPIO_SetBits(ICE40_SPI_CS_GPIO_PORT, ICE40_SPI_CS_PIN);
return TIMEOUT;
} else {
/* Delay 2 millisecs to allow FPGA to configure */
/* Delay 2 millisecs to allow FPGA to reconfigure itself*/
while(TICK_elapsed_ms(elapsed) < 2);
elapsed = TICK_get_cur();
/* We are all go for programming */
return OK;
}
}
/******************************************************************************
* @ Brief Program the ICE40 in Slave mode, transfer bitfile over SPI_ *
******************************************************************************/
uint8_t ice40_program(uint8_t *bitimg, uint32_t len){
//uint64_t elapsed = 0;
/* Timing Variable */
uint32_t timeout = 100;
/* Lets Reset the ICE40, If good proceed otherwise return error */
if(ice40_reset() != OK) {
GPIO_SetBits(ICE40_SPI_CS_GPIO_PORT, ICE40_SPI_CS_PIN);
return ICE_ERROR;
} else {
/* Light the LED to indicate we are programming */
GPIO_ResetBits(LEDP, LED);
// GPIO_SetBits(ICE40_SPI_CS_GPIO_PORT, ICE40_SPI_CS_PIN);
// while (SPI_I2S_GetFlagStatus(ICE40_SPI, SPI_I2S_FLAG_TXE) == RESET);
// SPI_I2S_SendData(ICE40_SPI, ANY);
// while (SPI_I2S_GetFlagStatus(ICE40_SPI, SPI_I2S_FLAG_RXNE) == RESET);
// SPI_I2S_ReceiveData(ICE40_SPI);
// GPIO_ResetBits(ICE40_SPI_CS_GPIO_PORT, ICE40_SPI_CS_PIN);
/* Write the bitfile over SPI to ICE40 bitfile */
spi_write(ICE40_SPI,bitimg,len);
/* Write bitfile */
spiReadWrite(ICE40_SPI,0,bitimg,len);
/* Wait for CDONE to be pulled back up, keep clocking dummies */
/* Wait for ICE40 CDONE release, keep clocking dummies until it works or timesout */
while(timeout && IS_DONE(Bit_RESET)) {
while (SPI_I2S_GetFlagStatus(ICE40_SPI, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(ICE40_SPI, ANY);
// while (SPI_I2S_GetFlagStatus(ICE40_SPI, SPI_I2S_FLAG_RXNE) == RESET);
// SPI_I2S_ReceiveData(ICE40_SPI);
timeout--;
}
/* Send extra bunch of dummy clks */
/* Send the ICE40 at least 49 clocks using dummy data */
for(int i = 0; i < 7;i++) {
while (SPI_I2S_GetFlagStatus(ICE40_SPI, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(ICE40_SPI, ANY);
// while (SPI_I2S_GetFlagStatus(ICE40_SPI, SPI_I2S_FLAG_RXNE) == RESET);
// SPI_I2S_ReceiveData(ICE40_SPI);
}
// It we timeout before getting CDON return error */
/* If we tiemout before getting CDONE, return error */
if(!timeout) {
/* Release ICE40 SPI CS*/
GPIO_SetBits(ICE40_SPI_CS_GPIO_PORT, ICE40_SPI_CS_PIN);
return TIMEOUT;
}
/* Turn LED of indicating success */
GPIO_SetBits(LEDP, LED);
// while(TICK_elapsed_ms(elapsed) < 2);
// elapsed = TICK_get_cur();
// while(timeout && IS_DONE(Bit_RESET)) {
// timeout--;
// }
// if(!timeout) {
// GPIO_SetBits(ICE40_SPI_CS_GPIO_PORT, ICE40_SPI_CS_PIN);
// return TIMEOUT;
// }
// GPIO_SetBits(LEDP, LED);
/* Release ICE40 SPI CS*/
GPIO_SetBits(ICE40_SPI_CS_GPIO_PORT, ICE40_SPI_CS_PIN);
/* We are all good */
return OK;
}
}
// uint8_t ice40_spi_read(uint8_t byte) {
// WAIT_SPI_BUFFER_EMPTY();
// SPI_SendData8(ICE40_SPI, ANY);
// AIT_SPI_BUFFER_RECIEVE();
// return ICE40_SPI->DR;
// }
// void ice40_write_array(int8_t *bytes, uint32_t len) {
// while(len--)
// ice40_spi_write(*bytes++);
// }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment