Implement EEPROM and use it for saving the calibration
This commit is contained in:
		@@ -45,7 +45,7 @@ CFILES += rotary-encoder.c button.c
 | 
				
			|||||||
CFILES += ui/lcd.c ui/menu.c ui/gui.c
 | 
					CFILES += ui/lcd.c ui/menu.c ui/gui.c
 | 
				
			||||||
CFILES += fatfs/diskio.c fatfs/ff.c fatfs/ffsystem.c fatfs/ffunicode.c fatfs/shimatta_sdio_driver/shimatta_sdio.c
 | 
					CFILES += fatfs/diskio.c fatfs/ff.c fatfs/ffsystem.c fatfs/ffunicode.c fatfs/shimatta_sdio_driver/shimatta_sdio.c
 | 
				
			||||||
CFILES += pid-controller.c oven-driver.c
 | 
					CFILES += pid-controller.c oven-driver.c
 | 
				
			||||||
CFILES += settings/settings.c settings/settings-sd-card.c settings/spi-eeprom.c
 | 
					CFILES += settings/settings.c settings/settings-sd-card.c settings/spi-eeprom.c settings/settings-eeprom.c
 | 
				
			||||||
CFILES += stm-periph/crc-unit.c
 | 
					CFILES += stm-periph/crc-unit.c
 | 
				
			||||||
CFILES += safety/safety-adc.c safety/safety-controller.c safety/watchdog.c safety/fault.c safety/safety-memory.c safety/stack-check.c
 | 
					CFILES += safety/safety-adc.c safety/safety-controller.c safety/watchdog.c safety/fault.c safety/safety-memory.c safety/stack-check.c
 | 
				
			||||||
CFILES += hw-version-detect.c
 | 
					CFILES += hw-version-detect.c
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					/* Reflow Oven Controller
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* Copyright (C) 2020  Mario Hüttel <mario.huettel@gmx.net>
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* This file is part of the Reflow Oven Controller Project.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* The reflow oven controller is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					* it under the terms of the GNU General Public License version 2 as
 | 
				
			||||||
 | 
					* published by the Free Software Foundation.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					* but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					* GNU General Public License for more details.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					* along with the reflow oven controller project.
 | 
				
			||||||
 | 
					* If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SETTINGS_SETTINGS_EEPROM_H__
 | 
				
			||||||
 | 
					#define __SETTINGS_SETTINGS_EEPROM_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool settings_eeprom_detect_and_prepare(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int settings_eeprom_save_calibration(float sens, float offset, bool active);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int settings_eeprom_load_calibration(float *sens, float *offset, bool *active);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* __SETTINGS_SETTINGS_EEPROM_H__ */
 | 
				
			||||||
