i2c module stuff, firmware now correctly handles error conditions

This commit is contained in:
Triss 2021-07-14 03:04:40 +02:00
parent f163c38823
commit 16963bd39b
8 changed files with 69 additions and 21 deletions

View File

@ -4,7 +4,6 @@
#define DBOARD_HAS_UART
#define DBOARD_HAS_CMSISDAP
// TODO: rename to _SPI
#define DBOARD_HAS_SPI
#define DBOARD_HAS_I2C
#define DBOARD_HAS_TEMPSENSOR

View File

@ -87,17 +87,18 @@ epout.write(b'\x12') # get mode1 features
print("stat=%d"%stat)
print(res)
epout.write(b'\x20') # get mode1 name
print("echo time!")
epout.write(b'\x14\x00\x42') # I2C echo!
(stat, res) = rdresp(epin)
print("stat=%d"%stat)
print(res)
epout.write(b'\x21') # get mode1 version
epout.write(b'\x1f\x14\x00\x43')
(stat, res) = rdresp(epin)
print("stat=%d"%stat)
print(res)
epout.write(b'\x22') # get mode1 features
epout.write(b'\x14\x00\x44') # I2C echo!
(stat, res) = rdresp(epin)
print("stat=%d"%stat)
print(res)

View File

@ -453,17 +453,19 @@ static int dmj_probe(struct usb_interface *itf, const struct usb_device_id *usb_
goto out_free;
}
if (dmj->dmj_mode & DMJ_FEATURE_MODE1_SPI) {
if (dmj->dmj_m1feature & DMJ_FEATURE_MODE1_SPI) {
// TODO: add SPI MFD
}
if (dmj->dmj_mode & DMJ_FEATURE_MODE1_I2C) {
if (dmj->dmj_m1feature & DMJ_FEATURE_MODE1_I2C) {
ret = mfd_add_hotplug_devices(dev, dmj_mfd_i2c, ARRAY_SIZE(dmj_mfd_i2c));
if (ret) {
dev_err(dev, "failed to add MFD I2C devices\n");
goto out_free;
} else {
dev_warn(dev, "added i2c mfd\n");
}
}
if (dmj->dmj_mode & DMJ_FEATURE_MODE1_TEMPSENSOR) {
if (dmj->dmj_m1feature & DMJ_FEATURE_MODE1_TEMPSENSOR) {
// TODO: add tempsensor MFD
}
}

View File

@ -219,7 +219,7 @@ static int dmj_i2c_check_hw(struct platform_device *pdev)
len = sizeof(curmode);
ret = dmj_transfer(pdev, DMJ_CMD_CFG_GET_CUR_MODE,
DMJ_XFER_FLAGS_PARSE_RESP, NULL, 0, &curmode, &len);
ret = dmj_check_retval(ret, len, dev, "i2c test", true, sizeof(curmode), sizeof(curmode));
ret = dmj_check_retval(ret, len, dev, "i2c test 1", true, sizeof(curmode), sizeof(curmode));
if (ret < 0) return ret;
if (curmode != 0x1) {
dev_err(dev, "device must be in mode 1 for ICD to work, but it is in mode %d\n", curmode);
@ -229,7 +229,7 @@ static int dmj_i2c_check_hw(struct platform_device *pdev)
len = sizeof(m1ver);
ret = dmj_transfer(pdev, (1<<4) | DMJ_CMD_MODE_GET_VERSION,
DMJ_XFER_FLAGS_PARSE_RESP, NULL, 0, &m1ver, &len);
ret = dmj_check_retval(ret, len, dev, "i2c test", true, sizeof(m1ver), sizeof(m1ver));
ret = dmj_check_retval(ret, len, dev, "i2c test 2", true, sizeof(m1ver), sizeof(m1ver));
if (ret < 0) return ret;
if (le16_to_cpu(m1ver) > ver_max || le16_to_cpu(m1ver) < ver_min) {
dev_err(dev, "bad mode 1 version %04x on device, must be between %04x and %04x\n",
@ -240,7 +240,7 @@ static int dmj_i2c_check_hw(struct platform_device *pdev)
len = sizeof(m1feat);
ret = dmj_transfer(pdev, (1<<4) | DMJ_CMD_MODE_GET_FEATURES,
DMJ_XFER_FLAGS_PARSE_RESP, NULL, 0, &m1feat, &len);
ret = dmj_check_retval(ret, len, dev, "i2c test", true, sizeof(m1feat), sizeof(m1feat));
ret = dmj_check_retval(ret, len, dev, "i2c test 3", true, sizeof(m1feat), sizeof(m1feat));
if (ret < 0) return ret;
if (!(m1feat & DMJ_FEATURE_MODE1_I2C)) {
dev_err(dev, "device's mode 1 does not support I2C\n");
@ -286,6 +286,8 @@ static int dmj_i2c_probe(struct platform_device *pdev)
struct dmj_i2c *dmji;
struct device *dev = &pdev->dev;
dev_warn(dev, "i2c probe hi!\n");
ret = dmj_i2c_check_hw(pdev);
if (ret) return -ENODEV;

View File

@ -29,7 +29,7 @@
/*#define MODE_ENABLE_I2CTINYUSB*/
enum m_default_cmds {
mdef_cmd_spi = mode_cmd__specific | 0x10,
mdef_cmd_spi = mode_cmd__specific,
mdef_cmd_i2c,
mdef_cmd_tempsense
};
@ -137,25 +137,25 @@ static void handle_cmd_cb(uint8_t cmd) {
#ifdef DBOARD_HAS_SPI
sp_spi_bulk_cmd();
#else
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
vnd_cfg_write_str(cfg_resp_illcmd, "SPI not implemented on this device");
#endif
break;
case mdef_cmd_i2c:
#ifdef DBOARD_HAS_I2C
i2ctu_bulk_cmd();
#else
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
vnd_cfg_write_str(cfg_resp_illcmd, "I2C not implemented on this device");
#endif
break;
case mdef_cmd_tempsense:
#ifdef DBOARD_HAS_TEMPSENSOR
tempsense_bulk_cmd();
#else
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
vnd_cfg_write_str(cfg_resp_illcmd, "temperature sensor not implemented on this device");
#endif
break;
default:
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
vnd_cfg_write_strf(cfg_resp_illcmd, "unknown mode1 command %02x", cmd);
break;
}
}

View File

@ -276,7 +276,7 @@ void i2ctu_bulk_cmd(void) {
} break;
default:
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
vnd_cfg_write_str(cfg_resp_illcmd, "unknown I2C command");
break;
}
}

View File

@ -1,5 +1,7 @@
// vim: set et:
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <tusb.h>
@ -14,6 +16,8 @@ static uint8_t tx_buf[CFG_TUD_VENDOR_TX_BUFSIZE];
static uint32_t rxavail, rxpos, txpos;
static const int VND_N_CFG;
void vnd_cfg_init(void) {
rxavail = 0;
rxpos = 0;
@ -22,13 +26,13 @@ void vnd_cfg_init(void) {
uint8_t vnd_cfg_read_byte(void) {
while (rxavail <= 0) {
if (!tud_vendor_n_mounted(0) && !tud_vendor_n_available(0)) {
if (!tud_vendor_n_mounted(VND_N_CFG) || !tud_vendor_n_available(VND_N_CFG)) {
thread_yield();
continue;
}
rxpos = 0;
rxavail = tud_vendor_n_read(0, rx_buf, sizeof rx_buf);
rxavail = tud_vendor_n_read(VND_N_CFG, rx_buf, sizeof rx_buf);
if (rxavail == 0) thread_yield();
}
@ -39,13 +43,24 @@ uint8_t vnd_cfg_read_byte(void) {
return rv;
}
void vnd_cfg_drop_incoming(void) {
rxavail = 0;
rxpos = 0;
// empty tinyusb internal buffer
if (tud_vendor_n_mounted(VND_N_CFG)) {
while (tud_vendor_n_available(VND_N_CFG)) {
tud_vendor_n_read(VND_N_CFG, rx_buf, sizeof rx_buf);
}
}
}
void vnd_cfg_write_flush(void) {
// TODO: is this needed?
while (tud_vendor_n_write_available(0) < txpos) {
while (tud_vendor_n_write_available(VND_N_CFG) < txpos) {
thread_yield();
}
tud_vendor_n_write(0, tx_buf, txpos);
tud_vendor_n_write(VND_N_CFG, tx_buf, txpos);
txpos = 0;
}
void vnd_cfg_write_byte(uint8_t v) {
@ -56,7 +71,7 @@ void vnd_cfg_write_byte(uint8_t v) {
tx_buf[txpos] = v;
++txpos;
}
void vnd_cfg_write_resp(enum cfg_resp stat, uint32_t len, const void* data) {
void vnd_cfg_write_resp_no_drop(enum cfg_resp stat, uint32_t len, const void* data) {
if (len > 0x3fffff) {
printf("W: truncating response length from 0x%lx to 0x3fffff\n", len);
len = 0x3fffff;
@ -82,6 +97,23 @@ void vnd_cfg_write_resp(enum cfg_resp stat, uint32_t len, const void* data) {
vnd_cfg_write_flush();
}
void vnd_cfg_write_resp(enum cfg_resp stat, uint32_t len, const void* data) {
if (stat != cfg_resp_ok) vnd_cfg_drop_incoming();
vnd_cfg_write_resp_no_drop(stat, len, data);
}
void vnd_cfg_write_str(enum cfg_resp stat, const char* str) {
vnd_cfg_write_resp(stat, strlen(str), str);
}
void vnd_cfg_write_strf(enum cfg_resp stat, const char* fmt, ...) {
static char pbuf[64];
va_list args;
va_start(args, fmt);
vsnprintf(pbuf, sizeof pbuf, fmt, args);
va_end(args);
vnd_cfg_write_str(stat, pbuf);
}
void vnd_cfg_task(void) {
uint8_t cmd = vnd_cfg_read_byte();
@ -157,11 +189,18 @@ void vnd_cfg_task(void) {
#else /* CFG_TUD_VENDOR == 0 */
void vnd_cfg_init(void) { }
uint8_t vnd_cfg_read_byte(void) { return 0xff; }
void vnd_cfg_drop_incoming(void) { }
void vnd_cfg_write_flush(void) { }
void vnd_cfg_write_byte(uint8_t v) { (void)v; }
void vnd_cfg_write_resp(enum cfg_resp stat, uint16_t len, const void* data) {
(void)stat; (void)len; (void)data;
}
void vnd_cfg_write_str(enum cfg_resp stat, const char* str) {
(void)stat; (void)str;
}
void vnd_cfg_write_strf(enum cfg_resp stat, const char* fmt, ...) {
(void)stat; (void)str;
}
void vnd_cfg_task(void) { }
#endif /* CFG_TUD_VENDOR */

View File

@ -52,9 +52,14 @@ enum cfg_resp {
};
uint8_t vnd_cfg_read_byte (void);
void vnd_cfg_drop_incoming(void);
void vnd_cfg_write_flush(void);
void vnd_cfg_write_byte(uint8_t v);
void vnd_cfg_write_resp_no_drop(enum cfg_resp stat, uint32_t len, const void* data);
void vnd_cfg_write_resp(enum cfg_resp stat, uint32_t len, const void* data);
void vnd_cfg_write_str(enum cfg_resp stat, const char* str);
__attribute__((__format__(printf, 2, 3)))
void vnd_cfg_write_strf(enum cfg_resp stat, const char* fmt, ...);
#endif