New ML support - W25X20CL external spi flash support

This commit is contained in:
Robert Pelnar 2018-06-08 00:20:28 +02:00
parent 3417392791
commit bd1e410228
10 changed files with 469 additions and 114 deletions

View file

@ -83,6 +83,9 @@
#include "tmc2130.h"
#endif //TMC2130
#ifdef W25X20CL
#include "w25x20cl.h"
#endif //W25X20CL
#ifdef BLINKM
#include "BlinkM.h"
@ -982,6 +985,8 @@ void __test()
while(1);
}
#ifdef W25X20CL
void upgrade_sec_lang_from_external_flash()
{
if ((boot_app_magic == 0x55aa55aa) && (boot_app_flags & BOOT_APP_FLG_USER0))
@ -999,11 +1004,54 @@ void upgrade_sec_lang_from_external_flash()
boot_app_flags &= ~BOOT_APP_FLG_USER0;
}
uint8_t lang_xflash_enum_codes(uint16_t* codes)
{
lang_table_header_t header;
uint8_t count = 0;
uint32_t addr = 0x00000;
while (1)
{
printf_P(_n("LANGTABLE%d:"), count);
w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t));
if (header.magic != LANG_MAGIC)
{
printf_P(_n("NG!\n"));
break;
}
printf_P(_n("OK\n"));
printf_P(_n(" _lt_magic = 0x%08lx %S\n"), header.magic, (header.magic==LANG_MAGIC)?_n("OK"):_n("NA"));
printf_P(_n(" _lt_size = 0x%04x (%d)\n"), header.size, header.size);
printf_P(_n(" _lt_count = 0x%04x (%d)\n"), header.count, header.count);
printf_P(_n(" _lt_chsum = 0x%04x\n"), header.checksum);
printf_P(_n(" _lt_code = 0x%04x\n"), header.code);
printf_P(_n(" _lt_resv1 = 0x%08lx\n"), header.reserved1);
addr += header.size;
codes[count] = header.code;
count ++;
}
return count;
}
void list_sec_lang_from_external_flash()
{
uint16_t codes[8];
uint8_t count = lang_xflash_enum_codes(codes);
printf_P(_n("XFlash lang count = %hhd\n"), count);
}
#endif //W25X20CL
// "Setup" function is called by the Arduino framework on startup.
// Before startup, the Timers-functions (PWM)/Analog RW and HardwareSerial provided by the Arduino-code
// are initialized by the main() routine provided by the Arduino framework.
void setup()
{
#ifdef NEW_SPI
spi_init();
#endif //NEW_SPI
lcd_init();
fdev_setup_stream(lcdout, lcd_putchar, NULL, _FDEV_SETUP_WRITE); //setup lcdout stream
@ -1157,9 +1205,6 @@ void setup()
#endif //TMC2130
#ifdef NEW_SPI
spi_init();
#endif //NEW_SPI
st_init(); // Initialize stepper, this enables interrupts!
@ -1303,16 +1348,35 @@ void setup()
// If they differ, an update procedure may need to be performed. At the end of this block, the current firmware version
// is being written into the EEPROM, so the update procedure will be triggered only once.
spi_setup(TMC2130_SPCR, TMC2130_SPSR);
puts_P(_n("w25x20cl init: "));
if (w25x20cl_ini())
{
uint8_t uid[8]; // 64bit unique id
w25x20cl_rd_uid(uid);
puts_P(_n("OK, UID="));
for (uint8_t i = 0; i < 8; i ++)
printf_P(PSTR("%02hhx"), uid[i]);
putchar('\n');
list_sec_lang_from_external_flash();
}
else
puts_P(_n("NG!\n"));
lang_selected = eeprom_read_byte((uint8_t*)EEPROM_LANG);
if (lang_selected >= LANG_NUM)
{
lcd_mylang();
// lcd_mylang();
lang_selected = 0;
}
lang_select(lang_selected);
uint16_t sec_lang_code=lang_get_code(1);
printf_P(_n("SEC_LANG_CODE=0x%04x (%c%c)\n"), sec_lang_code, sec_lang_code >> 8, sec_lang_code & 0xff);
#ifdef DEBUG_SEC_LANG
lang_print_sec_lang(uartout);
#endif //DEBUG_SEC_LANG

View file

@ -18,6 +18,9 @@
#define TMC2130_SPCR SPI_SPCR(TMC2130_SPI_RATE, 1, 1, 1, 0)
#define TMC2130_SPSR SPI_SPSR(TMC2130_SPI_RATE)
//W25X20CL configuration
#define W25X20CL_PIN_CS 32
//LANG - Multi-language support
//#define LANG_MODE 0 // primary language only
#define LANG_MODE 1 // sec. language support

View file

@ -4,54 +4,44 @@
#include "bootapp.h"
// Currectly active language selection.
#ifdef W25X20CL
#include "w25x20cl.h"
#endif //W25X20CL
// Currently active language selection.
uint8_t lang_selected = 0;
#if (LANG_MODE == 0) //primary language only
#else //(LANG_MODE == 0)
uint8_t lang_select(uint8_t lang) { return 0; }
uint8_t lang_get_count() { return 1; }
uint16_t lang_get_code(uint8_t lang) { return LANG_CODE_EN; }
const char* lang_get_name_by_code(uint16_t code) { return _n("English"); }
#else //(LANG_MODE == 0) //secondary languages in progmem or xflash
//reserved xx kbytes for secondary language table
const char _SEC_LANG[LANG_SIZE_RESERVED] PROGMEM_I2 = "_SEC_LANG";
#endif //(LANG_MODE == 0)
//lang_table_header_t structure - (size= 16byte)
typedef struct
{
uint32_t magic; //+0
uint16_t size; //+4
uint16_t count; //+6
uint16_t checksum; //+8
uint16_t code; //+10
uint32_t reserved1; //+12
} lang_table_header_t;
//lang_table_t structure - (size= 16byte + 2*count)
typedef struct
{
lang_table_header_t header;
uint16_t table[];
} lang_table_t;
//lang_table pointer
lang_table_t* lang_table = 0;
const char* lang_get_translation(const char* s)
{
if (lang_selected == 0) return s + 2; //primary language selected
if (lang_table == 0) return s + 2; //sec. lang table not found
if (lang_selected == 0) return s + 2; //primary language selected, return orig. str.
if (lang_table == 0) return s + 2; //sec. lang table not found, return orig. str.
uint16_t ui = pgm_read_word(((uint16_t*)s)); //read string id
if (ui == 0xffff) return s + 2; //translation not found
if (ui == 0xffff) return s + 2; //translation not found, return orig. str.
ui = pgm_read_word(((uint16_t*)(((char*)lang_table + 16 + ui*2)))); //read relative offset
if (pgm_read_byte(((uint8_t*)((char*)lang_table + ui))) == 0)
return s + 2;//not translated string
if (pgm_read_byte(((uint8_t*)((char*)lang_table + ui))) == 0) //read first character
return s + 2;//zero length string == not translated, return orig. str.
return (const char*)((char*)lang_table + ui); //return calculated pointer
}
const char* lang_get_sec_lang_str(const char* s)
{
uint16_t ui = (uint16_t)&_SEC_LANG; //pointer to _SEC_LANG reserved space
ui += 0x00ff; //add 1 page
ui &= 0xff00; //align to page
uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
lang_table_t* _lang_table = ui; //table pointer
ui = pgm_read_word(((uint16_t*)s)); //read string id
if (ui == 0xffff) return s + 2; //translation not found
@ -59,69 +49,108 @@ const char* lang_get_sec_lang_str(const char* s)
return (const char*)((char*)_lang_table + ui); //return calculated pointer
}
const char* lang_get_sec_lang_str_by_id(uint16_t id)
uint8_t lang_select(uint8_t lang)
{
uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
return ui + pgm_read_word(((uint16_t*)(ui + 16 + id * 2))); //read relative offset and return calculated pointer
}
const char* lang_select(uint8_t lang)
{
#if (LANG_MODE == 0) //primary language only
return 0;
#else //(LANG_MODE == 0)
if (lang == 0) //primary language
if (lang == LANG_ID_PRI) //primary language
{
lang_table = 0;
lang_selected = 0;
return;
return 1;
}
if (lang == LANG_ID_SEC) //current secondary language
{
uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
if (pgm_read_dword(((uint32_t*)(ui + 0))) != LANG_MAGIC) return 0; //magic not valid
lang_table = ui; // set table pointer
lang_selected = 1; // set language id
return 1;
}
/*
uint16_t ui = (uint16_t)&_SEC_LANG; //pointer to _SEC_LANG reserved space
ui += 0x00ff; //add 1 page
ui &= 0xff00; //align to page
lang_table = ui; //set table pointer
ui = pgm_read_word(((uint16_t*)(((char*)lang_table + 16)))); //read relative offset of first string (language name)
return (const char*)((char*)lang_table + ui); //return calculated pointer
#endif //(LANG_MODE == 0)
*/
}
uint8_t lang_get_count()
{
uint16_t ui = (uint16_t)&_SEC_LANG; //pointer to _SEC_LANG reserved space
ui += 0x00ff; //add 1 page
ui &= 0xff00; //align to page
lang_table_t* _lang_table = ui; //table pointer
if (pgm_read_dword(((uint32_t*)(_lang_table + 0))) == LANG_MAGIC) return 2;
return 1;
}
const char* lang_get_name(uint8_t lang)
{
if (lang == LANG_ID_UNDEFINED) lang = lang_selected;
if (lang == LANG_ID_PRI) return MSG_LANGUAGE_NAME + 2;
if (lang == LANG_ID_SEC)
//#ifdef W25X20CL
uint8_t count = 1; //count = 1+n (primary + all in xflash)
uint32_t addr = 0x00000; //start of xflash
lang_table_header_t header; //table header structure
while (1)
{
uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
if (pgm_read_dword(((uint32_t*)(ui + 0))) == LANG_MAGIC) //magic num is OK
return lang_get_sec_lang_str(MSG_LANGUAGE_NAME);
w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash
if (header.magic != LANG_MAGIC) break; //break if magic not valid
addr += header.size; //calc address of next table
count++; //inc counter
}
return 0;
return count;
}
uint16_t lang_get_code(uint8_t lang)
{
if (lang == LANG_ID_UNDEFINED) lang = lang_selected;
if (lang == LANG_ID_PRI) return LANG_CODE_EN;
if (lang == LANG_ID_PRI) return LANG_CODE_EN; //primary lang = EN
if (lang == LANG_ID_SEC)
{
uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
if (pgm_read_dword(((uint32_t*)(ui + 0))) == LANG_MAGIC) //magic num is OK
return pgm_read_word(((uint16_t*)(ui + 10))); //read language code
if (pgm_read_dword(((uint32_t*)(ui + 0))) != LANG_MAGIC) return LANG_CODE_XX; //magic not valid
return pgm_read_word(((uint32_t*)(ui + 10))); //return lang code from progmem
}
uint32_t addr = 0x00000; //start of xflash
lang_table_header_t header; //table header structure
lang--;
while (1)
{
w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash
if (header.magic != LANG_MAGIC) break; //break if not valid
if (--lang == 0) return header.code;
addr += header.size; //calc address of next table
}
// if (lang == LANG_ID_SEC)
// {
// uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
// if (pgm_read_dword(((uint32_t*)(ui + 0))) == LANG_MAGIC) //magic num is OK
// return pgm_read_word(((uint16_t*)(ui + 10))); //read language code
// }
return LANG_CODE_XX;
}
const char* lang_get_name_by_code(uint16_t code)
{
switch (code)
{
case LANG_CODE_EN: return _n("English");
case LANG_CODE_CZ: return _n("Cestina");
case LANG_CODE_DE: return _n("Deutsch");
case LANG_CODE_ES: return _n("Espanol");
case LANG_CODE_IT: return _n("Italiano");
case LANG_CODE_PL: return _n("Polski");
}
return _n("??");
// if (lang == LANG_ID_UNDEFINED) lang = lang_selected;
// if (lang == LANG_ID_PRI) return _T(MSG_LANGUAGE_NAME + 2);
// if (lang == LANG_ID_SEC)
// {
// uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
// if (pgm_read_dword(((uint32_t*)(ui + 0))) == LANG_MAGIC) //magic num is OK
// return lang_get_sec_lang_str(MSG_LANGUAGE_NAME);
// }
// return 0;
}
#ifdef DEBUG_SEC_LANG
const char* lang_get_sec_lang_str_by_id(uint16_t id)
{
uint16_t ui = ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00); //table pointer
return ui + pgm_read_word(((uint16_t*)(ui + 16 + id * 2))); //read relative offset and return calculated pointer
}
uint16_t lang_print_sec_lang(FILE* out)
{
printf_P(_n("&_SEC_LANG = 0x%04x\n"), &_SEC_LANG);
@ -149,6 +178,7 @@ uint16_t lang_print_sec_lang(FILE* out)
}
#endif //DEBUG_SEC_LANG
#endif //(LANG_MODE == 0)
const char MSG_LANGUAGE_NAME[] PROGMEM_I1 = ISTR("English"); ////c=0 r=0
//const char MSG_LANGUAGE_NAME[] PROGMEM_I1 = ISTR("English"); ////c=0 r=0

