SMbus battery driver - a lot of updates and optimizations

- added support for BQ40Z80 based battery
- added performance counter for interface errors
- added SMART_BATTERY_INFO mavlink message
- general code cleanups and optimization
- fixed: void flooding the log in case of interface error
- fixed: using _batt_startup_capacity instead of _batt_capacity for discharged_mah
- update: read manufacture_date
- update: get _cell_count from parameter and not const 4
- update: avoid re-reading data that has already been read and stored on class already
- currently the battery type defined by BAT_SMBUS_MODEL parameter and not by auto detection
This commit is contained in:
bazooka joe
2020-08-18 21:41:19 -04:00
committed by Daniel Agar
parent 372866a22b
commit 190b96a46c
7 changed files with 386 additions and 243 deletions
+21 -3
View File
@@ -36,6 +36,7 @@
* SMBus v2.0 protocol implementation.
*
* @author Jacob Dahl <dahl.jakejacob@gmail.com>
* @author Bazooka Joe <BazookaJoe1900@gmail.com>
*
* TODO
* - Enable SMBus mode at the NuttX level. This may be tricky sharing the bus with i2c.
@@ -50,6 +51,11 @@ SMBus::SMBus(int bus_num, uint16_t address) :
{
}
SMBus::~SMBus()
{
perf_free(_interface_errors);
}
int SMBus::read_word(const uint8_t cmd_code, uint16_t &data)
{
uint8_t buf[6];
@@ -68,7 +74,11 @@ int SMBus::read_word(const uint8_t cmd_code, uint16_t &data)
if (pec != buf[sizeof(buf) - 1]) {
result = -EINVAL;
perf_count(_interface_errors);
}
} else {
perf_count(_interface_errors);
}
return result;
@@ -87,10 +97,14 @@ int SMBus::write_word(const uint8_t cmd_code, uint16_t data)
int result = transfer(&buf[1], 4, nullptr, 0);
if (result != PX4_OK) {
perf_count(_interface_errors);
}
return result;
}
int SMBus::block_read(const uint8_t cmd_code, void *data, const uint8_t length, bool use_pec)
int SMBus::block_read(const uint8_t cmd_code, void *data, const uint8_t length, const bool use_pec)
{
unsigned byte_count = 0;
// addr(wr), cmd_code, addr(r), byte_count, data (32 bytes max), pec
@@ -99,6 +113,7 @@ int SMBus::block_read(const uint8_t cmd_code, void *data, const uint8_t length,
int result = transfer(&cmd_code, 1, (uint8_t *)&rx_data[3], length + 2);
if (result != PX4_OK) {
perf_count(_interface_errors);
return result;
}
@@ -115,13 +130,14 @@ int SMBus::block_read(const uint8_t cmd_code, void *data, const uint8_t length,
if (pec != rx_data[byte_count + 4]) {
result = -EINVAL;
perf_count(_interface_errors);
}
}
return result;
}
int SMBus::block_write(const uint8_t cmd_code, void *data, uint8_t byte_count, bool use_pec)
int SMBus::block_write(const uint8_t cmd_code, const void *data, uint8_t byte_count, const bool use_pec)
{
// cmd code[1], byte count[1], data[byte_count] (32max), pec[1] (optional)
uint8_t buf[32 + 2];
@@ -141,11 +157,11 @@ int SMBus::block_write(const uint8_t cmd_code, void *data, uint8_t byte_count, b
// If block_write fails, try up to 10 times.
while (i < 10 && ((result = transfer((uint8_t *)buf, byte_count + 2, nullptr, 0)) != PX4_OK)) {
perf_count(_interface_errors);
i++;
}
if (i == 10 || result) {
PX4_WARN("Block_write failed %d times", i);
result = -EINVAL;
}
@@ -154,6 +170,8 @@ int SMBus::block_write(const uint8_t cmd_code, void *data, uint8_t byte_count, b
uint8_t SMBus::get_pec(uint8_t *buff, const uint8_t len)
{
// TODO: use "return crc8ccitt(buff, len);"
// Initialise CRC to zero.
uint8_t crc = 0;
uint8_t shift_register = 0;
+7 -4
View File
@@ -36,10 +36,11 @@
* SMBus v2.0 protocol implementation.
*
* @author Jacob Dahl <dahl.jakejacob@gmail.com>
* @author Bazooka Joe <BazookaJoe1900@gmail.com>
*/
#include <drivers/device/i2c.h>
#include <perf/perf_counter.h>
#include <string.h>
#define SMBUS_PEC_POLYNOMIAL 0x07 ///< Polynomial for calculating PEC
@@ -48,7 +49,7 @@ class SMBus : public device::I2C
{
public:
SMBus(int bus_num, uint16_t address);
~SMBus() override = default;
~SMBus() override;
/**
* @brief Sends a block write command.
@@ -57,7 +58,7 @@ public:
* @param length The number of bytes being written.
* @return Returns PX4_OK on success, -errno on failure.
*/
int block_write(const uint8_t cmd_code, void *data, uint8_t byte_count, bool use_pec);
int block_write(const uint8_t cmd_code, const void *data, uint8_t byte_count, const bool use_pec);
/**
* @brief Sends a block read command.
@@ -66,7 +67,7 @@ public:
* @param length The number of bytes being read.
* @return Returns PX4_OK on success, -errno on failure.
*/
int block_read(const uint8_t cmd_code, void *data, const uint8_t length, bool use_pec);
int block_read(const uint8_t cmd_code, void *data, const uint8_t length, const bool use_pec);
/**
* @brief Sends a read word command.
@@ -92,4 +93,6 @@ public:
*/
uint8_t get_pec(uint8_t *buffer, uint8_t length);
perf_counter_t _interface_errors{perf_alloc(PC_COUNT, MODULE_NAME": errors")};
};