u8 send_cmd(u8 c, u32 a) { u8 i, r; // enable SD card // CS low SELECT(); // send a comand packet (6 bytes) xmit_spi(c | 0x40); // send command xmit_spi(a>>24); // msb of the address xmit_spi(a>>16); xmit_spi(a>>8); xmit_spi(a); // lsb xmit_spi(0x95); // send CMD0 CRC // now wait for a response, allow for up to 8 bytes delay for(i=0; i<8; i++) { r = rcvr_spi(); if (r != 0xFF) break; } return (r); // NOTE CS is still low! }
int main( void ) { char cmd_buf[10]; unsigned short data = 0; prvSetupHardware(); for( ;; ) { blinky(2); INFO(welcome); UARTgets(UART0_BASE,cmd_buf, 10); SELECT(); // wait_ready(); data=recv_command(MSR); INFO("reg MSR: %X", data); data=recv_command(LSR); INFO("reg LSR: %X", data); data = xmit_spi( LCR); // write to LCR INFO("reg LCR: %X", data); data = xmit_spi( 0x83); // write to LCR INFO("data: %X", data); // for(size_t i = 0; i < 10; ++i) { // spi_uart_send(UART4_SSI_BASE,"ABDC",4); // } DESELECT(); } return 0; }
void ram_bulk_erase(void) { RAM_PORT &= ~(1<<RAM_CS); // assert cs xmit_spi(RAM_WREN); // write enable instruction RAM_PORT |= (1<<RAM_CS); // deassert cs _delay_us(1); RAM_PORT &= ~(1<<RAM_CS); // assert cs xmit_spi(RAM_BE); // bulk erase instruction RAM_PORT |= (1<<RAM_CS); // deassert cs while (read_ram_status()) ; }
// write to the RAM status byte. 0 in bottom bit position = ready void write_ram_status(uint8_t status) { RAM_PORT &= ~(1<<RAM_CS); // assert cs xmit_spi(RAM_WREN); // write enable instruction RAM_PORT |= (1<<RAM_CS); // deassert cs _delay_us(2); RAM_PORT &= ~(1<<RAM_CS); // assert cs xmit_spi(RAM_WRSR); xmit_spi(status); RAM_PORT |= 1<<RAM_CS; // deassert cs _delay_us(2); while (read_ram_status() & 0x01) ; }
void nrf_read_pkt_crc(int len, uint8_t* data, uint8_t* crc){ CS_LOW(); xmit_spi(C_R_RX_PAYLOAD); sspReceive(0,data,len); sspReceive(0,crc,2); CS_HIGH(); };
char nrf_snd_pkt_crc_encr(int size, uint8_t * pkt, uint32_t const key[4]){ if(size > MAX_PKT) size=MAX_PKT; nrf_write_reg(R_CONFIG, R_CONFIG_PWR_UP| // Power on R_CONFIG_EN_CRC // CRC on, single byte ); // nrf_write_long(C_W_TX_PAYLOAD,size,pkt); uint16_t crc=crc16(pkt,size-2); pkt[size-2]=(crc >>8) & 0xff; pkt[size-1]=crc & 0xff; if(key !=NULL) xxtea_encode_words((uint32_t*)pkt,size/4,key); CS_LOW(); xmit_spi(C_W_TX_PAYLOAD); sspSend(0,pkt,size); CS_HIGH(); CE_HIGH(); delayms(1); // Send it. (only needs >10ys, i think) CE_LOW(); return nrf_cmd_status(C_NOP); };
void power_up_flash_ram(void) { RAM_PORT &= ~(1<<RAM_CS); // assert cs xmit_spi(RAM_RES); RAM_PORT |= 1<<RAM_CS; // deassert cs _delay_us(30); }
void ram_sector_erase(uint8_t sector) { RAM_PORT &= ~(1<<RAM_CS); // assert cs xmit_spi(RAM_WREN); // write enable instruction RAM_PORT |= (1<<RAM_CS); // deassert cs _delay_us(1); RAM_PORT &= ~(1<<RAM_CS); // assert cs xmit_spi(RAM_SE); // sector erase instruction xmit_spi(sector); // sector erase instruction xmit_spi(0x00); // sector erase instruction xmit_spi(0x00); // sector erase instruction RAM_PORT |= (1<<RAM_CS); // deassert cs while (read_ram_status()) ; }
DRESULT disk_writep ( const BYTE *buff, /* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */ DWORD sa /* Number of bytes to send, Sector number (LBA) or zero */ ) { // BYTE buf; DRESULT res; WORD bc; static WORD wc; res = RES_ERROR; if (buff) { /* Send data bytes */ bc = (WORD)sa; while (bc && wc) { /* Send data bytes to the card */ xmit_spi(*buff++); wc--; bc--; } res = RES_OK; } else { if (sa) { /* Initiate sector write process */ if (!(CardType & CT_BLOCK)) sa *= 512; /* Convert to byte address if needed */ if (send_cmd(CMD24, sa) == 0) { /* WRITE_SINGLE_BLOCK */ xmit_spi(0xFF); xmit_spi(0xFE); /* Data block header */ wc = 512; /* Set byte counter */ res = RES_OK; } } else { /* Finalize sector write process */ bc = wc + 2; while (bc--) xmit_spi(0); /* Fill left bytes and CRC with zeros */ if ((rcv_spi() & 0x1F) == 0x05) { /* Receive data resp and wait for end of write process in timeout of 500ms */ // for (bc = 5000; buf!= 0xFF && bc; bc--){ // dly_100us(); /* Wait ready */ // buf=rcv_spi() ; // } for (bc = 5000; rcv_spi() != 0xFF && bc; bc--) dly_100us(); /* Wait ready */ if (bc) res = RES_OK; } DESELECT(); rcv_spi(); } } return res; }
uint8_t nrf_read_reg(const uint8_t reg){ uint8_t val; CS_LOW(); xmit_spi(C_R_REGISTER | reg); rcv_spi(&val); CS_HIGH(); return val; };
void nrf_read_long(const uint8_t cmd, int len, uint8_t* data){ CS_LOW(); xmit_spi(cmd); for(int i=0;i<len;i++) data[i] = 0x00; sspSendReceive(0,data,len); CS_HIGH(); };
void read_ram_id(uint8_t* mem_ptr) { RAM_PORT &= ~(1<<RAM_CS); // assert cs xmit_spi(RAM_RDID); mem_ptr[0] = recv_spi(); mem_ptr[1] = recv_spi(); mem_ptr[2] = recv_spi(); RAM_PORT |= 1<<RAM_CS; // deassert cs }
static void wait_for_ready() { BYTE reg_status = 0xFF; CS_LOW(); xmit_spi(OP_STATUSREAD); do { rcvr_spi_m((uint8_t *) ®_status); } while (!(reg_status & SB_READY)); CS_HIGH(); }
uint8_t read_ram_status(void) { uint8_t status; RAM_PORT &= ~(1<<RAM_CS); // assert cs xmit_spi(RAM_RDSR); status = recv_spi(); RAM_PORT |= 1<<RAM_CS; // deassert cs return status; }
DRESULT disk_writep ( const BYTE *buff, // Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) DWORD sa // Number of bytes to send, Sector number (LBA) or zero ) { DRESULT res; WORD bc; static WORD wc; if ((PINB&_BV(SD_INS))!=0x00) return RES_ERROR; if ((PINB&_BV(SD_WP))!=0x00) return RES_ERROR; res = RES_ERROR; if (buff) { // Send data bytes bc = (WORD)sa; while (bc && wc) { // Send data bytes to the card xmit_spi(*buff++); wc--; bc--; } res = RES_OK; } else { if (sa) { // Initiate sector write process if (!(CardType & CT_BLOCK)) sa *= 512; // Convert to byte address if needed if (send_cmd(CMD24, sa) == 0) { // WRITE_SINGLE_BLOCK xmit_spi(0xFF); xmit_spi(0xFE); // Data block header wc = 512; // Set byte counter res = RES_OK; } } else { // Finalize sector write process bc = wc + 2; while (bc--) xmit_spi(0); // Fill left bytes and CRC with zeros if ((rcv_spi() & 0x1F) == 0x05) { // Receive data resp and wait for end of write process in timeout of 300ms for (bc = 65000; rcv_spi() != 0xFF && bc; bc--) ; // Wait ready if (bc) res = RES_OK; } release_spi(); } } return res; }
//----------------------------------------------------------------------- // Send a command packet to MMC //----------------------------------------------------------------------- static BYTE send_cmd ( BYTE cmd, // Command byte DWORD arg // Argument ) { BYTE n, res; if (cmd & 0x80) { // ACMD<n> is the command sequense of CMD55-CMD<n> cmd &= 0x7F; res = send_cmd(CMD55, 0); if (res > 1) return res; } // Select the card DESELECT(); rcv_spi(); SELECT(); rcv_spi(); // Send a command packet xmit_spi(cmd); // Start + Command index xmit_spi((BYTE)(arg >> 24)); // Argument[31..24] xmit_spi((BYTE)(arg >> 16)); // Argument[23..16] xmit_spi((BYTE)(arg >> 8)); // Argument[15..8] xmit_spi((BYTE)arg); // Argument[7..0] n = 0x01; // Dummy CRC + Stop if (cmd == CMD0) n = 0x95; // Valid CRC for CMD0(0) if (cmd == CMD8) n = 0x87; // Valid CRC for CMD8(0x1AA) xmit_spi(n); // Receive a command response n = 10; // Wait for a valid response in timeout of 10 attempts do { res = rcv_spi(); } while ((res & 0x80) && --n); return res; // Return with the response value }
static BYTE send_cmd ( BYTE cmd, /* 1st byte (Start + Index) */ DWORD arg /* Argument (32 bits) */ ) { BYTE n, res; if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */ cmd &= 0x7F; res = send_cmd(CMD55, 0); if (res > 1) return res; } /* Select the card */ DESELECT(); rcv_spi(); SELECT(); rcv_spi(); /* Send a command packet */ xmit_spi(cmd); /* Start + Command index */ xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */ xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */ xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */ xmit_spi((BYTE)arg); /* Argument[7..0] */ n = 0x01; /* Dummy CRC + Stop */ if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */ if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */ xmit_spi(n); /* Receive a command response */ n = 10; /* Wait for a valid response in timeout of 10 attempts */ do { res = rcv_spi(); } while ((res & 0x80) && --n); return res; /* Return with the response value */ }
DRESULT dataflash_random_read(BYTE *buff, DWORD offset, DWORD length) { if (!length) return RES_PARERR; if (status & STA_NOINIT) return RES_NOTRDY; if (offset+length > MAX_PAGE*256) return RES_PARERR; do { wait_for_ready(); DWORD pageaddr = ((offset/256) << 9) | (offset%256); DWORD remaining = 256 - offset%256; if (remaining > length) { remaining = length; } length -= remaining; offset += remaining; CS_LOW(); xmit_spi(OP_PAGEREAD); xmit_spi((BYTE)(pageaddr >> 16)); xmit_spi((BYTE)(pageaddr >> 8)); xmit_spi((BYTE)pageaddr); xmit_spi(0x00); // follow up with 4 don't care bytes xmit_spi(0x00); xmit_spi(0x00); xmit_spi(0x00); do { rcvr_spi_m(buff++); } while (--remaining); CS_HIGH(); } while (length); return length ? RES_ERROR : RES_OK; }
void read_write_flash_ram(uint8_t one_read_zero_write,uint16_t bytes_to_readwrite,uint8_t flash_sector,uint8_t flash_page,uint8_t offset,uint8_t* mem_ptr) { // NB CAUTION page writes which cross page boundaries will wrap // parameters // one_read_zero_write = 1 for read, 0 for write // bytes_to_readwrite to read or write // flash sector within device // flash page within device // offset for first byte to transfer // POINTER TO ram address for first byte to transfer uint16_t i; // for ram device, enter and leave with SCK low RAM_PORT &= ~(1<<RAM_CS); // assert cs if (one_read_zero_write) { xmit_spi(RAM_READ); } else { xmit_spi(RAM_WREN); // write enable instruction RAM_PORT |= (1<<RAM_CS); _delay_us(1); RAM_PORT &= ~(1<<RAM_CS); xmit_spi(RAM_PP); } xmit_spi(flash_sector); xmit_spi(flash_page); xmit_spi(offset); for (i=0;i<bytes_to_readwrite;i++) { if (one_read_zero_write) { mem_ptr[i] = recv_spi(); } else { xmit_spi(mem_ptr[i]); } } RAM_PORT |= (1<<RAM_CS); _delay_ms(400); while (read_ram_status()) { _delay_ms(10); } }
char snd_pkt_no_crc(int size, uint8_t * pkt) { if(size > MAX_PKT) size=MAX_PKT; nrf_write_reg(R_CONFIG, R_CONFIG_PWR_UP| // Power on R_CONFIG_EN_CRC // CRC on, single byte ); CS_LOW(); xmit_spi(C_W_TX_PAYLOAD); sspSend(0,pkt,size); CS_HIGH(); CE_HIGH(); delayms(1); // Send it. (only needs >10ys, i think) CE_LOW(); return nrf_cmd_status(C_NOP); }
void nrf_write_long(const uint8_t cmd, int len, const uint8_t* data){ CS_LOW(); xmit_spi(cmd); sspSend(0,data,len); CS_HIGH(); };
static void spi_uart_send(unsigned long base, const char *buffer, unsigned short count) { for(size_t i = 0; i < count; ++i) { xmit_spi(THR); xmit_spi(*(buffer + i)); } }
DSTATUS disk_initialize(void) { u8 n, cmd, ty, ocr[4], rep, timeout; u16 tmr; power_on(); /* Force socket power on */ for (n = 10; n; n--) xmit_spi(0xFF); /* Dummy clocks */ ty = 0; timeout=100; // Trying to enter Idle state do { DESELECT(); xmit_spi(0xFF); SELECT(); rep = send_cmd(CMD0,0); } while ((rep != 1) && (--timeout)); if(timeout == 0) { DESELECT(); xmit_spi(0xFF); SELECT(); rep = send_cmd(CMD12,0); rep = send_cmd(CMD0,0); if (rep != 1) { return STA_NOINIT; } } rep = send_cmd(CMD8, 0x1AA); // SDHC if ( rep == 1) { for (n = 0; n < 4; n++) ocr[n] = rcvr_spi(); /* Get trailing return value of R7 resp */ if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ for (tmr = 25000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) ; /* Wait for leaving idle state (ACMD41 with HCS bit) */ if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ for (n = 0; n < 4; n++) ocr[n] = rcvr_spi(); ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 */ } } } // SDSC or MMC else { if (send_cmd(ACMD41, 0) <= 1) { ty = CT_SD1; cmd = ACMD41; /* SDv1 */ } else { ty = CT_MMC; cmd = CMD1; /* MMCv3 */ } for (tmr = 25000; tmr && send_cmd(cmd, 0); tmr--) ; /* Wait for leaving idle state */ if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ ty = 0; } CardType = ty; release_spi(); // Initialization succeded if (ty) { FCLK_FAST(); return RES_OK; } // Initialization failed else { power_off(); return STA_NOINIT; } }
void nrf_write_reg(const uint8_t reg, const uint8_t val){ CS_LOW(); xmit_spi(C_W_REGISTER | reg); xmit_spi(val); CS_HIGH(); };
static void dataflash_resume() { CS_LOW(); xmit_spi(OP_RESUME); CS_HIGH(); }
static void dataflash_powerdown() { CS_LOW(); xmit_spi(OP_POWERDOWN); CS_HIGH(); }
void power_down_flash_ram(void) { RAM_PORT &= ~(1<<RAM_CS); // assert cs xmit_spi(RAM_DP); RAM_PORT |= 1<<RAM_CS; // deassert cs }
DRESULT dataflash_random_write(const BYTE *buff, DWORD offset, DWORD length) { if (!length) return RES_PARERR; if (status & STA_NOINIT) return RES_NOTRDY; if (offset+length > MAX_PAGE*256) return RES_PARERR; do { wait_for_ready(); DWORD pageaddr = (offset/256) << 9; DWORD buffaddr = (offset%256); DWORD remaining = 256 - offset%256; if (remaining > length) { remaining = length; } length -= remaining; offset += remaining; // read page into the internal buffer CS_LOW(); xmit_spi(OP_PAGE2BUFFER1); xmit_spi((BYTE)(pageaddr >> 16)); xmit_spi((BYTE)(pageaddr >> 8)); xmit_spi((BYTE)pageaddr); CS_HIGH(); wait_for_ready(); // write bytes into the dataflash buffer CS_LOW(); xmit_spi(OP_BUFFER1WRITE); xmit_spi((BYTE)(buffaddr >> 16)); xmit_spi((BYTE)(buffaddr >> 8)); xmit_spi((BYTE)buffaddr); do { xmit_spi(*buff++); } while (--remaining); CS_HIGH(); wait_for_ready(); // compare buffer with target memory page CS_LOW(); xmit_spi(OP_BUFFER1PAGECMP); xmit_spi((BYTE)(pageaddr >> 16)); xmit_spi((BYTE)(pageaddr >> 8)); xmit_spi((BYTE)pageaddr); CS_HIGH(); wait_for_ready(); CS_LOW(); BYTE reg_status = 0xFF; xmit_spi(OP_STATUSREAD); rcvr_spi_m((uint8_t *) ®_status); CS_HIGH(); // trigger program only if data changed if (reg_status & SB_COMP) { CS_LOW(); xmit_spi(OP_BUFFER1PROG); xmit_spi((BYTE)(pageaddr >> 16)); xmit_spi((BYTE)(pageaddr >> 8)); xmit_spi((BYTE)pageaddr); CS_HIGH(); } } while (length); return length ? RES_ERROR : RES_OK; }
void nrf_cmd(uint8_t cmd){ CS_LOW(); xmit_spi(cmd); CS_HIGH(); };