Alexander Efimov
5 years ago
10 changed files with 18 additions and 199 deletions
@ -1,189 +0,0 @@ |
|||
/**
|
|||
|
|||
AT24C16, 16K SERIAL EEPROM: |
|||
Internally organized with 128 pages of 16 bytes each (2048 bytes) |
|||
|
|||
16K requires an 11-bit data word address for random word addressing. |
|||
|
|||
The 16K does not use any device address bits but instead the 3 bits are used for mem- |
|||
ory page addressing. These page addressing bits on the 4K, 8K and 16K devices |
|||
should be considered the most significant bits of the data word address which follows. |
|||
The A0, A1 and A2 pins are no connect. |
|||
|
|||
*/ |
|||
#include "../../inc/MarlinConfig.h" |
|||
|
|||
#if ENABLED(I2C_EEPROM_AT24C16) |
|||
|
|||
#include "../HAL.h" |
|||
#include "../../module/mks_wifi/small_cmsis.h" |
|||
#include "../../module/mks_wifi/dwt.h" |
|||
|
|||
#define DEV_ADDR 0xA0 |
|||
#define FSMC_DISABLE RCC->AHBENR &= ~RCC_AHBENR_FSMCEN //Конфликт на ноге FSMC_NADV с I2C. На время передачи приходится отключать FSMC
|
|||
#define FSMC_RESTORE RCC->AHBENR |= RCC_AHBENR_FSMCEN; |
|||
|
|||
#define I2C_TIMEOUT 2000 //таймаут на ожидание опереций I2C.
|
|||
|
|||
#define CHECK_TIMEOUT do{if(dwt_get_timeout() == 0){ERROR("Timeout");return 0;}}while(0) |
|||
|
|||
static bool waitSRBitSet(uint32_t Bit); |
|||
static uint8_t i2c_write(const uint8_t hw_adr, uint8_t *data, uint32_t len); |
|||
static uint8_t i2c_read(const uint8_t hw_adr, uint16_t addr, uint8_t *data, uint32_t len); |
|||
|
|||
|
|||
void eeprom_hw_init(void){ |
|||
/*
|
|||
PB6 SCL Alternate function open drain |
|||
PB7 SDA Alternate function open drain |
|||
*/ |
|||
dwt_init(); |
|||
|
|||
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN|RCC_APB2ENR_AFIOEN; |
|||
PORTB->CRL |= (GPIO_CRL_MODE6|GPIO_CRL_MODE7|GPIO_CRL_CNF6|GPIO_CRL_CNF7); |
|||
|
|||
AFIO->MAPR2 |= AFIO_MAPR2_FSMC_NADV_REMAP; //Remap по факту не работает, бит не устанавливается.
|
|||
RCC->APB1ENR|= RCC_APB1ENR_I2C1EN; |
|||
|
|||
I2C1->CR1 = I2C_CR1_SWRST; |
|||
I2C1->CR1 = 0; |
|||
|
|||
//Тактовая 72Mhz, PCLK 36Mhz
|
|||
I2C1->CCR = (180 << I2C_CCR_CCR_Pos); |
|||
I2C1->CR2 = (36 << I2C_CR2_FREQ_Pos); |
|||
I2C1->TRISE = 37; |
|||
I2C1->CR1 = I2C_CR1_PE; |
|||
} |
|||
|
|||
void eeprom_write_byte(uint16_t *pos, unsigned char value) { |
|||
uint8_t data[2]; |
|||
|
|||
//DEBUG("EEPROM write to pos: %d val %0X",pos,value);
|
|||
FSMC_DISABLE; |
|||
|
|||
data[0]=(uint8_t)((unsigned)pos % 256); |
|||
data[1]=(uint8_t)(value); |
|||
|
|||
if(!i2c_write((DEV_ADDR+(uint8_t)(((unsigned)pos/256)<<1)),data,2)){ |
|||
ERROR("write failed"); |
|||
} |
|||
safe_delay(20); //Задержка на время пока eeprom пишет.
|
|||
FSMC_RESTORE; |
|||
} |
|||
|
|||
uint8_t eeprom_read_byte(uint16_t *pos) { |
|||
uint8_t data; |
|||
|
|||
//DEBUG("EEPROM read from pos: %d",pos);
|
|||
FSMC_DISABLE; |
|||
|
|||
if(!i2c_read(DEV_ADDR, (uint16_t)((unsigned)pos), &data, 1)){ |
|||
ERROR("read failed"); |
|||
data=0; |
|||
} |
|||
|
|||
safe_delay(1); //небольшая пауза перед включением FSMC, чтобы состояние STOP успело выставиться на линии.
|
|||
FSMC_RESTORE; |
|||
return data; |
|||
} |
|||
|
|||
|
|||
static uint8_t i2c_write(const uint8_t hw_adr, uint8_t *data, uint32_t len){ |
|||
|
|||
DEBUG("i2c write at %d val %0X",data[0],data[1]); |
|||
|
|||
dwt_settimeout(I2C_TIMEOUT); |
|||
DEBUG("Wait busy"); |
|||
while(I2C1->SR2 & I2C_SR2_BUSY) {CHECK_TIMEOUT;}; |
|||
|
|||
|
|||
I2C1->CR1 = I2C_CR1_PE | I2C_CR1_START; |
|||
dwt_settimeout(I2C_TIMEOUT); |
|||
DEBUG("Wait SB"); |
|||
while(!(I2C1->SR1 & I2C_SR1_SB)) {CHECK_TIMEOUT;}; |
|||
I2C1->DR = (hw_adr & 0xFE); |
|||
|
|||
if(!waitSRBitSet(I2C_SR1_ADDR)) return false; |
|||
(void)I2C1->SR2; |
|||
|
|||
while(len--){ |
|||
if(!waitSRBitSet(I2C_SR1_TXE)) return false; |
|||
I2C1->DR = *data++; |
|||
} |
|||
|
|||
dwt_settimeout(I2C_TIMEOUT); |
|||
DEBUG("Wait BTF"); |
|||
while(!((I2C1->SR1 & I2C_SR1_TXE) && (I2C1->SR1 & I2C_SR1_BTF))) {CHECK_TIMEOUT;}; |
|||
I2C1->CR1 = I2C_CR1_PE | I2C_CR1_STOP; |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
static uint8_t i2c_read(const uint8_t hw_adr, uint16_t addr, uint8_t *data, uint32_t len){ |
|||
|
|||
dwt_settimeout(I2C_TIMEOUT); |
|||
DEBUG("Wait busy"); |
|||
while(I2C1->SR2 & I2C_SR2_BUSY) {CHECK_TIMEOUT;}; |
|||
|
|||
//Запись адреса
|
|||
I2C1->CR1 = I2C_CR1_PE | I2C_CR1_START; |
|||
|
|||
dwt_settimeout(I2C_TIMEOUT); |
|||
DEBUG("Wait SB"); |
|||
while(!(I2C1->SR1 & I2C_SR1_SB)) {CHECK_TIMEOUT;}; //Условие старт
|
|||
|
|||
|
|||
I2C1->DR = ((hw_adr & 0xFE) + ((addr/256) << 1)); |
|||
if(!waitSRBitSet(I2C_SR1_ADDR)) return false; //i2c адрес отправлен
|
|||
I2C1->SR2; |
|||
|
|||
if(!waitSRBitSet(I2C_SR1_TXE)) return false; |
|||
I2C1->DR = addr%256; //адрес в памяти отправлен
|
|||
|
|||
dwt_settimeout(I2C_TIMEOUT); |
|||
DEBUG("Wait BTF"); |
|||
while(!((I2C1->SR1 & I2C_SR1_TXE) && (I2C1->SR1 & I2C_SR1_BTF))) {CHECK_TIMEOUT;}; |
|||
|
|||
//Чтение
|
|||
I2C1->CR1 = I2C_CR1_PE | I2C_CR1_START | I2C_CR1_ACK; |
|||
|
|||
dwt_settimeout(I2C_TIMEOUT); |
|||
DEBUG("Wait SB"); |
|||
while(!(I2C1->SR1 & I2C_SR1_SB)) {CHECK_TIMEOUT;}; |
|||
I2C1->DR = hw_adr|1; |
|||
|
|||
if(!waitSRBitSet(I2C_SR1_ADDR)) return false; |
|||
I2C1->SR2; |
|||
I2C1->CR1 = I2C_CR1_PE | I2C_CR1_STOP; |
|||
|
|||
if(!waitSRBitSet(I2C_SR1_RXNE)) return false; |
|||
*data = I2C1->DR; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
static bool waitSRBitSet(uint32_t Bit){ |
|||
uint32_t sr; |
|||
|
|||
dwt_settimeout(I2C_TIMEOUT); |
|||
do{ |
|||
sr = I2C1->SR1; |
|||
if(sr & ( I2C_SR1_AF | I2C_SR1_ARLO | I2C_SR1_BERR)){ |
|||
I2C1->CR1 = I2C_CR1_PE | I2C_CR1_STOP; |
|||
I2C1->SR1 = 0; |
|||
ERROR("I2C Error flag %0X",sr); |
|||
return false; |
|||
} |
|||
if(dwt_get_timeout() == 0){ |
|||
ERROR("Timeout %0X",Bit); |
|||
return false; |
|||
} |
|||
|
|||
}while(!(sr & Bit)); |
|||
|
|||
return true; |
|||
}; |
|||
|
|||
|
|||
#endif // I2C_EEPROM
|
Loading…
Reference in new issue