void mrf_write_short(uint8_t address, uint8_t data) { mrf_select(); // 0 for top address, 1 bottom for write spi_tx((address<<1 & 0b01111110) | 0x01); spi_tx(data); mrf_deselect(); }
/*---------------------------------------------------------------------------*/ static const char * program_page(unsigned long offset, const unsigned char *p, int nbytes) { const unsigned char *end = p + nbytes; int s; wait_ready(); write_enable(); s = splhigh(); SPI_FLASH_ENABLE(); spi_tx(SPI_FLASH_INS_PP); spi_tx(offset >> 16); /* MSB */ spi_tx(offset >> 8); spi_tx(offset >> 0); /* LSB */ for(; p < end; p++) { spi_tx(~*p); } SPI_FLASH_DISABLE(); splx(s); return p; }
uint8_t mrf_read_short(uint8_t address) { mrf_select(); // 0 top for short addressing, 0 bottom for read spi_tx(address<<1 & 0b01111110); uint8_t res = spi_tx(0x0); mrf_deselect(); return res; }
/*********************************************************** * Function: * Description: * Input: * Input: * Output: * Return: * Others: ***********************************************************/ static uint8_t sst25_busy( void ) { uint8_t st; DF_CS_0; spi_tx( 0x05 ); st = spi_tx( 0xff ); DF_CS_1; return st & 0x01; }
void mrf_write_long(uint16_t address, uint8_t data) { mrf_select(); uint8_t ahigh = address >> 3; uint8_t alow = address << 5; spi_tx(0x80 | ahigh); // high bit for long spi_tx(alow | 0x10); // last bit for write spi_tx(data); mrf_deselect(); }
uint8_t mrf_read_long(uint16_t address) { mrf_select(); uint8_t ahigh = address >> 3; uint8_t alow = address << 5; spi_tx(0x80 | ahigh); // high bit for long spi_tx(alow); uint8_t res = spi_tx(0); mrf_deselect(); return res; }
// Reads the JEDEC ID. static uint32_t read_device_id() { start_command(COMMAND_JEDEC_ID); uint32_t id = 0; char* id_bytes = reinterpret_cast<char*>(&id); id_bytes[2] = spi_tx(0); id_bytes[1] = spi_tx(0); id_bytes[0] = spi_tx(0); end_command(); return id; }
/*---------------------------------------------------------------------------*/ int xmem_pread(void *_p, int size, unsigned long offset) { unsigned char *p = _p; const unsigned char *end = p + size; int s; wait_ready(); ENERGEST_ON(ENERGEST_TYPE_FLASH_READ); s = splhigh(); SPI_FLASH_ENABLE(); spi_tx(SPI_FLASH_INS_READ); spi_tx(offset >> 16); /* MSB */ spi_tx(offset >> 8); spi_tx(offset >> 0); /* LSB */ FASTSPI_CLEAR_RX(); for(; p < end; p++) { unsigned char u; FASTSPI_RX(u); *p = ~u; } SPI_FLASH_DISABLE(); splx(s); ENERGEST_OFF(ENERGEST_TYPE_FLASH_READ); return size; }
// Read status reg. static uint8_t read_status_reg() { start_command(COMMAND_READ_STATUS); uint8_t value = spi_tx(0); end_command(); return value; }
uint8 spi_aux_write(spi_dev *spi_device, const uint8 *data, uint32 length) { uint32 txed = 0; while (txed < length) { uint32 ret = spi_tx(spi_device, data + txed, length - txed); if(ret == -1) return 1; txed += ret; } return 0; }
void sst25_write_back( uint32_t addr, uint8_t *p, uint16_t len ) { uint32_t i, wr_addr; uint16_t offset; uint8_t *pbuf; /*找到当前地址对应的4k=0x1000边界*/ wr_addr = addr & 0xFFFFF000; /*对齐到4k边界*/ offset = addr & 0xfff; /*4k内偏移*/ sst25_read( wr_addr, buf, 4096 ); /*读出数据*/ sst25_erase_4k( wr_addr ); /*清除扇区*/ memcpy( buf + offset, p, len ); pbuf = buf; DF_CS_0; spi_tx( SST25_WREN ); DF_CS_1; DF_CS_0; spi_tx( SST25_AAI ); /**/ spi_tx( wr_addr >> 16 ); spi_tx( wr_addr >> 8 ); spi_tx( wr_addr & 0xff ); spi_tx( *pbuf++ ); spi_tx( *pbuf++ ); DF_CS_1; while( sst25_busy( ) ) { ; } for( i = 0; i < 4094; i += 2 ) { DF_CS_0; spi_tx( SST25_AAI ); /**/ spi_tx( *pbuf++ ); spi_tx( *pbuf++ ); DF_CS_1; while( sst25_busy( ) ) { ; } } DF_CS_0; spi_tx( SST25_WRDI ); //WRDI用于退出AAI写模式 所谓AAI 就是地址自动加 DF_CS_1; }
/************************************************************************************************** * @fn npSpiRxIsr * * @brief This function handles the DMA Rx complete interrupt. * * input parameters * * None. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void npSpiRxIsr(void) { uint8 *pBuf; mtRpcCmdType_t type = (mtRpcCmdType_t)(npSpiBuf[1] & MT_RPC_CMD_TYPE_MASK); NP_SPI_ASSERT(npSpiState == NP_SPI_WAIT_RX); switch (type) { case MT_RPC_CMD_POLL: npSpiState = NP_SPI_WAIT_TX; if ((pBuf = npSpiPollCallback()) != NULL) { /* Send TX packet using uDMA */ spi_tx(pBuf); osal_msg_deallocate((uint8 *)pBuf); } else { /* If there is no data in the queue, send 3 zeros. */ pBuf = npSpiBuf; npSpiBuf[0] = npSpiBuf[1] = npSpiBuf[2] = 0; /* Send TX packet using uDMA */ spi_tx(pBuf); } break; case MT_RPC_CMD_SREQ: npSpiState = NP_SPI_WAIT_SREQ; osal_set_event(znpTaskId, ZNP_SPI_RX_SREQ_EVENT); break; case MT_RPC_CMD_AREQ: npSpiState = NP_SPI_WAIT_AREQ; osal_set_event(znpTaskId, ZNP_SPI_RX_AREQ_EVENT); break; default: npSpiState = NP_SPI_IDLE; break; } }
/*搽除一个扇区,不需要连续删除*/ void sst25_erase_4k( uint32_t addr ) { while( sst25_busy( ) ) { ; } DF_CS_0; spi_tx( SST25_WREN ); DF_CS_1; DF_CS_0; spi_tx( SectorErace_4KB ); spi_tx( ( addr & 0xffFFFF ) >> 16 ); spi_tx( ( addr & 0xffFF ) >> 8 ); spi_tx( addr & 0xFF ); DF_CS_1; while( sst25_busy( ) ) { ; } }
/*********************************************************** * Function: * Description: * Input: * Input: * Output: * Return: * Others: ***********************************************************/ void sst25_read( uint32_t addr, uint8_t *p, uint16_t len ) { uint8_t *pdata = p; uint32_t readaddr = addr; while( sst25_busy( ) ) { ; } DF_CS_0; spi_tx( SST25_READ ); spi_tx( ( readaddr & 0xFF0000 ) >> 16 ); spi_tx( ( readaddr & 0xFF00 ) >> 8 ); spi_tx( readaddr & 0xFF ); while( len-- ) { *pdata = spi_tx( 0xA5 ); pdata++; } DF_CS_1; }
/*********************************************************** * Function: * Description: * Input: * Input: * Output: * Return: * Others: ***********************************************************/ static void sst25_bytewrite( uint32_t addr, uint8_t data ) { volatile uint8_t st; DF_CS_0; spi_tx( SST25_WREN ); DF_CS_1; delay(3); DF_CS_0; spi_tx( SST25_BP ); spi_tx( ( addr & 0xffffff ) >> 16 ); spi_tx( ( addr & 0xff00 ) >> 8 ); spi_tx( addr & 0xff ); spi_tx( data ); DF_CS_1; while( sst25_busy( ) ) { ; } #if 0 DF_CS_0; spi_tx( SST25_RDSR ); do { st = spi_tx( 0xA5 ); } while( st & 0x01 ); DF_CS_1; #endif }
/*---------------------------------------------------------------------------*/ static void write_enable(void) { int s; s = splhigh(); SPI_FLASH_ENABLE(); spi_tx(SPI_FLASH_INS_WREN); SPI_FLASH_DISABLE(); splx(s); }
// Read data. static void read_data(uint32_t offset, char* buf, uint32_t size) { start_command(COMMAND_READ_DATA); write_address(offset); // The file data bit order is reversed. spi_set_bit_order(SPI_LSB_FIRST); for (; size > 0; --size, ++buf) { *buf = spi_tx(0); } spi_set_bit_order(SPI_MSB_FIRST); end_command(); }
// Programs a page of data. static void page_program(uint32_t offset, const char* buf, uint16_t size) { start_command(COMMAND_PAGE_PROGRAM); write_address(offset); if (size > PAGE_SIZE) { size = PAGE_SIZE; } // The file data bit order is reversed. spi_set_bit_order(SPI_LSB_FIRST); for (; size > 0; --size, ++buf) { spi_tx(*buf); } spi_set_bit_order(SPI_MSB_FIRST); end_command(); }
int main() { led_on(); usart_init(); debugln("\nUSART initialized"); spi_init_master(); debugln("SPI master"); for(int i=0; i<5; i++) { debugx(spi_tx(42)); debugln(" spi_tx"); } for (;;){} return 1; }
/*********************************************************** * Function: * Description: * Input: * Input: * Output: * Return: * Others: ***********************************************************/ static uint8_t sst25_info( void ) { //uint8_t n; DF_CS_0; spi_tx( 0x90 ); spi_tx( 0x00 ); spi_tx( 0x00 ); spi_tx( 0x00 ); mem_ID = spi_tx( 0xff )<<8; mem_ID |= spi_tx( 0xff ); DF_CS_1; //rt_kprintf("\n MEM_ID=%04X",mem_ID); }
/************************************************************************************************** * @fn npSpiSRspReady * * @brief This function is called by MT to notify SPI driver that an SRSP is ready to Tx. * * input parameters * * @param pBuf - Pointer to the buffer to transmit on the SPI. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void npSpiSRspReady(uint8 *pBuf) { halIntState_t intState; HAL_ENTER_CRITICAL_SECTION_DEBUG(intState); if ((npSpiState == NP_SPI_WAIT_SREQ) && (GPIOPinRead(HAL_SPI_SRDY_BASE, HAL_SPI_SRDY_PIN) == 0)) { npSpiState = NP_SPI_WAIT_TX; /* Send TX packet using uDMA */ spi_tx(pBuf); HAL_EXIT_CRITICAL_SECTION_DEBUG(intState); osal_msg_deallocate((uint8 *)pBuf); } else { HAL_EXIT_CRITICAL_SECTION_DEBUG(intState); } }
/* * Erase 64k bytes of data. It takes about 1s before WIP goes low! */ static void erase_sector(unsigned long offset) { int s; wait_ready(); write_enable(); s = splhigh(); SPI_FLASH_ENABLE(); spi_tx(SPI_FLASH_INS_SE); spi_tx(offset >> 16); /* MSB */ spi_tx(offset >> 8); spi_tx(offset >> 0); /* LSB */ SPI_FLASH_DISABLE(); splx(s); }
/*---------------------------------------------------------------------------*/ static unsigned read_status_register(void) { unsigned char u; int s; s = splhigh(); SPI_FLASH_ENABLE(); spi_tx(SPI_FLASH_INS_RDSR); FASTSPI_CLEAR_RX(); FASTSPI_RX(u); SPI_FLASH_DISABLE(); splx(s); return u; }
int spi_isr(spi_p t) { int st; spir_p reg; spi_xfr_p bp; register int actual, count, rem, inc; reg = t->r; st = io_rd32(reg->sta); #if 0 st &= io_rd32(reg->ier); if (!st) #else if (!(st & io_rd32(reg->ier))) #endif { dbg("spi: isr err - no source\n"); return 0; } //dbg("isr=%X\n", st); io_wr32(reg->sta, st); /* errors */ if (st & (SPI_INT_WOVR | SPI_INT_WUNR | SPI_INT_FOVR)) { dbg("spi: isr err - %X\n", st); t->evt(t->ctx, SPI_EVT_ERR); } /* data xfer */ bp = t->bp; if (!bp) { dbg("spi: isr err - no buf, %X\n", st); return 0; } inc = t->inc; actual = bp->actual; rem = bp->len - actual; if (st & SPI_INT_TEMT) { /* use transmitter empty to minimize io & irq for all cases except slave rx-only */ int size; size = t->fifosize << inc; count = MIN(size, rem); rem -= count; if (bp->rx) { spi_rx(®->rx, bp->rx + actual, count, inc); } actual += count; bp->actual = actual; if (!rem) { io_wr32(reg->ier, 0); io_wr32(reg->op, io_rd32(reg->op) & ~SPI_OP_EN); io_wr32(reg->ctl, 0); #ifndef SPI_AUTOCS if (bp->csflag & SPI_XFR_NCS) { io_wr32(reg->master, io_rd32(reg->master) & ~SPI_MST_FSS); } #endif t->bp = 0; //ddump("spi: rx - ", bp->rx, bp->len); //dbg("spi: isr info - done, %X %X\n", st, io_rd32(reg->sta)); t->evt(t->ctx, SPI_EVT_DONE); } else { count = MIN(size, rem); rem = count >>= t->inc; #ifdef SPI_AUTOCS if (t->master && !t->burst) { /* assert chip select for rest of xfer */ io_wr32(reg->op, (io_rd32(reg->op) & ~SPI_OP_BURST(16)) | SPI_OP_BURST(rem)); } #endif if (bp->tx) { spi_tx(®->tx, bp->tx + actual, count, inc); } else { while (rem--) { io_wr32(reg->tx, 0); } } } }
// Sends a 24-bit address over the SPI. static void write_address(uint32_t address) { const char* address_bytes = reinterpret_cast<const char*>(&address); spi_tx(address_bytes[2]); spi_tx(address_bytes[1]); spi_tx(address_bytes[0]); }
// Starts a command operation. static void start_command(uint8_t command) { flash_spi_select(); spi_tx(command); }
void sst25_write_through( uint32_t addr, uint8_t *p, uint16_t len ) { volatile uint8_t st = 0; uint32_t wr_addr; uint8_t *pdata = p; uint16_t remain = len; uint32_t delay_counter; wr_addr = addr; while( sst25_busy( ) ) { ; } if(mem_ID == 0xBF4A) ///存储设备为sst25 { /*AAI方式写,要判读地址的奇偶*/ if( len == 1 ) { sst25_bytewrite( wr_addr, *pdata ); return; } if( wr_addr & 0x01 ) /*AAI需要从A0=0开始*/ { sst25_bytewrite( wr_addr++, *pdata++ ); remain--; } DF_CS_0; spi_tx( SST25_WREN ); DF_CS_1; delay(3); DF_CS_0; spi_tx( SST25_AAI ); /**/ spi_tx( wr_addr >> 16 ); spi_tx( wr_addr >> 8 ); spi_tx( wr_addr & 0xff ); spi_tx( *pdata++ ); spi_tx( *pdata++ ); DF_CS_1; while( sst25_busy( ) ) { ; //判忙 } remain -= 2; while( remain > 1 ) { DF_CS_0; spi_tx( SST25_AAI ); /**/ spi_tx( *pdata++ ); spi_tx( *pdata++ ); DF_CS_1; while( sst25_busy( ) ) { ; //判忙 } remain -= 2; } DF_CS_0; spi_tx( SST25_WRDI ); //WRDI用于退出AAI写模式 所谓AAI 就是地址自动加 DF_CS_1; if( remain ) { sst25_bytewrite( wr_addr + len - 1, *pdata ); } } else {
void sst25_write_through( uint32_t addr, uint8_t *p, uint16_t len ) { volatile uint8_t st = 0; uint32_t wr_addr; uint8_t *pdata = p; uint16_t remain = len; wr_addr = addr; while( sst25_busy( ) ) { ; } /*字节写的方式*/ #if 0 while( remain-- ) { sst25_bytewrite( wr_addr, *pdata++ ); wr_addr++; } #else /*AAI方式写,要判读地址的奇偶*/ if( len == 1 ) { sst25_bytewrite( wr_addr, *pdata ); return; } if( wr_addr & 0x01 ) /*AAI需要从A0=0开始*/ { sst25_bytewrite( wr_addr++, *pdata++ ); remain--; } DF_CS_0; spi_tx( SST25_WREN ); DF_CS_1; DF_CS_0; spi_tx( SST25_AAI ); /**/ spi_tx( wr_addr >> 16 ); spi_tx( wr_addr >> 8 ); spi_tx( wr_addr & 0xff ); spi_tx( *pdata++ ); spi_tx( *pdata++ ); DF_CS_1; while( sst25_busy( ) ) { ; //判忙 } remain -= 2; while( remain > 1 ) { DF_CS_0; spi_tx( SST25_AAI ); /**/ spi_tx( *pdata++ ); spi_tx( *pdata++ ); DF_CS_1; while( sst25_busy( ) ) { ; //判忙 } remain -= 2; } DF_CS_0; spi_tx( SST25_WRDI ); //WRDI用于退出AAI写模式 所谓AAI 就是地址自动加 DF_CS_1; if( remain ) { sst25_bytewrite( wr_addr + len - 1, *pdata ); } #endif }
/*********************************************************** * Function: * Description: * Input: * Input: * Output: * Return: * Others: ***********************************************************/ void sst25_init( void ) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; uint32_t delay_counter; /* Enable DF_SPI Periph clock */ RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB, ENABLE ); RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE ); GPIO_PinAFConfig( GPIOB, GPIO_PinSource13, GPIO_AF_SPI2 ); GPIO_PinAFConfig( GPIOB, GPIO_PinSource14, GPIO_AF_SPI2 ); GPIO_PinAFConfig( GPIOB, GPIO_PinSource15, GPIO_AF_SPI2 ); RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOD, ENABLE ); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; /*!< SPI SCK pin configuration */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_Init( GPIOB, &GPIO_InitStructure ); /*!< SPI MOSI pin configuration */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_Init( GPIOB, &GPIO_InitStructure ); /*!< SPI MISO pin configuration */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; GPIO_Init( GPIOB, &GPIO_InitStructure ); //------- CS _pin GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init( GPIOD, &GPIO_InitStructure ); //PA4 pin: CS SD_CARD GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init( GPIOA, &GPIO_InitStructure ); GPIO_SetBits(GPIOA,GPIO_Pin_4); //------- WP _pin GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init( GPIOD, &GPIO_InitStructure ); /*------------------------ DF_SPI configuration ------------------------*/ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //SPI_Direction_1Line_Tx; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; /* 42M/4=10.5M */ SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; //SPI1->CR2=0x04; //NSS ---SSOE // SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //MSTR SPI_I2S_DeInit( SPI2 ); SPI_Init( SPI2, &SPI_InitStructure ); /* Enable SPI_MASTER */ SPI_Cmd( SPI2, ENABLE ); SPI_CalculateCRC( SPI2, DISABLE ); DF_CS_1; DF_WP_0; DF_CS_0; spi_tx( 0x50 ); DF_CS_1; delay(3); DF_CS_0; spi_tx( 0x01 ); spi_tx( 0x00 ); DF_CS_1; //delay(3); //DF_CS_0; //spi_tx( DBSY ); //DF_CS_1; sst25_info( ); //rt_sem_init( &sem_dataflash, "sem_df", 0, RT_IPC_FLAG_FIFO ); //rt_sem_release( &sem_dataflash ); }