Я написал драйвер I2C для него, где я устанавливал реестр управления Chip, чтобы соответствовать своей цели на этой печатной плате, но, похоже, не работает каждый раз после сброса мощности. У меня есть две проблемы:
1 - у меня есть функция инициирования с сбросом памяти программного обеспечения:
Код: Выделить всё
static int lis3dh_init_device(void) {
int ret;
u8 reg_value;
// Memory reset
ret = lis3dh_write_reg(LIS3DH_CTRL_REG5, 0x80);
if (ret) {
return ret;
}
// 100 ms register check timeout
int timeout = 100;
while (timeout > 0) {
mdelay(10);
timeout -= 20;
ret = lis3dh_read_reg(LIS3DH_CTRL_REG5, ®_value);
if (!ret && !(reg_value & 0x80)) {
break;
}
}
if (timeout dev, "Reset timeout");
return -ETIMEDOUT;
}
mdelay(20);
// ... registers setup
// Read int1 to clear pending interruption
lis3dh_read_reg(LIS3DH_INT1_SRC, ®_value);
mdelay(20);
return 0;
}
< /code>
Иногда я получаю эту ошибку тайм -аута и уходит драйвер. Разве 100 мс недостаточно для сброса памяти Чипа? Функции чтения-записи: < /p>
static int lis3dh_read_reg(u8 reg, u8 * value) {
struct i2c_msg msgs[2] = {
{
.addr = lis3dh.client->addr,
.flags = 0,
.len = 1,
.buf = ®,
},
{
.addr = lis3dh.client->addr,
.flags = I2C_M_RD,
.len = 1,
.buf = value,
},
};
int ret = i2c_transfer(lis3dh.client->adapter, msgs, 2);
if (ret != 2) {
dev_err(&lis3dh.client->dev, "I2C read failed (reg 0x%02x)\n", reg);
return (ret < 0) ? ret : -EIO;
}
return 0;
}
static int lis3dh_write_reg(u8 reg, u8 value) {
u8 buf[2] = {reg, value};
struct i2c_msg msg = {
.addr = lis3dh.client->addr,
.flags = 0,
.len = 2,
.buf = buf,
};
int ret = i2c_transfer(lis3dh.client->adapter, &msg, 1);
if (ret != 1) {
dev_err(&lis3dh.client->dev, "I2C write failed (reg 0x%02x)\n", reg);
return (ret < 0) ? ret : -EIO;
}
return 0;
}
Код: Выделить всё
static ssize_t active_low_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) {
unsigned long val;
u8 new_value;
int ret;
ret = kstrtoul(buf, 10, &val);
if (ret) {
return ret;
}
new_value = val ? LIS3DH_INT_POLARITY_ACTIVE_LOW : LIS3DH_INT_POLARITY_ACTIVE_HIGH;
ret = lis3dh_verify_reg(LIS3DH_CTRL_REG6, new_value);
if (ret != 0) {
dev_err(&lis3dh.client->dev, "Couldn't set LIS3DH INT1 Active Level");
return ret;
}
mdelay(50);
return count;
}
< /code>
где: < /p>
static int lis3dh_verify_reg(u8 reg, u8 expected_value) {
u8 read_value;
int ret;
int attempts = 5;
int delay_ms = 5;
while (attempts--) {
ret = lis3dh_read_reg(reg, &read_value);
if (ret) {
// progress the delay on error
mdelay(delay_ms);
delay_ms *= 2;
continue;
}
// Quit is the register value is correct
if (read_value == expected_value) {
return 0;
}
else {
ret = lis3dh_write_reg(reg, expected_value);
if (ret) {
mdelay(delay_ms);
delay_ms *= 2;
continue;
}
}
}
dev_err(&lis3dh.client->dev, "Failed to verify reg 0x%02x (expected 0x%02x, got 0x%02x)",
reg, expected_value, read_value);
return -EIO;
}
Может быть>
Подробнее здесь: https://stackoverflow.com/questions/796 ... ware-reset