View file

@ -2,15 +2,15 @@
#ifndef LANGUAGE_H
#define LANGUAGE_H
#define W25X20CL
#include "config.h"
#include <inttypes.h>
#include <stdio.h>
//#include <stdio.h>
#define PROTOCOL_VERSION "1.0"
#ifdef CUSTOM_MENDEL_NAME
// #define CUSTOM_MENDEL_NAME CUSTOM_MENDEL_NAME
#else
#ifndef CUSTOM_MENDEL_NAME
#define MACHINE_NAME "Mendel"
#endif
@ -44,6 +44,23 @@
#define _N(s) (__extension__({static const char __c[] PROGMEM_N1 = s; &__c[0];}))
#define _n(s) _N(s)
//lang_table_header_t structure - (size= 16byte)
typedef struct
{
uint32_t magic; //+0
uint16_t size; //+4
uint16_t count; //+6
uint16_t checksum; //+8
uint16_t code; //+10
uint32_t reserved1; //+12
} lang_table_header_t;
//lang_table_t structure - (size= 16byte + 2*count)
typedef struct
{
lang_table_header_t header;
uint16_t table[];
} lang_table_t;
// Language indices into their particular symbol tables.
#define LANG_ID_PRI 0
@ -82,21 +99,23 @@ extern uint8_t lang_selected;
#if (LANG_MODE != 0)
extern const char _SEC_LANG[LANG_SIZE_RESERVED];
#endif //(LANG_MODE == 0)
extern const char* lang_get_translation(const char* s);
extern const char* lang_get_sec_lang_str(const char* s);
extern const char* lang_get_sec_lang_str_by_id(uint16_t id);
extern const char* lang_select(uint8_t lang);
#endif //(LANG_MODE != 0)
//selects
extern uint8_t lang_select(uint8_t lang);
//get total number of languages (primary + all in xflash)
extern uint8_t lang_get_count();
extern const char* lang_get_name(uint8_t lang);
extern uint16_t lang_get_code(uint8_t lang);
extern const char* lang_get_name_by_code(uint16_t code);
#ifdef DEBUG_SEC_LANG
extern const char* lang_get_sec_lang_str_by_id(uint16_t id);
extern uint16_t lang_print_sec_lang(FILE* out);
#endif //DEBUG_SEC_LANG
#if defined(__cplusplus)
}
#endif //defined(__cplusplus)
@ -104,7 +123,8 @@ extern uint16_t lang_print_sec_lang(FILE* out);
#define CAT2(_s1, _s2) _s1
#define CAT4(_s1, _s2, _s3, _s4) _s1
extern const char MSG_LANGUAGE_NAME[];
//Localized language name
//extern const char MSG_LANGUAGE_NAME[];
#include "messages.h"

