From fb2d080fbbcea3a91e598b4ea8837a230de6a319 Mon Sep 17 00:00:00 2001 From: Shlomo Hecht Date: Tue, 6 Mar 2018 12:09:02 +0200 Subject: A new forlder for embedded software in our common structure --- .../Embedded/Drivers/Flash_Memory/Flash_Memory.c | 488 +++++++++++++++++++++ .../Embedded/Drivers/Flash_Memory/Flash_Memory.h | 6 + 2 files changed, 494 insertions(+) create mode 100644 Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.c create mode 100644 Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.h (limited to 'Software/Embedded_SW/Embedded/Drivers/Flash_Memory') diff --git a/Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.c b/Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.c new file mode 100644 index 000000000..5eea54a1c --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.c @@ -0,0 +1,488 @@ +//Avi Last update: 20/12/17 +//Based on TM4C129_SSI3_MacronixFlash.c +//On board Quad SPI 512Mb Flash + +#include +#include +#include +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "inc/hw_gpio.h" +#include "inc/hw_ssi.h" +#include "inc/hw_sysctl.h" +#include "inc/hw_epi.h" +#include "inc/hw_ints.h" +#include "inc/hw_nvic.h" + +#include "driverlib/debug.h" +#include "driverlib/fpu.h" +#include "driverlib/gpio.h" +#include "driverlib/rom.h" +#include "driverlib/rom_map.h" +#include "driverlib/interrupt.h" +#include "driverlib/pin_map.h" +#include "driverlib/sysctl.h" +#include "driverlib/ssi.h" +#include "driverlib/uart.h" +#include "utils/uartstdio.h" + +#include "drivers/twine_graphicslib/graphics_adapter.h" +#include "include.h" + +//#define NUM_SSI_DATA 20 +#define INS_WRITE_ENABLE 0x06 +#define INS_READ_STATUS_REGISTER1 0x05 +#define DUMMY_BYTE 0x00 +#define FLASH_BUSY_BIT 0x01 +#define FLASH_WRITE_EN_LATCH_BIT 0x02 +#define INS_SECTOR_ERASE_4KB 0x20 +#define INS_PAGE_PROGRAM 0x02 +#define INS_READ_DATA 0x03 + + +uint8_t g_ui8InstrReadID[] = {0x90,0x00,0x00,0x00}; +//uint32_t pui32DataTx[NUM_SSI_DATA]; +//uint32_t pui32DataRx[NUM_SSI_DATA]; + +//***************************************************************************** +// +// This function sets up SSI External Flash ID Read +// +//***************************************************************************** +uint32_t SSILibSendReadIDAdvMode(uint32_t ui32Base) +{ + uint32_t ui32Idx, ui32Receive; + uint32_t ui32MfgID; + uint32_t ui32DevID; + uint32_t ui32ReadID[]={0xaa,0xaa}; + uint32_t ui32ReadIDFlash; + + for(ui32Idx = 0; ui32Idx < sizeof(g_ui8InstrReadID) / sizeof(g_ui8InstrReadID[0]); ui32Idx++) + { + SSIDataPut(ui32Base, g_ui8InstrReadID[ui32Idx]); + } + + SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE); + SSIDataPut(ui32Base, 0x00); + SSIDataGet(ui32Base, &ui32Receive); + ui32ReadID[0] = ui32Receive; + SSIAdvDataPutFrameEnd(ui32Base,0x00); + SSIDataGet(ui32Base, &ui32Receive); + ui32ReadID[1] = ui32Receive; + ui32MfgID = ui32ReadID[0]; + ui32DevID = ui32ReadID[1]; + ui32ReadIDFlash = ui32MfgID; + + ui32ReadIDFlash = ui32ReadIDFlash << 8; + ui32ReadIDFlash |= ui32DevID; + + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + + return ui32ReadIDFlash; +} + +uint8_t SSILibSendReadStatusRegister(uint32_t ui32Base, uint8_t ui8FlashCommand) +{ + uint32_t ui32Status = 0; + uint8_t ui8FlashStatus; + + SSIAdvFrameHoldEnable(ui32Base); + SSIDataPut(ui32Base,ui8FlashCommand); + SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE); + SSIAdvDataPutFrameEnd(ui32Base,DUMMY_BYTE); + while(SSIBusy(ui32Base)); + SSIDataGet(ui32Base, &ui32Status); + ui8FlashStatus = (uint8_t)ui32Status; + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + + return ui8FlashStatus; +} + + +void SSILibDeviceBusyCheck(uint32_t ui32Base) +{ + uint8_t ui8TempData=0xFF; + + ui8TempData = SSILibSendReadStatusRegister(ui32Base,INS_READ_STATUS_REGISTER1); + + while((ui8TempData & FLASH_BUSY_BIT) == FLASH_BUSY_BIT) + { + ui8TempData = SSILibSendReadStatusRegister(ui32Base,INS_READ_STATUS_REGISTER1); + } +} + +void SSILibSendPageProgram(uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand) +{ + uint32_t ui32TempAddr, ui32TempData; + uint8_t ui8AddrByte1, ui8AddrByte2, ui8AddrByte3; + + ui32TempAddr = ui32Address >> 16 ; + ui8AddrByte1 = (uint8_t)ui32TempAddr; + ui32TempAddr = ui32Address >> 8 ; + ui8AddrByte2 = (uint8_t)ui32TempAddr; + ui8AddrByte3 = (uint8_t)ui32Address; + + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + SSIAdvFrameHoldEnable(ui32Base); + SSIAdvDataPutFrameEnd(ui32Base,INS_WRITE_ENABLE); + while(SSIBusy(ui32Base)); + + ui32TempData = SSILibSendReadStatusRegister(ui32Base,INS_READ_STATUS_REGISTER1); + while((ui32TempData & FLASH_WRITE_EN_LATCH_BIT) != FLASH_WRITE_EN_LATCH_BIT) { + ui32TempData = SSILibSendReadStatusRegister(ui32Base,INS_READ_STATUS_REGISTER1); + } + + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + SSIAdvFrameHoldEnable(ui32Base); + SSIDataPut(ui32Base,ui8FlashCommand); + SSIDataPut(ui32Base,ui8AddrByte1); + SSIDataPut(ui32Base,ui8AddrByte2); + SSIDataPut(ui32Base,ui8AddrByte3); +} + +void SSILibSendReadDataAdvBi(uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand) +{ + uint32_t ui32TempAddr; + uint8_t ui8AddrByte1, ui8AddrByte2, ui8AddrByte3; + + ui32TempAddr = ui32Address >> 16 ; + ui8AddrByte1 = (uint8_t)ui32TempAddr; + ui32TempAddr = ui32Address >> 8 ; + ui8AddrByte2 = (uint8_t)ui32TempAddr; + ui8AddrByte3 = (uint8_t)ui32Address; + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + SSIAdvFrameHoldEnable(ui32Base); + SSIDataPut(ui32Base,ui8FlashCommand); + SSIDataPut(ui32Base,ui8AddrByte1); + SSIDataPut(ui32Base,ui8AddrByte2); + SSIDataPut(ui32Base,ui8AddrByte3); + + SSIAdvModeSet(ui32Base,SSI_ADV_MODE_READ_WRITE); +} + + +//***************************************************************************** +// +// This function sets up SSI External Flash Erase +// +//***************************************************************************** +void SSILibSendEraseCommand (uint32_t ui32Base, uint32_t ui32Address, uint8_t ui8FlashCommand) +{ + uint32_t ui32TempAddr, ui32TempData; + uint8_t ui8AddrByte1, ui8AddrByte2, ui8AddrByte3; + + ui32TempAddr = ui32Address >> 16 ; + + ui8AddrByte1 = (uint8_t)ui32TempAddr; + ui32TempAddr = ui32Address >> 8 ; + ui8AddrByte2 = (uint8_t)ui32TempAddr; + ui8AddrByte3 = (uint8_t)ui32Address; + + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + SSIAdvFrameHoldEnable(ui32Base); + SSIAdvDataPutFrameEnd(ui32Base,INS_WRITE_ENABLE); + while(SSIBusy(ui32Base)); + + ui32TempData = SSILibSendReadStatusRegister(ui32Base,INS_READ_STATUS_REGISTER1); + while((ui32TempData & FLASH_WRITE_EN_LATCH_BIT) != FLASH_WRITE_EN_LATCH_BIT) { + ui32TempData = SSILibSendReadStatusRegister(ui32Base,INS_READ_STATUS_REGISTER1); + } + + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + SSIAdvFrameHoldEnable(ui32Base); + SSIDataPut(ui32Base,ui8FlashCommand); + SSIDataPut(ui32Base,ui8AddrByte1); + SSIDataPut(ui32Base,ui8AddrByte2); + SSIAdvDataPutFrameEnd(ui32Base,ui8AddrByte3); + while(SSIBusy(ui32Base)); + //wait till the erase is completed + SSILibDeviceBusyCheck(ui32Base); + +} + + +int Init_Ext_Flash() +{ + uint32_t pui32Dummy[1]; + uint32_t ui32SysClockFreq; + + // + // Set the clocking to run directly from the external crystal/oscillator. + // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the + // crystal on your board. + // + ui32SysClockFreq = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | + SYSCTL_OSC_MAIN | + SYSCTL_USE_PLL | + SYSCTL_CFG_VCO_480), 120000000); + + // Display the setup on the console. + writeLine("SSI3 To DK-TM4C129 FLASH TRANSFER"); + + // The SSI3 peripheral must be enabled for use. + SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3); + + // + // For this example SSI3 is used with PortA[5:2]. The actual port and pins + // used may be different on your part, consult the data sheet for more + // information. GPIO port A needs to be enabled so these pins can be used. + // TODO: change this to whichever GPIO port you are using. + // + SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ); + SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); + SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); + + // + // GPIO Port F0 Pin is Locked. So Unlock and write the CR bit + // + HWREG(GPIO_PORTF_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY; + HWREG(GPIO_PORTF_BASE+GPIO_O_CR) |= GPIO_PIN_0; + + // + // Configure the pin muxing for SSI3 functions on port Q0, Q1, Q2, F0, + // F4, F5 + // + GPIOPinConfigure(GPIO_PQ0_SSI3CLK); + GPIOPinConfigure(GPIO_PQ1_SSI3FSS); + GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0); + GPIOPinConfigure(GPIO_PF0_SSI3XDAT1); + GPIOPinConfigure(GPIO_PF4_SSI3XDAT2); + GPIOPinConfigure(GPIO_PF5_SSI3XDAT3); + + // + // Configure the GPIO settings for the SSI pins. This function also gives + // control of these pins to the SSI hardware. Consult the data sheet to + // see which functions are allocated per pin. + // The pins are assigned as follows: + // PF5 - SSI3XDAT3 + // PF4 - SSI3XDAT2 + // PF0 - SSI3XDAT1 + // PQ2 - SSI3XDAT0 + // PQ1 - SSI3Fss + // PQ0 - SSI3CLK + // TODO: change this to select the port/pin you are using. + // + GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_2 | GPIO_PIN_1 | + GPIO_PIN_0); + GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_5 | GPIO_PIN_4 | + GPIO_PIN_0); + + // + // Configure and enable the SSI port for SPI master mode. Use SSI3, + // system clock supply, idle clock level low and active low clock in + // freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data. + // For SPI mode, you can set the polarity of the SSI clock when the SSI + // unit is idle. You can also configure what clock edge you want to + // capture data on. Please reference the datasheet for more information on + // the different SPI modes. + // + SSIConfigSetExpClk(SSI3_BASE, ui32SysClockFreq, SSI_FRF_MOTO_MODE_0, + SSI_MODE_MASTER, 1000000, 8); + + // + // Enable the SSI3 module. + // + SSIAdvModeSet(SSI3_BASE,SSI_ADV_MODE_WRITE); + SSIAdvFrameHoldEnable(SSI3_BASE); + SSIEnable(SSI3_BASE); + + // + // Read any residual data from the SSI port. This makes sure the receive + // FIFOs are empty, so we don't read any unwanted junk. This is done here + // because the SPI SSI mode is full-duplex, which allows you to send and + // receive at the same time. The SSIDataGetNonBlocking function returns + // "true" when data was returned, and "false" when no data was returned. + // The "non-blocking" function checks if there is any data in the receive + // FIFO and does not "hang" if there isn't. + // + while(SSIDataGetNonBlocking(SSI3_BASE, &pui32Dummy[0])) + { + } + + return 0; +} + +int Init_TxBuf(uint32_t NumOfWords, uint32_t* TxBuf) +{ + uint32_t ui32Index; + + for(ui32Index=0;ui32Index