/** * @brief Erase whole SPI flash memory. * @param spi is the base address of SPI module. * @return None. * @note Before calling this function, the transaction length (data width) must be configured as 8 bits. */ void SpiFlash_ChipErase(SPI_T *spi) { /* /CS: active */ SPI_SET_SS_LOW(spi); /* Send command 0x06: Write enable */ SPI_WRITE_TX0(spi, 0x06); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* /CS: inactive */ SPI_SET_SS_HIGH(spi); __NOP(); /* /CS: active */ SPI_SET_SS_LOW(spi); /* Send command 0xC7: Chip erase */ SPI_WRITE_TX0(spi, 0xC7); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* /CS: inactive */ SPI_SET_SS_HIGH(spi); }
/** * @brief Read SPI flash memory. * @param spi is the base address of SPI module. * @param u32StartAddress is the start address. * @param au8DataBuffer is the pointer of destination buffer. * @param u32ByteCount is the total data count. * @return None. * @note Before calling this function, the transaction length (data width) must be configured as 8 bits. */ void SpiFlash_ReadData(SPI_T *spi, uint32_t u32StartAddress, uint8_t *au8DataBuffer, uint32_t u32ByteCount) { uint32_t u32RxCounter; /* /CS: active */ SPI_SET_SS_LOW(spi); /* Send command 0x03: Read data */ SPI_WRITE_TX0(spi, 0x03); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Send 24-bit start address */ /* Send the first 8 address bits */ SPI_WRITE_TX0(spi, (u32StartAddress >> 16) & 0xFF); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Send the second 8 address bits */ SPI_WRITE_TX0(spi, (u32StartAddress >> 8) & 0xFF); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Send the third 8 address bits */ SPI_WRITE_TX0(spi, u32StartAddress & 0xFF); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Reset RX data counter */ u32RxCounter = 0; while(u32RxCounter < u32ByteCount) { /* Send SPI bus clock to get data from SPI flash */ SPI_WRITE_TX0(spi, 0x00); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Read data */ au8DataBuffer[u32RxCounter++] = SPI_READ_RX0(spi); } /* /CS: inactive */ SPI_SET_SS_HIGH(spi); }
void ConfigHWSpiport(void) { // plese ensure has opened the system clock of SPI1 mode. CLK_EnableModuleClock(SPI1_MODULE); //1st . config pin MFP function /*---------------------------------------------------------------------------------------------------------*/ /* Init I/O Multi-function */ /*---------------------------------------------------------------------------------------------------------*/ /* SPI1: PC15=MOSI0, PD0=MISO0, PD1=CLK */ //note :there is a qustion that for the Register option must be "OR" bits. //othewith, will occured changed other Hardwave bits. SYS->GPC_MFPH |= (SYS_GPC_MFPH_PC15MFP_SPI1_MOSI0); SYS->GPD_MFPL |= (SYS_GPD_MFPL_PD0MFP_SPI1_MISO0 | SYS_GPD_MFPL_PD1MFP_SPI1_CLK); //2st . config the SPI1 of Hardwave Port /* Configure SPI1 as a master, MSB first, 8-bit transaction, SPI Mode-0 timing, clock is 400KHz */ SPI_Open(SPI1, SPI_MASTER, SPI_MODE_0, 8, 400000); //open SPI1 and config it. SPI_DisableAutoSS(SPI1);//closed the ss by hardwave and give it for softwave ctrl that well used ctrl SS/HSA pin select ADE7878 into the SPI mode. SPI_TRIGGER(SPI1);//start SPI1 transf. //3st . config the SS/HSA pin GPIO_SetMode(PC, BIT12, GPIO_MODE_OUTPUT);// SP1 SS pin by SOFTWAVE ctrl PC12=1;// hold the pin hight.. //2016 01 03 make by wangjunwei in bittel. }
void SPIClass::begin() { if(init_flag==0) init(); /* Unlock protected registers */ SYS_UnlockReg(); /* Enable IP clock */ CLK_EnableModuleClock(module); /* Select IP clock source and clock divider */ CLK_SetModuleClock(module,clksel,0); /* Lock protected registers */ SYS_LockReg(); /* Configure as a master, clock idle low, falling clock edge Tx, rising edge Rx and 8-bit transaction */ /* Set IP clock divider. SPI clock rate = 4MHz */ SPI_Open(spi, SPI_MASTER, SPI_MODE_0, 8, 4000000); #if defined(__NUC240__) | defined(__NANO100__) | defined(__NUC131__) SPI_EnableFIFO(spi,12,12); #endif setBitOrder(SS, MSBFIRST); #if defined(__M451__) SPI_ClearRxFIFO(spi); SPI_TRIGGER(spi); #endif }
/** * @brief Write SPI flash status register. * @param spi is the base address of SPI module. * @param u32Value is the value attempt to write to status register. * @return None. * @note Before calling this function, the transaction length (data width) must be configured as 8 bits. */ void SpiFlash_WriteStatusReg(SPI_T *spi, uint32_t u32Value) { /* /CS: active */ SPI_SET_SS_LOW(spi); /* Send command 0x06: Write enable */ SPI_WRITE_TX0(spi, 0x06); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* /CS: inactive */ SPI_SET_SS_HIGH(spi); __NOP(); /* /CS: active */ SPI_SET_SS_LOW(spi); /* Send command 0x01: Write status register */ SPI_WRITE_TX0(spi, 0x01); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* write to status register 1 */ SPI_WRITE_TX0(spi, u32Value & 0xFF); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* write to status register 2 */ SPI_WRITE_TX0(spi, (u32Value >> 8) & 0xFF); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* /CS: inactive */ SPI_SET_SS_HIGH(spi); }
void SPIClass::beginTransaction(uint8_t pin, SPISettings settings) { if(init_flag==0);// init(); /* Configure as a master, clock idle low, falling clock edge Tx, rising edge Rx and 8-bit transaction */ /* Set IP clock divider. SPI clock rate = 4MHz */ SPI_Open(spi, SPI_MASTER, settings.datmode, 8, settings.clock); //SPI_EnableFIFO(spi,12,12); setBitOrder(SS, settings.border); //#if defined(__M451__) | defined(__NANO100__) SPI_ClearRxFIFO(spi); SPI_TRIGGER(spi); //#endif }
/** * @brief Read SPI flash manufacturer ID and device ID. * @param spi is the base address of SPI module. * @return High byte is manufacturer ID; low byte is device ID. * @note Before calling this function, the transaction length (data width) must be configured as 8 bits. */ uint32_t SpiFlash_ReadMidDid(SPI_T *spi) { uint32_t u32MID_DID; /* /CS: active */ SPI_SET_SS_LOW(spi); /* Send command 0x90: Read Manufacturer/Device ID */ SPI_WRITE_TX0(spi, 0x90); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Send total 24 '0' dummy bits */ /* Send the first 8 dummy bits */ SPI_WRITE_TX0(spi, 0x00); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Send the second 8 dummy bits */ SPI_WRITE_TX0(spi, 0x00); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Send the third 8 dummy bits */ SPI_WRITE_TX0(spi, 0x00); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Send SPI bus clock to get the Manufacturer ID */ SPI_WRITE_TX0(spi, 0x00); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Get the Manufacturer ID */ u32MID_DID = spi->RX0 << 8; /* Send SPI bus clock to get the Device ID */ SPI_WRITE_TX0(spi, 0x00); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Get the Device ID */ u32MID_DID |= spi->RX0; /* /CS: inactive */ SPI_SET_SS_HIGH(spi); return u32MID_DID; }
/** * @brief Read SPI flash status register. * @param spi is the base address of SPI module. * @return Status register value. * @note Before calling this function, the transaction length (data width) must be configured as 8 bits. */ uint32_t SpiFlash_ReadStatusReg(SPI_T *spi) { /* /CS: active */ SPI_SET_SS_LOW(spi); /* Send command 0x05: Read status register */ SPI_WRITE_TX0(spi, 0x05); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Send SPI bus clock to read status register */ SPI_WRITE_TX0(spi, 0x00); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* /CS: inactive */ SPI_SET_SS_HIGH(spi); /* Return the status register value */ return (spi->RX0); }
int spi_write_packet(SPI_T *spi, uint8_t *data, int len) { int timeout, i; for(i=0; len != 0; i++, len--) { SPI_WRITE_TX0(spi, data[i]); SPI_TRIGGER(spi); timeout = SPI_TIMEOUT; while(SPI_IS_BUSY(spi)) { if(!timeout--) { return(-1); } } } return(0); }
int spi_read_packet(SPI_T *spi, uint8_t *data, int len) { int timeout, i; for(i=0; len != 0; i++, len--) { timeout = SPI_TIMEOUT; SPI_WRITE_TX0(spi, 0); SPI_TRIGGER(spi); while(SPI_IS_BUSY(spi)) { if(!timeout--) { printf("spi_read_packet timeout (len = %d)\n",len); return(-1); } } data[i] = SPI_READ_RX0(spi); } return(0); }
/** * @brief Perform SPI flash page program. * @param spi is the base address of SPI module. * @param u32StartAddress is the start address. * @param au8DataBuffer is the pointer of source data. * @param u32ByteCount is the total data count. The maximum number is 256. * @return None. * @note Before calling this function, the transaction length (data width) must be configured as 8 bits. */ void SpiFlash_PageProgram(SPI_T *spi, uint32_t u32StartAddress, uint8_t *au8DataBuffer, uint32_t u32ByteCount) { uint32_t u32Counter; /* /CS: active */ SPI_SET_SS_LOW(spi); /* Send command 0x06: Write enable */ SPI_WRITE_TX0(spi, 0x06); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* /CS: inactive */ SPI_SET_SS_HIGH(spi); __NOP(); /* /CS: active */ SPI_SET_SS_LOW(spi); /* Send command 0x02: Page program */ SPI_WRITE_TX0(spi, 0x02); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Send 24-bit start address */ /* Send the first 8 address bits */ SPI_WRITE_TX0(spi, (u32StartAddress >> 16) & 0xFF); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Send the second 8 address bits */ SPI_WRITE_TX0(spi, (u32StartAddress >> 8) & 0xFF); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Send the third 8 address bits */ SPI_WRITE_TX0(spi, u32StartAddress & 0xFF); /* Trigger SPI transfer */ SPI_TRIGGER(spi); /* Check busy state */ while(SPI_IS_BUSY(spi)); u32Counter = 0; while(u32Counter < u32ByteCount) { /* Check busy state */ while(SPI_IS_BUSY(spi)); /* Write one byte to SPI flash */ SPI_WRITE_TX0(spi, au8DataBuffer[u32Counter++]); /* Trigger SPI transfer */ SPI_TRIGGER(spi); } /* Check busy state */ while(SPI_IS_BUSY(spi)); /* /CS: inactive */ SPI_SET_SS_HIGH(spi); }
/* Main */ int main(void) { uint32_t u32ByteCount, u32FlashAddress, u32PageNumber; uint32_t nError = 0; uint16_t u16ID; /* Init System, IP clock and multi-function I/O */ SYS_Init(); /* Init UART to 115200-8n1 for print message */ UART_Open(UART0, 115200); /* Configure SPI_FLASH_PORT as a master, MSB first, 8-bit transaction, SPI Mode-0 timing, clock is 2MHz */ SPI_Open(SPI_FLASH_PORT, SPI_MASTER, SPI_MODE_0, 8, 2000000); /* Enable the automatic hardware slave select function. Select the SS0 pin and configure as low-active. */ SPI_EnableAutoSS(SPI_FLASH_PORT, SPI_SS0, SPI_SS_ACTIVE_LOW); SPI_TRIGGER(SPI_FLASH_PORT); printf("\n+------------------------------------------------------------------------+\n"); printf("| NUC472/NUC442 SPI Dual Mode with Flash Sample Code |\n"); printf("+------------------------------------------------------------------------+\n"); /* Wait ready */ SpiFlash_WaitReady(); if((u16ID = SpiFlash_ReadMidDid()) != 0x1C14) { printf("Wrong ID, 0x%x\n", u16ID); return -1; } else printf("Flash found: EN25QH16 ...\n"); printf("Erase chip ..."); /* Erase SPI flash */ SpiFlash_ChipErase(); /* Wait ready */ SpiFlash_WaitReady(); printf("[OK]\n"); /* init source data buffer */ for(u32ByteCount=0; u32ByteCount<TEST_LENGTH; u32ByteCount++) { SrcArray[u32ByteCount] = u32ByteCount; } printf("Start to normal write data to Flash ..."); /* Program SPI flash */ u32FlashAddress = 0; for(u32PageNumber=0; u32PageNumber<TEST_NUMBER; u32PageNumber++) { /* page program */ SpiFlash_NormalPageProgram(u32FlashAddress, SrcArray); SpiFlash_WaitReady(); u32FlashAddress += 0x100; } printf("[OK]\n"); /* clear destination data buffer */ for(u32ByteCount=0; u32ByteCount<TEST_LENGTH; u32ByteCount++) { DestArray[u32ByteCount] = 0; } printf("Dual Read & Compare ..."); /* Read SPI flash */ u32FlashAddress = 0; for(u32PageNumber=0; u32PageNumber<TEST_NUMBER; u32PageNumber++) { /* page read */ SpiFlash_DualFastRead(u32FlashAddress, DestArray); u32FlashAddress += 0x100; for(u32ByteCount=0; u32ByteCount<TEST_LENGTH; u32ByteCount++) { if(DestArray[u32ByteCount] != SrcArray[u32ByteCount]) nError ++; } } if(nError == 0) printf("[OK]\n"); else printf("[FAIL]\n"); while(1); }
int main(void) { uint32_t u32DataCount, u32TestCount, u32Err; /* Init System, IP clock and multi-function I/O */ SYS_Init(); /* Init UART to 115200-8n1 for print message */ UART_Open(UART0, 115200); /* Configure SPI0 as a master, MSB first, 32-bit transaction, SPI Mode-0 timing, clock is 2MHz */ SPI_Open(SPI0, SPI_MASTER, SPI_MODE_0, 32, 2000000); /* Enable the automatic hardware slave select function. Select the SPI0_SS0 pin and configure as low-active. */ SPI_EnableAutoSS(SPI0, SPI_SS0, SPI_SS_ACTIVE_LOW); /* Configure SPI1 as a slave, MSB first, 32-bit transaction, SPI Mode-0 timing, clock is 4Mhz */ SPI_Open(SPI1, SPI_SLAVE, SPI_MODE_0, 32, 4000000); /* Configure SPI1 as a low level active device. */ SPI_SET_SS0_LOW(SPI1); printf("\n\n"); printf("+----------------------------------------------------------------------+\n"); printf("| SPI Driver Sample Code |\n"); printf("+----------------------------------------------------------------------+\n"); printf("\n"); printf("Configure SPI0 as a master and SPI1 as a slave.\n"); printf("Data width of a transaction: 32\n"); printf("SPI clock rate: %d Hz\n", SPI_GetBusClock(SPI0)); printf("The I/O connection for SPI0/SPI1 loopback:\n"); printf(" SPI0_SS (PE.4) <--> SPI1_SS(PC.12)\n SPI0_CLK(PE.5) <--> SPI1_CLK(PD.1)\n"); printf(" SPI0_MISO(PE.2) <--> SPI1_MISO(PD.0)\n SPI0_MOSI(PE.3) <--> SPI1_MOSI(PC.15)\n\n"); printf("Please connect SPI0 with SPI1, and press any key to start transmission ..."); getchar(); printf("\n"); printf("\nSPI0/1 Loopback test "); /* Enable the SPI1 unit transfer interrupt. */ SPI_EnableInt(SPI1, SPI_UNITIEN_MASK); NVIC_EnableIRQ(SPI1_IRQn); SPI_TRIGGER(SPI1); u32Err = 0; for(u32TestCount=0; u32TestCount<10000; u32TestCount++) { /* set the source data and clear the destination buffer */ for(u32DataCount=0; u32DataCount<TEST_COUNT; u32DataCount++) { g_au32SourceData[u32DataCount] = u32DataCount; g_au32DestinationData[u32DataCount] = 0; } u32DataCount=0; SPI1_INT_Flag = 0; if((u32TestCount&0x1FF) == 0) { putchar('.'); } SPI_TRIGGER(SPI0); /* write the first data of source buffer to Tx register of SPI0. And start transmission. */ SPI_WRITE_TX(SPI0, g_au32SourceData[0]); while(1) { if(SPI1_INT_Flag==1) { SPI1_INT_Flag = 0; if(u32DataCount<(TEST_COUNT-1)) { /* Read the previous retrieved data and trigger next transfer. */ g_au32DestinationData[u32DataCount] = SPI_READ_RX(SPI1); u32DataCount++; /* Write data to SPI0 Tx buffer and trigger the transfer */ SPI_WRITE_TX(SPI0, g_au32SourceData[u32DataCount]); } else { /* Just read the previous retrieved data but trigger next transfer, because this is the last transfer. */ g_au32DestinationData[u32DataCount] = SPI_READ_RX(SPI1); break; } } } /* Check the received data */ for(u32DataCount=0; u32DataCount<TEST_COUNT; u32DataCount++) { if(g_au32DestinationData[u32DataCount]!=g_au32SourceData[u32DataCount]) u32Err = 1; } if(u32Err) break; } /* Disable the SPI1 unit transfer interrupt. */ SPI_DisableInt(SPI1, SPI_UNITIEN_MASK); NVIC_DisableIRQ(SPI1_IRQn); if(u32Err) printf(" [FAIL]\n\n"); else printf(" [PASS]\n\n"); printf("\n\nExit SPI driver sample code.\n"); while(1); }