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_UART
#define DBOARD_HAS_CMSISDAP #define DBOARD_HAS_CMSISDAP
// TODO: rename to _SPI
#define DBOARD_HAS_SPI #define DBOARD_HAS_SPI
#define DBOARD_HAS_I2C #define DBOARD_HAS_I2C
#define DBOARD_HAS_TEMPSENSOR #define DBOARD_HAS_TEMPSENSOR

View File

@ -87,17 +87,18 @@ epout.write(b'\x12') # get mode1 features
print("stat=%d"%stat) print("stat=%d"%stat)
print(res) print(res)
epout.write(b'\x20') # get mode1 name print("echo time!")
epout.write(b'\x14\x00\x42') # I2C echo!
(stat, res) = rdresp(epin) (stat, res) = rdresp(epin)
print("stat=%d"%stat) print("stat=%d"%stat)
print(res) print(res)
epout.write(b'\x21') # get mode1 version epout.write(b'\x1f\x14\x00\x43')
(stat, res) = rdresp(epin) (stat, res) = rdresp(epin)
print("stat=%d"%stat) print("stat=%d"%stat)
print(res) print(res)
epout.write(b'\x22') # get mode1 features epout.write(b'\x14\x00\x44') # I2C echo!
(stat, res) = rdresp(epin) (stat, res) = rdresp(epin)
print("stat=%d"%stat) print("stat=%d"%stat)
print(res) 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; goto out_free;
} }
if (dmj->dmj_mode & DMJ_FEATURE_MODE1_SPI) { if (dmj->dmj_m1feature & DMJ_FEATURE_MODE1_SPI) {
// TODO: add SPI MFD // 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)); ret = mfd_add_hotplug_devices(dev, dmj_mfd_i2c, ARRAY_SIZE(dmj_mfd_i2c));
if (ret) { if (ret) {
dev_err(dev, "failed to add MFD I2C devices\n"); dev_err(dev, "failed to add MFD I2C devices\n");
goto out_free; 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 // TODO: add tempsensor MFD
} }
} }

View File

@ -219,7 +219,7 @@ static int dmj_i2c_check_hw(struct platform_device *pdev)
len = sizeof(curmode); len = sizeof(curmode);
ret = dmj_transfer(pdev, DMJ_CMD_CFG_GET_CUR_MODE, ret = dmj_transfer(pdev, DMJ_CMD_CFG_GET_CUR_MODE,
DMJ_XFER_FLAGS_PARSE_RESP, NULL, 0, &curmode, &len); 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 (ret < 0) return ret;
if (curmode != 0x1) { if (curmode != 0x1) {
dev_err(dev, "device must be in mode 1 for ICD to work, but it is in mode %d\n", curmode); 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); len = sizeof(m1ver);
ret = dmj_transfer(pdev, (1<<4) | DMJ_CMD_MODE_GET_VERSION, ret = dmj_transfer(pdev, (1<<4) | DMJ_CMD_MODE_GET_VERSION,
DMJ_XFER_FLAGS_PARSE_RESP, NULL, 0, &m1ver, &len); 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 (ret < 0) return ret;
if (le16_to_cpu(m1ver) > ver_max || le16_to_cpu(m1ver) < ver_min) { 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", 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); len = sizeof(m1feat);
ret = dmj_transfer(pdev, (1<<4) | DMJ_CMD_MODE_GET_FEATURES, ret = dmj_transfer(pdev, (1<<4) | DMJ_CMD_MODE_GET_FEATURES,
DMJ_XFER_FLAGS_PARSE_RESP, NULL, 0, &m1feat, &len); 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 (ret < 0) return ret;
if (!(m1feat & DMJ_FEATURE_MODE1_I2C)) { if (!(m1feat & DMJ_FEATURE_MODE1_I2C)) {
dev_err(dev, "device's mode 1 does not support I2C\n"); 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 dmj_i2c *dmji;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
dev_warn(dev, "i2c probe hi!\n");
ret = dmj_i2c_check_hw(pdev); ret = dmj_i2c_check_hw(pdev);
if (ret) return -ENODEV; if (ret) return -ENODEV;

View File

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

View File

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

View File

@ -1,5 +1,7 @@
// vim: set et: // vim: set et:
#include <stdarg.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include <tusb.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 uint32_t rxavail, rxpos, txpos;
static const int VND_N_CFG;
void vnd_cfg_init(void) { void vnd_cfg_init(void) {
rxavail = 0; rxavail = 0;
rxpos = 0; rxpos = 0;
@ -22,13 +26,13 @@ void vnd_cfg_init(void) {
uint8_t vnd_cfg_read_byte(void) { uint8_t vnd_cfg_read_byte(void) {
while (rxavail <= 0) { 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(); thread_yield();
continue; continue;
} }
rxpos = 0; 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(); if (rxavail == 0) thread_yield();
} }
@ -39,13 +43,24 @@ uint8_t vnd_cfg_read_byte(void) {
return rv; 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) { void vnd_cfg_write_flush(void) {
// TODO: is this needed? // TODO: is this needed?
while (tud_vendor_n_write_available(0) < txpos) { while (tud_vendor_n_write_available(VND_N_CFG) < txpos) {
thread_yield(); thread_yield();
} }
tud_vendor_n_write(0, tx_buf, txpos); tud_vendor_n_write(VND_N_CFG, tx_buf, txpos);
txpos = 0; txpos = 0;
} }
void vnd_cfg_write_byte(uint8_t v) { void vnd_cfg_write_byte(uint8_t v) {
@ -56,7 +71,7 @@ void vnd_cfg_write_byte(uint8_t v) {
tx_buf[txpos] = v; tx_buf[txpos] = v;
++txpos; ++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) { if (len > 0x3fffff) {
printf("W: truncating response length from 0x%lx to 0x3fffff\n", len); printf("W: truncating response length from 0x%lx to 0x3fffff\n", len);
len = 0x3fffff; 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(); 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) { void vnd_cfg_task(void) {
uint8_t cmd = vnd_cfg_read_byte(); uint8_t cmd = vnd_cfg_read_byte();
@ -157,11 +189,18 @@ void vnd_cfg_task(void) {
#else /* CFG_TUD_VENDOR == 0 */ #else /* CFG_TUD_VENDOR == 0 */
void vnd_cfg_init(void) { } void vnd_cfg_init(void) { }
uint8_t vnd_cfg_read_byte(void) { return 0xff; } 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_flush(void) { }
void vnd_cfg_write_byte(uint8_t v) { (void)v; } 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 vnd_cfg_write_resp(enum cfg_resp stat, uint16_t len, const void* data) {
(void)stat; (void)len; (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) { } void vnd_cfg_task(void) { }
#endif /* CFG_TUD_VENDOR */ #endif /* CFG_TUD_VENDOR */

View File

@ -52,9 +52,14 @@ enum cfg_resp {
}; };
uint8_t vnd_cfg_read_byte (void); uint8_t vnd_cfg_read_byte (void);
void vnd_cfg_drop_incoming(void);
void vnd_cfg_write_flush(void); void vnd_cfg_write_flush(void);
void vnd_cfg_write_byte(uint8_t v); 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_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 #endif