📄 atmel-flash.c
字号:
#define READBIT(n) \ PORTD = clrClkAndData; \ asm __volatile__ \ ("\tsbi 18,5\n" \ "\tsbic 16,2\n" \ "\tori %0,1<<" #n "\n" \ : "=d" (spiIn) : "0" (spiIn))/** @brief Retrieve 1 byte of data from the external flash. */static uint8_t atmel_flash_get_byte (void){ uint8_t spiIn = 0; uint8_t handle = mos_disable_ints(); BITINIT; READBIT(7); READBIT(6); READBIT(5); READBIT(4); READBIT(3); READBIT(2); READBIT(1); READBIT(0); mos_enable_ints(handle); return spiIn;}/** @brief Send 1 byte of data from the external flash. */static uint8_t atmel_flash_send_byte (uint8_t spiOut){ uint8_t spiIn = 0; uint8_t handle = mos_disable_ints(); BITINIT; WRITEBIT(7); WRITEBIT(6); WRITEBIT(5); WRITEBIT(4); WRITEBIT(3); WRITEBIT(2); WRITEBIT(1); WRITEBIT(0); mos_enable_ints(handle); return spiIn;}/* Directly Read Through the Memory, doesn't change the buffer * It works when writing/reading the characters, but doesn't work * when writing the long data. Sometimes it just doesn't work * need to use logic analysis figure out later. *//** @brief Directly read through the memory. */static void atmel_flash_read_memory(uint16_t page, uint16_t offset, void *reqData, uint16_t len){ uint8_t cmd[8], *reqPtr; uint16_t i; cmd[0] = C_READ_THROUGH_MEMORY; // 8 bit of op code cmd[1] = (page >> 7); // 4 bit reserve and high 4 MSB cmd[2] = (page << 1) | offset >> 8;// 7 bit page and 1 bit offset MSB cmd[3] = offset; // low-order 8 address bits cmd[4] = 0x00; cmd[5] = 0x00; cmd[6] = 0x00; cmd[7] = 0x00; reqPtr = (uint8_t *)reqData; atmel_flash_low(); for (i = 0; i < sizeof (cmd); i++) atmel_flash_send_byte(cmd[i]); for (i = 0; i < len; i++) reqPtr[i] = atmel_flash_get_byte(); atmel_flash_high(); }/** @brief Compute crc on main memory without using a buffer. */static uint16_t atmel_flash_crc_memory(uint16_t page, uint16_t offset, uint32_t len){ uint8_t cmd[8]; uint16_t crc; uint32_t i; cmd[0] = C_READ_THROUGH_MEMORY; // 8 bit of op code cmd[1] = (page >> 7); // 4 bit reserve and high 4 MSB cmd[2] = (page << 1) | offset >> 8;// 7 bit page and 1 bit offset MSB cmd[3] = offset; // low-order 8 address bits cmd[4] = 0x00; cmd[5] = 0x00; cmd[6] = 0x00; cmd[7] = 0x00; atmel_flash_low(); for (i = 0; i < sizeof (cmd); i++) atmel_flash_send_byte(cmd[i]); // The following code was adapted directly from crc.c { uint8_t v, xor_flag, byte, bit; crc = 0xFFFF/*INITIAL_VALUE*/; for(i = 0; i < len; i++) { // Read the current byte from flash byte = atmel_flash_get_byte(); v = 0x80; for(bit = 0; bit < 8; bit++) { if(crc & 0x8000) xor_flag= 1; else xor_flag= 0; crc = crc << 1; if(byte & v) crc= crc + 1; if(xor_flag) crc = crc ^ 0x1021/*POLY*/; v = v >> 1; } } for(bit = 0; bit < 16; bit++) { if(crc & 0x8000) xor_flag= 1; else xor_flag= 0; crc = crc << 1; if(xor_flag) crc = crc ^ 0x1021/*POLY*/; } } atmel_flash_high(); return crc; }/** @brief Get the flash register status. * @return Status of external flash *//* static uint8_t atmel_flash_get_status (void) { uint8_t status; atmel_flash_low(); atmel_flash_send_byte(C_REQ_STATUS); //SEND d7h, op code for register request status = atmel_flash_get_byte(); atmel_flash_high(); return status; }*//** @brief Check the status of flash to see whether it's busy or not. * * A little bit slower than simply holding the clk low, But * easier * @return TRUE if busy, else return FALSE */static uint8_t atmel_flash_busy (void){ uint8_t status; atmel_flash_low(); atmel_flash_send_byte(C_REQ_STATUS); //SEND d7h, op code for register request status = atmel_flash_get_byte(); atmel_flash_high(); status &= 0x80; if( status == 0) return TRUE; return FALSE;}//first version, no length check/** @brief Read data from the buffer. * @param selected Read buffer to select * @param offset How far the data is offset * @param reqdata Data requested * @param len Length of data * @return TRUE if success, else return FALSE *//* static void atmel_flash_read_buffer(uint8_t selected, uint16_t offset, void *reqdata, uint16_t len) { uint8_t cmd[5], *reqPtr; uint16_t i; if(selected == 1) cmd[0] = C_READ_BUFFER1; // 8 bit of op code else cmd[0] = C_READ_BUFFER2; // 8 bit of op code cmd[1] = 0x00; // 8 bit don't care code cmd[2] = offset>>8; // 8 bit don't care code cmd[3] = offset; // low-order 8 address bits cmd[4] = 0x00; // 8 bit don't care code reqPtr = (uint8_t *)reqdata; atmel_flash_low(); for (i = 0; i < sizeof (cmd); i++) atmel_flash_send_byte(cmd[i]); for (i = 0; i < len; i++) reqPtr[i] = atmel_flash_get_byte(); atmel_flash_high(); }*//** @brief Write the data to the buffer. * @param selected Write buffer to select * @param offset How far the data will be offset * @param reqdata Data requested * @param len Length of data * @return TRUE if success, else return FALSE */static uint8_t atmel_flash_write_buffer(uint8_t selected, uint16_t offset, void *reqdata, uint16_t len){ uint8_t cmd[4], *reqPtr; uint16_t i; if(selected == 1) cmd[0] = C_WRITE_BUFFER1; // 8 bit of op code else cmd[0] = C_WRITE_BUFFER2; // 8 bit of op code cmd[1] = 0x00; // 8 bit don't care code cmd[2] = offset>>8; // 7 bit don't care code with 1 bit address cmd[3] = offset; // low-order 8 address bits reqPtr = (uint8_t *)reqdata; // put the cs to low in order to begin writing atmel_flash_low(); for (i = 0; i < sizeof (cmd); i++) atmel_flash_send_byte(cmd[i]); for (i = 0; i < len; i++) atmel_flash_send_byte(reqPtr[i]); atmel_flash_high(); return TRUE;}/** @brief Dump the buffer to the memory. * @param selected Flush buffer to select * @param page Page to flush to * @return TRUE if success, else return FALSE */static uint8_t atmel_flash_flush_buffer(uint8_t selected, uint16_t page){ uint8_t i, cmd[4]; if(selected == 1) cmd[0] = C_FLUSH_BUFFER1; // 8 bit of op code else cmd[0] = C_FLUSH_BUFFER2; // 8 bit of op code cmd[1] = page >> 7; // 4 bit reserve and high 4 MSB cmd[2] = page << 1; // 7 bit page and 1 bit offset MSB cmd[3] = 0x00; // 8 bit don't care code // put the cs to low in order to begin writing atmel_flash_low(); for (i = 0; i < sizeof (cmd); i++) atmel_flash_send_byte(cmd[i]); atmel_flash_high(); return TRUE;}/** @brief Compare the buffer to the memory. * @param selected Buffer to compare * @param page Page to compare to * @return 0 if equal, else return 0x40 */static uint8_t atmel_flash_compare_buffer(uint8_t selected, uint16_t page){ uint8_t i, cmd[4], status; if(selected == 1) cmd[0] = C_COMPARE_BUFFER1; // 8 bit of op code else cmd[0] = C_COMPARE_BUFFER2; // 8 bit of op code cmd[1] = page >> 7; // 4 bit reserve and high 4 MSB cmd[2] = page << 1; // 7 bit page and 1 bit offset MSB cmd[3] = 0x00; // 8 bit don't care code // put the cs to low in order to begin writing atmel_flash_low(); for (i = 0; i < sizeof (cmd); i++) atmel_flash_send_byte(cmd[i]); atmel_flash_high(); do { atmel_flash_low(); atmel_flash_send_byte(C_REQ_STATUS); //SEND d7h, op code for register request status = atmel_flash_get_byte(); atmel_flash_high(); } while (status & 0x80); // wait until comparison is complete return status & 0x40; // return result of comparison}/** @brief Read a page from flash memory and fill into the buffer. * @param selected Fill buffer to select * @param page Page to fill from * @return TRUE if success, else return FALSE */static uint8_t atmel_flash_fill_buffer(uint8_t selected, uint16_t page){ uint8_t i, cmd[4]; if(selected == 1) cmd[0] = C_FILL_BUFFER1; // 8 bit of op code else cmd[0] = C_FILL_BUFFER2; // 8 bit of op code cmd[1] = page >> 7; // 4 bit reserve and high 4 MSB cmd[2] = page << 1; // 7 bit page and 1 bit don't care MSB cmd[3] = 0x00; // 8 bit don't care code // put the cs to low in order to begin writing atmel_flash_low(); for (i = 0; i < sizeof (cmd); i++) atmel_flash_send_byte(cmd[i]); atmel_flash_high(); return TRUE;}/** @brief Erase a whole page in the memory. * @param page Page to erase * @return TRUE if success, else return FALSE */static uint8_t atmel_flash_erase_page(uint16_t page){ uint8_t i, cmd[4]; cmd[0] = C_ERASE_PAGE; // 8 bit of op code cmd[1] = page >> 7; // 4 bit reserve and high 4 MSB cmd[2] = page << 1; // 7 bit page and 1 bit don't care MSB cmd[3] = 0x00; // 8 bit don't care code // put the cs to low in order to begin writing atmel_flash_low(); for (i = 0; i < sizeof (cmd); i++) atmel_flash_send_byte(cmd[i]); atmel_flash_high(); return TRUE; }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -