diff options
| author | Shlomo Hecht <shlomo@twine-s.com> | 2018-03-06 12:09:02 +0200 |
|---|---|---|
| committer | Shlomo Hecht <shlomo@twine-s.com> | 2018-03-06 12:09:02 +0200 |
| commit | fb2d080fbbcea3a91e598b4ea8837a230de6a319 (patch) | |
| tree | 6b3ce09a252d2ebab8189a92b3326ffbba6dbe4b /Software/Embedded_SW/Embedded/Drivers/Flash_Memory | |
| parent | d734bb5cf08ba2433b74fc86a8858d2437d1a237 (diff) | |
| download | Tango-fb2d080fbbcea3a91e598b4ea8837a230de6a319.tar.gz Tango-fb2d080fbbcea3a91e598b4ea8837a230de6a319.zip | |
A new forlder for embedded software in our common structure
Diffstat (limited to 'Software/Embedded_SW/Embedded/Drivers/Flash_Memory')
| -rw-r--r-- | Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.c | 488 | ||||
| -rw-r--r-- | Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.h | 6 |
2 files changed, 494 insertions, 0 deletions
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 <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#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<NumOfWords;ui32Index++) + { + TxBuf[ui32Index] = rand()%256; + } + + return 0; +} + +int Init_RxBuf(uint32_t NumOfWords, uint32_t* RxBuf) +{ + uint32_t ui32Index; + + for(ui32Index=0;ui32Index<NumOfWords;ui32Index++) + { + RxBuf[ui32Index] = 0x0; + } + + return 0; +} + + +int Read_Ext_Flash_Device_ID() +{ + uint32_t ui32DeviceID; + + ui32DeviceID = SSILibSendReadIDAdvMode(SSI3_BASE); + if(ui32DeviceID != 0xC219) + { + writeLine("No External Flash... Read Back:"); + writeFloat(ui32DeviceID); + while(1); + } + + writeLine("External Flash Detected with Device ID:"); + writeFloat(ui32DeviceID); + + return 0; +} + +int Erase_Sector_before_writting_To_Ext_Flash() +{ + writeLine("Starting Erase Operations..."); + + SSILibSendEraseCommand(SSI3_BASE,0x0,INS_SECTOR_ERASE_4KB); + + writeLine("Erase Completed..."); + + return 0; +} + +int Write_Words_To_Ext_Flash(uint32_t NumOfWords, uint32_t* TxBuf) +{ + + uint32_t ui32Index; + + writeLine("Starting Write Operations..."); + + SSILibSendPageProgram(SSI3_BASE,0x0,INS_PAGE_PROGRAM); + + for(ui32Index=0;ui32Index<NumOfWords-1;ui32Index++) + { + SSIDataPut(SSI3_BASE,TxBuf[ui32Index]); + } + + SSIAdvDataPutFrameEnd(SSI3_BASE,TxBuf[NumOfWords-1]); + + writeLine("Write Completed..."); + + return 0; +} + +int Read_Words_From_Ext_Flash(uint32_t NumOfWords, uint32_t* RxBuf) +{ + + uint32_t ui32Index; + + writeLine("Starting Read Operations..."); + + SSILibSendReadDataAdvBi(SSI3_BASE,0x0,INS_READ_DATA); + + for(ui32Index=0;ui32Index<NumOfWords-1;ui32Index++) + { + SSIDataPut(SSI3_BASE,DUMMY_BYTE); + SSIDataGet(SSI3_BASE,&RxBuf[ui32Index]); + } + SSIAdvDataPutFrameEnd(SSI3_BASE,DUMMY_BYTE); + SSIDataGet(SSI3_BASE,&RxBuf[NumOfWords-1]); + + writeLine("Read Completed..."); + + return 0; +} + +int Display_RX_TX_Ext_Flash_Data(uint32_t NumOfWords, uint32_t* TxBuf, uint32_t* RxBuf) +{ + uint32_t ui32Index; + + for(ui32Index=0;ui32Index<NumOfWords;ui32Index++) + { + writeLine("#"); + writeFloat(ui32Index); + + if(TxBuf != NULL) + { + writeLine("Write: "); + writeFloat(TxBuf[ui32Index]); + } + + if(RxBuf != NULL) + { + writeLine("Read: "); + writeFloat(RxBuf[ui32Index]); + } + } + + return 0; +} + +//***************************************************************************** +// +// Configure SSI3 in master Freescale (SPI) mode. This example will send out +// 3 bytes of data, then wait for 3 bytes of data to come in. This will all be +// done using the polling method. +// +//***************************************************************************** +int Ext_Flash_Operation(uint32_t Operation, uint32_t NumOfWords, uint32_t* pui32DataTx, uint32_t* pui32DataRx )//main +{ + +/* uint32_t* pui32DataTx; + uint32_t* pui32DataRx; + + pui32DataTx = (uint32_t*) malloc(NumOfWords*sizeof(uint32_t)); + pui32DataRx = (uint32_t*) malloc(NumOfWords*sizeof(uint32_t));*/ + + Init_Ext_Flash(); + + // Read the DEVICE ID + Read_Ext_Flash_Device_ID(); + + if((Operation == TX) || (Operation == TXRX)) + { + // --------------------------- TX ------------------------------------------ + // Initialise the Transmit Buffer + //Init_TxBuf(NumOfWords, pui32DataTx);// with random numbers + + // Display Data + Display_RX_TX_Ext_Flash_Data(NumOfWords, pui32DataTx, NULL); + + // Erase the Sector before Program Operation... + Erase_Sector_before_writting_To_Ext_Flash(); + + // Write NUM_SSI_DATA words to the External Flash + Write_Words_To_Ext_Flash(NumOfWords, pui32DataTx); + } + + if((Operation == RX) || (Operation == TXRX)) + { + // --------------------------- RX ------------------------------------------ + + // Initialise the Receive Buffer + Init_RxBuf(NumOfWords, pui32DataRx); + + // Read NUM_SSI_DATA words from the External Flash + Read_Words_From_Ext_Flash(NumOfWords, pui32DataRx); + + if(Operation == RX) + { + // Display Data + Display_RX_TX_Ext_Flash_Data(NumOfWords, NULL, pui32DataRx); + } + else + { + // Display Data + Display_RX_TX_Ext_Flash_Data(NumOfWords, pui32DataTx, pui32DataRx); + } + + } + + return 0; +} diff --git a/Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.h b/Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.h new file mode 100644 index 000000000..3271c6abb --- /dev/null +++ b/Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.h @@ -0,0 +1,6 @@ +#ifndef FLASHMEMORY_H +#define FLASHMEMORY_H + +int Ext_Flash_Operation(); + +#endif //FLASHMEMORY_H |