View file

@ -15,6 +15,7 @@
#define AMBIENT_THERMISTOR
#define PINDA_THERMISTOR
#define W25X20CL // external 256kB flash
#define SWI2C // enable software i2c
#define SWI2C_A8 // 8bit address functions

View file

@ -15,7 +15,11 @@
#define DD_MOSI 2
#define DD_MISO 3
inline void spi_init()
#if defined(__cplusplus)
extern "C" {
#endif //defined(__cplusplus)
static inline void spi_init()
{
DDRB &= ~((1 << DD_SCK) | (1 << DD_MOSI) | (1 << DD_MISO));
DDRB |= (1 << DD_SS) | (1 << DD_SCK) | (1 << DD_MOSI);
@ -25,17 +29,21 @@ inline void spi_init()
SPSR = 0x00;
}
inline void spi_setup(uint8_t spcr, uint8_t spsr)
static inline void spi_setup(uint8_t spcr, uint8_t spsr)
{
SPCR = spcr;
SPSR = spsr;
}
inline uint8_t spi_txrx(uint8_t tx)
static inline uint8_t spi_txrx(uint8_t tx)
{
SPDR = tx;
while (!(SPSR & (1 << SPIF)));
return SPDR;
}
#if defined(__cplusplus)
}
#endif //defined(__cplusplus)
#endif //SPI_H