@@ -53,4 +53,6 @@ int settings_load_calibration(float *sens_dev, float *offset);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
enum settings_load_result settings_load_pid_oven_parameters(struct oven_pid_settings *settings);
 | 
					enum settings_load_result settings_load_pid_oven_parameters(struct oven_pid_settings *settings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void settings_setup(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* __SETTINGS_SETTINGS_H__ */
 | 
					#endif /* __SETTINGS_SETTINGS_H__ */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,8 @@
 | 
				
			|||||||
#define __SETTINGS_SPI_EEPROM_H__
 | 
					#define __SETTINGS_SPI_EEPROM_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int spi_eeprom_init();
 | 
					int spi_eeprom_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -29,8 +31,12 @@ void spi_eeprom_deinit();
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int spi_eeprom_read(uint32_t addr, uint8_t *rx_buff, uint32_t count);
 | 
					int spi_eeprom_read(uint32_t addr, uint8_t *rx_buff, uint32_t count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool spi_eeprom_write_in_progress(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int spi_eeprom_write(uint32_t addr, const uint8_t *data, uint32_t count);
 | 
					int spi_eeprom_write(uint32_t addr, const uint8_t *data, uint32_t count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint8_t spi_eeprom_read_status_reg(void);
 | 
					uint8_t spi_eeprom_read_status_reg(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool spi_eeprom_check_connected(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* __SETTINGS_SPI_EEPROM_H__ */
 | 
					#endif /* __SETTINGS_SPI_EEPROM_H__ */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,6 +46,7 @@
 | 
				
			|||||||
#include <reflow-controller/safety/safety-memory.h>
 | 
					#include <reflow-controller/safety/safety-memory.h>
 | 
				
			||||||
#include <reflow-controller/safety/fault.h>
 | 
					#include <reflow-controller/safety/fault.h>
 | 
				
			||||||
#include <reflow-controller/updater/updater.h>
 | 
					#include <reflow-controller/updater/updater.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <reflow-controller/settings/spi-eeprom.h>
 | 
					#include <reflow-controller/settings/spi-eeprom.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void setup_nvic_priorities(void)
 | 
					static void setup_nvic_priorities(void)
 | 
				
			||||||
@@ -179,7 +180,7 @@ static inline void setup_system(void)
 | 
				
			|||||||
	loudspeaker_setup();
 | 
						loudspeaker_setup();
 | 
				
			||||||
	gui_init();
 | 
						gui_init();
 | 
				
			||||||
	uart_gpio_config();
 | 
						uart_gpio_config();
 | 
				
			||||||
	spi_eeprom_init();
 | 
						settings_setup();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	handle_boot_status();
 | 
						handle_boot_status();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -210,8 +211,15 @@ int main(void)
 | 
				
			|||||||
	shellmatta_handle_t shell_handle;
 | 
						shellmatta_handle_t shell_handle;
 | 
				
			||||||
	int menu_wait_request;
 | 
						int menu_wait_request;
 | 
				
			||||||
	uint64_t quarter_sec_timestamp = 0ULL;
 | 
						uint64_t quarter_sec_timestamp = 0ULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setup_system();
 | 
						setup_system();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Try load the calibration. This will only succeed if there's an EEPROM */
 | 
				
			||||||
 | 
						status = settings_load_calibration(&sens, &offset);
 | 
				
			||||||
 | 
						if (!status) {
 | 
				
			||||||
 | 
							adc_pt1000_set_resistance_calibration(offset, sens, true);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	shell_handle = shell_init(write_shell_callback);
 | 
						shell_handle = shell_init(write_shell_callback);
 | 
				
			||||||
	shell_print_motd(shell_handle);
 | 
						shell_print_motd(shell_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										140
									
								
								stm-firmware/settings/settings-eeprom.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								stm-firmware/settings/settings-eeprom.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,140 @@
 | 
				
			|||||||
 | 
					/* Reflow Oven Controller
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* Copyright (C) 2020  Mario Hüttel <mario.huettel@gmx.net>
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* This file is part of the Reflow Oven Controller Project.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* The reflow oven controller is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					* it under the terms of the GNU General Public License version 2 as
 | 
				
			||||||
 | 
					* published by the Free Software Foundation.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					* but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					* GNU General Public License for more details.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					* along with the reflow oven controller project.
 | 
				
			||||||
 | 
					* If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <reflow-controller/settings/settings-eeprom.h>
 | 
				
			||||||
 | 
					#include <reflow-controller/settings/spi-eeprom.h>
 | 
				
			||||||
 | 
					#include <stm-periph/crc-unit.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EEPROM_HEADER_MAGIC 0xA5
 | 
				
			||||||
 | 
					#define EEPROM_HEADER_COMP_VER 0xFF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const uint8_t expected_header[2] = {EEPROM_HEADER_MAGIC, EEPROM_HEADER_COMP_VER};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EEPROM_CALIBRATION_BASE_ADDR 0x2
 | 
				
			||||||
 | 
					struct eeprom_calibration_settings {
 | 
				
			||||||
 | 
						uint32_t active;
 | 
				
			||||||
 | 
						float offset;
 | 
				
			||||||
 | 
						float sens_dev;
 | 
				
			||||||
 | 
						uint32_t crc;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool check_eeprom_header(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t header[2] = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Try to read the magic header and the compatible version */
 | 
				
			||||||
 | 
						spi_eeprom_read(0x0, header, 2);
 | 
				
			||||||
 | 
						if (memcmp(header, expected_header, 2))
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void settings_eeprom_zero()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						settings_eeprom_save_calibration(0.0f, 0.0f, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool settings_eeprom_detect_and_prepare(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bool eeprom_ready = false;;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						crc_unit_init();
 | 
				
			||||||
 | 
						res = spi_eeprom_init();
 | 
				
			||||||
 | 
						if (res)
 | 
				
			||||||
 | 
							goto ret_deinit_crc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!spi_eeprom_check_connected())
 | 
				
			||||||
 | 
							goto ret_deinit_crc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (check_eeprom_header() == false) {
 | 
				
			||||||
 | 
							/* Try to write a new header and check it again */
 | 
				
			||||||
 | 
							spi_eeprom_write(0, expected_header, sizeof(expected_header));
 | 
				
			||||||
 | 
							while (spi_eeprom_write_in_progress());
 | 
				
			||||||
 | 
							if (check_eeprom_header() == false) {
 | 
				
			||||||
 | 
								goto ret_deinit_crc;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								/* Sucessfully written new header
 | 
				
			||||||
 | 
								 * Zero out the rest of the settings
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								settings_eeprom_zero();
 | 
				
			||||||
 | 
								eeprom_ready = true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							eeprom_ready = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						goto exit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ret_deinit_crc:
 | 
				
			||||||
 | 
						crc_unit_deinit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exit:
 | 
				
			||||||
 | 
						return eeprom_ready;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int settings_eeprom_save_calibration(float sens, float offset, bool active)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct eeprom_calibration_settings sett;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sett.active = (active ? 0xAABBCCDD : 0);
 | 
				
			||||||
 | 
						sett.offset = offset;
 | 
				
			||||||
 | 
						sett.sens_dev = sens;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						crc_unit_reset();
 | 
				
			||||||
 | 
						crc_unit_input_array((const uint32_t *)&sett, (sizeof(sett) / 4)-1);
 | 
				
			||||||
 | 
						sett.crc = crc_unit_get_crc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						res = spi_eeprom_write(EEPROM_CALIBRATION_BASE_ADDR, (uint8_t *)&sett, sizeof(sett));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (res)
 | 
				
			||||||
 | 
							return -2;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int settings_eeprom_load_calibration(float *sens, float *offset, bool *active)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct eeprom_calibration_settings sett;
 | 
				
			||||||
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						res = spi_eeprom_read(EEPROM_CALIBRATION_BASE_ADDR, (uint8_t *)&sett, sizeof(sett));
 | 
				
			||||||
 | 
						if (res)
 | 
				
			||||||
 | 
							return -2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						crc_unit_reset();
 | 
				
			||||||
 | 
						crc_unit_input_array((const uint32_t *)&sett, sizeof(sett) / 4 - 1);
 | 
				
			||||||
 | 
						if (crc_unit_get_crc() == sett.crc) {
 | 
				
			||||||
 | 
							if (sens)
 | 
				
			||||||
 | 
								*sens = sett.sens_dev;
 | 
				
			||||||
 | 
							if (offset)
 | 
				
			||||||
 | 
								*offset = sett.offset;
 | 
				
			||||||
 | 
							if (active)
 | 
				
			||||||
 | 
								*active = (sett.active ? true : false);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -20,19 +20,47 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <reflow-controller/settings/settings.h>
 | 
					#include <reflow-controller/settings/settings.h>
 | 
				
			||||||
#include <reflow-controller/settings/settings-sd-card.h>
 | 
					#include <reflow-controller/settings/settings-sd-card.h>
 | 
				
			||||||
 | 
					#include <reflow-controller/settings/settings-eeprom.h>
 | 
				
			||||||
 | 
					#include <reflow-controller/hw-version-detect.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool settings_use_eeprom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int settings_save_calibration(float sens_deviation, float offset, bool active)
 | 
					int settings_save_calibration(float sens_deviation, float offset, bool active)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* There is no other configuration location besides the SD card (yet) */
 | 
						if (settings_use_eeprom)
 | 
				
			||||||
 | 
							return settings_eeprom_save_calibration(sens_deviation, offset, active);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
		return sd_card_settings_save_calibration(sens_deviation, offset, active);
 | 
							return sd_card_settings_save_calibration(sens_deviation, offset, active);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int settings_load_calibration(float *sens_dev, float *offset)
 | 
					int settings_load_calibration(float *sens_dev, float *offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return sd_card_settings_try_load_calibration(sens_dev, offset);
 | 
						bool active;
 | 
				
			||||||
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (settings_use_eeprom) {
 | 
				
			||||||
 | 
							res =settings_eeprom_load_calibration(sens_dev, offset, &active);
 | 
				
			||||||
 | 
							if (!res && !active)
 | 
				
			||||||
 | 
								res = -1;
 | 
				
			||||||
 | 
						} else  {
 | 
				
			||||||
 | 
							res = -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (res)
 | 
				
			||||||
 | 
							res = sd_card_settings_try_load_calibration(sens_dev, offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum settings_load_result settings_load_pid_oven_parameters(struct oven_pid_settings *settings)
 | 
					enum settings_load_result settings_load_pid_oven_parameters(struct oven_pid_settings *settings)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return sd_card_settings_load_pid_oven_parameters(settings);
 | 
						return sd_card_settings_load_pid_oven_parameters(settings);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void settings_setup(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (get_pcb_hardware_version() >= HW_REV_V1_3)
 | 
				
			||||||
 | 
							settings_use_eeprom = settings_eeprom_detect_and_prepare();
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							settings_use_eeprom = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,10 +23,23 @@
 | 
				
			|||||||
#include <reflow-controller/periph-config/spi-eeprom-hwcfg.h>
 | 
					#include <reflow-controller/periph-config/spi-eeprom-hwcfg.h>
 | 
				
			||||||
#include <stm-periph/rcc-manager.h>
 | 
					#include <stm-periph/rcc-manager.h>
 | 
				
			||||||
#include <stm-periph/stm32-gpio-macros.h>
 | 
					#include <stm-periph/stm32-gpio-macros.h>
 | 
				
			||||||
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define EEPROM_SIZE 0x200
 | 
					#define EEPROM_SIZE 0x200
 | 
				
			||||||
#define EEPROM_PAGE_SIZE 16
 | 
					#define EEPROM_PAGE_SIZE 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EEPROM_STATUS_REG_WIP (0x1U)
 | 
				
			||||||
 | 
					#define EEPROM_STATUS_REG_WEL (0x1U << 1)
 | 
				
			||||||
 | 
					#define EEPROM_STATUS_REG_BP0 (0x1U << 2)
 | 
				
			||||||
 | 
					#define EEPROM_STATUS_REG_BP1 (0x1U << 3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EEPROM_CMD_READ_STATUS 0x05
 | 
				
			||||||
 | 
					#define EEPROM_CMD_WRITE_STATUS 0x01
 | 
				
			||||||
 | 
					#define EEPROM_CMD_READ_DATA 0x3
 | 
				
			||||||
 | 
					#define EEPROM_CMD_WRITE_DATA 0x2
 | 
				
			||||||
 | 
					#define EEPROM_CMD_WREN 0x6
 | 
				
			||||||
 | 
					#define EEPROM_CMD_WRDI 0x4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static stm_spi_handle eeprom_spi_handle;
 | 
					static stm_spi_handle eeprom_spi_handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void eeprom_cs_activate(void)
 | 
					static void eeprom_cs_activate(void)
 | 
				
			||||||
@@ -63,7 +76,7 @@ int spi_eeprom_init()
 | 
				
			|||||||
	settings.cs_deactivate = eeprom_cs_deactivate;
 | 
						settings.cs_deactivate = eeprom_cs_deactivate;
 | 
				
			||||||
	settings.master = true;
 | 
						settings.master = true;
 | 
				
			||||||
	settings.msb_first = true;
 | 
						settings.msb_first = true;
 | 
				
			||||||
	settings.prescaler = SPI_PRSC_DIV64;
 | 
						settings.prescaler = SPI_PRSC_DIV16;
 | 
				
			||||||
	eeprom_spi_handle = spi_init(&spi_dev, SPI1, &settings);
 | 
						eeprom_spi_handle = spi_init(&spi_dev, SPI1, &settings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (eeprom_spi_handle)
 | 
						if (eeprom_spi_handle)
 | 
				
			||||||
@@ -91,9 +104,24 @@ uint8_t spi_eeprom_read_status_reg(void)
 | 
				
			|||||||
	return buff[1];
 | 
						return buff[1];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void spi_eeprom_set_write_enable_latch(bool status)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t cmd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (status)
 | 
				
			||||||
 | 
							cmd = EEPROM_CMD_WREN;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							cmd = EEPROM_CMD_WRDI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						(void)spi_transfer(eeprom_spi_handle, &cmd, NULL, 1, true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int spi_eeprom_read(uint32_t addr, uint8_t *rx_buff, uint32_t count)
 | 
					int spi_eeprom_read(uint32_t addr, uint8_t *rx_buff, uint32_t count)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret = 0;
 | 
						int ret = 0;
 | 
				
			||||||
 | 
						int retry = 250;
 | 
				
			||||||
 | 
						uint8_t status_reg;
 | 
				
			||||||
 | 
						uint8_t cmd[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!rx_buff || !count)
 | 
						if (!rx_buff || !count)
 | 
				
			||||||
		return -1000;
 | 
							return -1000;
 | 
				
			||||||
@@ -101,15 +129,100 @@ int spi_eeprom_read(uint32_t addr, uint8_t *rx_buff, uint32_t count)
 | 
				
			|||||||
	if (addr >= EEPROM_SIZE)
 | 
						if (addr >= EEPROM_SIZE)
 | 
				
			||||||
		return -1001;
 | 
							return -1001;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							status_reg = spi_eeprom_read_status_reg();
 | 
				
			||||||
 | 
						} while ((status_reg & EEPROM_STATUS_REG_WIP) && retry--);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (status_reg & EEPROM_STATUS_REG_WIP)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd[0] = EEPROM_CMD_READ_DATA;
 | 
				
			||||||
 | 
						if (addr & (1<<8))
 | 
				
			||||||
 | 
							cmd[0] |= (1U<<3);
 | 
				
			||||||
 | 
						cmd[1] = (uint8_t)(addr & 0xFF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	eeprom_cs_activate();
 | 
						eeprom_cs_activate();
 | 
				
			||||||
 | 
						spi_transfer(eeprom_spi_handle, cmd, NULL, 2, false);
 | 
				
			||||||
 | 
						spi_transfer(eeprom_spi_handle, NULL, rx_buff, count, false);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	eeprom_cs_deactivate();
 | 
						eeprom_cs_deactivate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int spi_eeprom_write(uint32_t addr, const uint8_t *data, uint32_t count);
 | 
					bool spi_eeprom_write_in_progress(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t status_reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						status_reg = spi_eeprom_read_status_reg();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (status_reg & EEPROM_STATUS_REG_WIP)
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void spi_eeprom_do_write_page(uint32_t addr, const uint8_t *data, uint8_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t cmd[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Wait for the previous write to finish */
 | 
				
			||||||
 | 
						while (spi_eeprom_write_in_progress());
 | 
				
			||||||
 | 
						/* Set the write enable latch */
 | 
				
			||||||
 | 
						spi_eeprom_set_write_enable_latch(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd[0] = EEPROM_CMD_WRITE_DATA | ((addr & (1<<8)) ? (1<<4) : 0);
 | 
				
			||||||
 | 
						cmd[1] = (uint8_t)(addr & 0xFF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						eeprom_cs_activate();
 | 
				
			||||||
 | 
						spi_transfer(eeprom_spi_handle, cmd, NULL, 2, false);
 | 
				
			||||||
 | 
						spi_transfer(eeprom_spi_handle, data, NULL, len, false);
 | 
				
			||||||
 | 
						eeprom_cs_deactivate();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int spi_eeprom_write(uint32_t addr, const uint8_t *data, uint32_t count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const uint8_t *ptr = data;
 | 
				
			||||||
 | 
						uint32_t transfer_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!data || !count)
 | 
				
			||||||
 | 
							return -1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (addr >= EEPROM_SIZE)
 | 
				
			||||||
 | 
							return -1001;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (count > 0) {
 | 
				
			||||||
 | 
							/* Calculate size for current page transfer */
 | 
				
			||||||
 | 
							transfer_len = EEPROM_PAGE_SIZE - (addr % EEPROM_PAGE_SIZE);
 | 
				
			||||||
 | 
							if (transfer_len > count)
 | 
				
			||||||
 | 
								transfer_len = count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spi_eeprom_do_write_page(addr, ptr, transfer_len);
 | 
				
			||||||
 | 
							count -= transfer_len;
 | 
				
			||||||
 | 
							addr += transfer_len;
 | 
				
			||||||
 | 
							ptr += transfer_len;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool spi_eeprom_check_connected(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t status_reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Try to set write enable latch */
 | 
				
			||||||
 | 
						spi_eeprom_set_write_enable_latch(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Read back status register */
 | 
				
			||||||
 | 
						status_reg = spi_eeprom_read_status_reg();
 | 
				
			||||||
 | 
						if (!(status_reg & EEPROM_STATUS_REG_WEL))
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Clear the latch */
 | 
				
			||||||
 | 
						spi_eeprom_set_write_enable_latch(false);
 | 
				
			||||||
 | 
						/* Read back status register */
 | 
				
			||||||
 | 
						status_reg = spi_eeprom_read_status_reg();
 | 
				
			||||||
 | 
						if ((status_reg & EEPROM_STATUS_REG_WEL))
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user