У меня есть печатная плата с акселерометром LIS3DH, и у меня возникли проблемы с тем, чтобы заставить его работать последовательно.
Я написал драйвер I2C для него, где я устанавливал реестр управления Chip, чтобы соответствовать своей цели на этой печатной плате, но, похоже, не работает каждый раз после сброса мощности. У меня есть две проблемы: 1 - у меня есть функция инициирования с сбросом памяти программного обеспечения:
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;
}
Chip имеет линии I2C и PIN-подтягивания INT1, это не проблема HW, потому что, когда я управлял чипом полностью из пространства пользователя, используя ioctl , настройка регистрации и полярность сработали просто отлично. Я также не получаю никаких ошибок водителя во время написания новой значения полярности.
Может быть>
У меня есть печатная плата с акселерометром LIS3DH, и у меня возникли проблемы с тем, чтобы заставить его работать последовательно. Я написал драйвер I2C для него, где я устанавливал реестр управления Chip, чтобы соответствовать своей цели на этой печатной плате, но, похоже, не работает каждый раз после сброса мощности. У меня есть две проблемы: [b] 1 - у меня есть функция инициирования с сбросом памяти программного обеспечения: [/b] [code] 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; }
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; } [/code] Это шина I2C, обрабатываемая контроллером ЦП.[code]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; } [/code] Chip имеет линии I2C и PIN-подтягивания INT1, это не проблема HW, потому что, когда я управлял чипом полностью из пространства пользователя, используя ioctl , настройка регистрации и полярность сработали просто отлично. Я также не получаю никаких ошибок водителя во время написания новой значения полярности. Может быть>