View file

@ -3715,14 +3715,18 @@ static void lcd_crash_mode_set()
#endif //TMC2130
static void lcd_set_lang(unsigned char lang) {
lang_selected = lang;
firstrun = 1;
eeprom_update_byte((unsigned char *)EEPROM_LANG, lang);
/*langsel=0;*/
if (langsel == LANGSEL_MODAL)
// From modal mode to an active mode? This forces the menu to return to the setup menu.
langsel = LANGSEL_ACTIVE;
static void lcd_set_lang(unsigned char lang)
{
lang_select(lang);
/*
lang_selected = lang;
firstrun = 1;
eeprom_update_byte((unsigned char *)EEPROM_LANG, lang);
// langsel=0;
if (langsel == LANGSEL_MODAL)
// From modal mode to an active mode? This forces the menu to return to the setup menu.
langsel = LANGSEL_ACTIVE;
*/
}
#ifdef PAT9125
@ -3756,17 +3760,21 @@ void lcd_force_language_selection() {
eeprom_update_byte((unsigned char *)EEPROM_LANG, LANG_ID_FORCE_SELECTION);
}
#if (LANG_MODE != 0)
static void lcd_language_menu()
{
START_MENU();
if (langsel == LANGSEL_OFF)
MENU_ITEM(back, _T(MSG_SETTINGS), 0);
else if (langsel == LANGSEL_ACTIVE)
MENU_ITEM(back, _T(MSG_WATCH), 0);
for (int i=0; i < lang_get_count(); i++)
MENU_ITEM(setlang, lang_get_name(i), i);
END_MENU();
START_MENU();
if (langsel == LANGSEL_OFF)
MENU_ITEM(back, _T(MSG_SETTINGS), 0);
else if (langsel == LANGSEL_ACTIVE)
MENU_ITEM(back, _T(MSG_WATCH), 0);
MENU_ITEM(setlang, lang_get_name_by_code(lang_get_code(0)), 0);
for (int i = 1; i < lang_get_count(); i++)
MENU_ITEM(setlang, lang_get_name_by_code(lang_get_code(i+1)), i);
END_MENU();
}
#endif //(LANG_MODE != 0)
void lcd_mesh_bedleveling()
{
@ -4232,7 +4240,10 @@ static void lcd_settings_menu()
{
MENU_ITEM(submenu, _T(MSG_BABYSTEP_Z), lcd_babystep_z);
}
#if (LANG_MODE != 0)
MENU_ITEM(submenu, _i("Select language"), lcd_language_menu);////MSG_LANGUAGE_SELECT c=0 r=0
#endif //(LANG_MODE != 0)
if (card.ToshibaFlashAir_isEnabled()) {
MENU_ITEM(function, _i("SD card [FlshAir]"), lcd_toshiba_flash_air_compatibility_toggle);////MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_ON c=19 r=1
@ -4591,7 +4602,7 @@ void lcd_mylang_drawmenu(int cursor) {
}
}
*/
/*
void lcd_mylang_drawmenu(int cursor)
{
unsigned char lang_cnt = lang_get_count();
@ -4642,7 +4653,8 @@ void lcd_mylang_drawmenu(int cursor)
lcd.print("^");
}
}
*/
/*
void lcd_mylang_drawcursor(int cursor) {
unsigned char lang_cnt = lang_get_count();
@ -4652,8 +4664,9 @@ void lcd_mylang_drawcursor(int cursor) {
lcd.print(">");
}
}
*/
/*
void lcd_mylang()
{
int enc_dif = 0;
@ -4710,15 +4723,13 @@ void lcd_mylang()
delay(500);
}
/*
if (++counter == 80) {
hlaska++;
if(hlaska>LANG_NUM) hlaska=1;
lcd_mylang_top(hlaska);
lcd_mylang_drawcursor(cursor_pos);
counter=0;
}
*/
// if (++counter == 80) {
// hlaska++;
// if(hlaska>LANG_NUM) hlaska=1;
// lcd_mylang_top(hlaska);
// lcd_mylang_drawcursor(cursor_pos);
// counter=0;
// }
};
if(MYSERIAL.available() > 1){
@ -4731,7 +4742,7 @@ void lcd_mylang()
lcd_return_to_status();
}
*/
void bowden_menu() {
int enc_dif = encoderDiff;
int cursor_pos = 0;

View file

@ -32,7 +32,7 @@
void prusa_statistics(int _message, uint8_t _col_nr = 0);
void lcd_confirm_print();
unsigned char lcd_choose_color();
void lcd_mylang();
//void lcd_mylang();
bool lcd_detected(void);
static void lcd_selftest_v();

178
Firmware/w25x20cl.c Normal file
View file

@ -0,0 +1,178 @@
//w25x20cl.c
#include "w25x20cl.h"
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "io_atmega2560.h"
#include "spi.h"
#define _MFRID 0xEF
#define _DEVID 0x11
#define _CMD_ENABLE_WR 0x06
#define _CMD_ENABLE_WR_VSR 0x50
#define _CMD_DISABLE_WR 0x04
#define _CMD_RD_STATUS_REG 0x05
#define _CMD_WR_STATUS_REG 0x01
#define _CMD_RD_DATA 0x03
#define _CMD_RD_FAST 0x0b
#define _CMD_RD_FAST_D_O 0x3b
#define _CMD_RD_FAST_D_IO 0xbb
#define _CMD_PAGE_PROGRAM 0x02
#define _CMD_SECTOR_ERASE 0x20
#define _CMD_BLOCK32_ERASE 0x52
#define _CMD_BLOCK64_ERASE 0xd8
#define _CMD_CHIP_ERASE 0xc7
#define _CMD_CHIP_ERASE2 0x60
#define _CMD_PWR_DOWN 0xb9
#define _CMD_PWR_DOWN_REL 0xab
#define _CMD_MFRID_DEVID 0x90
#define _CMD_MFRID_DEVID_D 0x92
#define _CMD_JEDEC_ID 0x9f
#define _CMD_RD_UID 0x4b
#define _CS_LOW() PORT(W25X20CL_PIN_CS) &= ~__MSK(W25X20CL_PIN_CS)
#define _CS_HIGH() PORT(W25X20CL_PIN_CS) |= __MSK(W25X20CL_PIN_CS)
//#define _SPI_TX swspi_tx
//#define _SPI_RX swspi_rx
#define _SPI_TX(b) spi_txrx(b)
#define _SPI_RX() spi_txrx(0xff)
int w25x20cl_mfrid_devid(void);
int8_t w25x20cl_ini(void)
{
PIN_OUT(W25X20CL_PIN_CS);
_CS_HIGH();
if (!w25x20cl_mfrid_devid()) return 0;
return 1;
}
void w25x20cl_enable_wr(void)
{
_CS_LOW();
_SPI_TX(_CMD_ENABLE_WR); // send command 0x06
_CS_HIGH();
}
void w25x20cl_disable_wr(void)
{
_CS_LOW();
_SPI_TX(_CMD_DISABLE_WR); // send command 0x04
_CS_HIGH();
}
uint8_t w25x20cl_rd_status_reg(void)
{
_CS_LOW();
_SPI_TX(_CMD_RD_STATUS_REG); // send command 0x90
uint8_t val = _SPI_RX(); // receive value
_CS_HIGH();
return val;
}
void w25x20cl_wr_status_reg(uint8_t val)
{
_CS_LOW();
_SPI_TX(_CMD_WR_STATUS_REG); // send command 0x90
_SPI_TX(val); // send value
_CS_HIGH();
}
void w25x20cl_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt)
{
_CS_LOW();
_SPI_TX(_CMD_RD_DATA); // send command 0x03
_SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
_SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
_SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
while (cnt--) // receive data
*(data++) = _SPI_RX();
_CS_HIGH();
}
void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt)
{
_CS_LOW();
_SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02
_SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
_SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
_SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
while (cnt--) // send data
_SPI_TX(*(data++));
_CS_HIGH();
}
void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt)
{
_CS_LOW();
_SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02
_SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
_SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
_SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
while (cnt--) // send data
_SPI_TX(pgm_read_byte(data++));
_CS_HIGH();
}
void w25x20cl_erase(uint8_t cmd, uint32_t addr)
{
_CS_LOW();
_SPI_TX(_CMD_SECTOR_ERASE); // send command 0x20
_SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23
_SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15
_SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7
_CS_HIGH();
}
void w25x20cl_sector_erase(uint32_t addr)
{
return w25x20cl_erase(_CMD_SECTOR_ERASE, addr);
}
void w25x20cl_block32_erase(uint32_t addr)
{
return w25x20cl_erase(_CMD_BLOCK32_ERASE, addr);
}
void w25x20cl_block64_erase(uint32_t addr)
{
return w25x20cl_erase(_CMD_BLOCK64_ERASE, addr);
}
void w25x20cl_chip_erase(void)
{
_CS_LOW();
_SPI_TX(_CMD_CHIP_ERASE); // send command 0xc7
_CS_HIGH();
}
void w25x20cl_rd_uid(uint8_t* uid)
{
_CS_LOW();
_SPI_TX(_CMD_RD_UID); // send command 0x4b
uint8_t cnt = 4; // 4 dummy bytes
while (cnt--) // receive dummy bytes
_SPI_RX();
cnt = 8; // 8 bytes UID
while (cnt--) // receive UID
uid[7 - cnt] = _SPI_RX();
_CS_HIGH();
}
int w25x20cl_mfrid_devid(void)
{
_CS_LOW();
_SPI_TX(_CMD_MFRID_DEVID); // send command 0x90
uint8_t cnt = 3; // 3 address bytes
while (cnt--) // send address bytes
_SPI_TX(0x00);
uint8_t w25x20cl_mfrid = _SPI_RX(); // receive mfrid
uint8_t w25x20cl_devid = _SPI_RX(); // receive devid
_CS_HIGH();
return ((w25x20cl_mfrid == _MFRID) && (w25x20cl_devid == _DEVID));
}

