aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Embedded_SW/Embedded/Drivers/Flash_Memory
diff options
context:
space:
mode:
authorShlomo Hecht <shlomo@twine-s.com>2018-03-06 12:09:02 +0200
committerShlomo Hecht <shlomo@twine-s.com>2018-03-06 12:09:02 +0200
commitfb2d080fbbcea3a91e598b4ea8837a230de6a319 (patch)
tree6b3ce09a252d2ebab8189a92b3326ffbba6dbe4b /Software/Embedded_SW/Embedded/Drivers/Flash_Memory
parentd734bb5cf08ba2433b74fc86a8858d2437d1a237 (diff)
downloadTango-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.c488
-rw-r--r--Software/Embedded_SW/Embedded/Drivers/Flash_Memory/Flash_Memory.h6
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