40
Firmware/w25x20cl.h Normal file
View file

@ -0,0 +1,40 @@
//w25x20cl.h
#ifndef _W25X20CL_H
#define _W25X20CL_H
#include <inttypes.h>
#include "config.h"
#define W25_STATUS_BUSY 0x01
#define W25_STATUS_WEL 0x02
#define W25_STATUS_BP0 0x04
#define W25_STATUS_BP1 0x08
#define W25_STATUS_TB 0x20
#define W25_STATUS_SRP 0x80
#if defined(__cplusplus)
extern "C" {
#endif //defined(__cplusplus)
extern int8_t w25x20cl_ini(void);
extern void w25x20cl_enable_wr(void);
extern void w25x20cl_disable_wr(void);
extern uint8_t w25x20cl_rd_status_reg(void);
extern void w25x20cl_wr_status_reg(uint8_t val);
extern void w25x20cl_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt);
extern void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt);
extern void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt);
extern void w25x20cl_sector_erase(uint32_t addr);
extern void w25x20cl_block32_erase(uint32_t addr);
extern void w25x20cl_block64_erase(uint32_t addr);
extern void w25x20cl_chip_erase(void);
extern void w25x20cl_rd_uid(uint8_t* uid);
#if defined(__cplusplus)
}
#endif //defined(__cplusplus)
#endif //_W25X20CL_H