diff --git a/project/inc/driver/i2c_drv.h b/project/inc/driver/i2c_drv.h new file mode 100644 index 0000000..59a27ad --- /dev/null +++ b/project/inc/driver/i2c_drv.h @@ -0,0 +1,55 @@ +/* + * i2c_drv.h + * + * Created on: 02/05/2017. + * Author: pvvx + */ + +#ifndef PROJECT_INC_DRIVER_I2C_DRV_H_ +#define PROJECT_INC_DRIVER_I2C_DRV_H_ + +#include "device.h" + +typedef struct _I2C_HND_ { + signed char status; + unsigned char idx; + unsigned char io_sel; + unsigned char mode; // if(I2C_FIXED_SPEED_MODE != 0) user set -> i2c_mode_e + void * base_regs; +} i2c_drv_t, *i2c_drv_p; + +typedef enum +{ + DRV_I2C_OFF = 0, // IC I2C DeInit + DRV_I2C_OK = 0, // DRV ret Ok + DRV_I2C_IC_OFF = 1, // IC I2C Off + DRV_I2C_IC_ENABLE = 2, // IC I2C On + DRV_I2C_ERR = -1, // DRV ret err + DRV_I2C_ABORT = -1, // IC I2C Abort + DRV_I2C_TIMEOUT = -3 // IC I2C / DRV ret Timeout +} _i2c_status_e; + + +typedef enum +{ + DRV_I2C_SS_MODE = 1, // Standard Mode (100 Kbps) + DRV_I2C_FS_MODE = 2, // Fast Mode (400 Kbps) + DRV_I2C_HS_MODE = 3 // Fast Mode Plus (1 Mbps) +} _i2c_mode_e; + +#define DRV_I2C_POOL_TIMEOUT 16384 +#define _i2c_deinit(p) _i2c_ic_off(p) + +// Setup +int _i2c_setup(i2c_drv_t *pi2c, PinName sda, PinName scl, unsigned char mode); // _i2c_mode_e +int _i2c_set_speed(i2c_drv_t *pi2c, uint32 clk_hz); +// Work +int _i2c_init(i2c_drv_t *pi2c); +int _i2c_write(i2c_drv_t *pi2c, uint32 address, const char *data, int length, int stop); +int _i2c_read(i2c_drv_t *pi2c, uint32 address, const char *data, int length, int stop); +// Utils +int _i2c_break(i2c_drv_t *pi2c); +void _i2c_ic_off(i2c_drv_t *pi2c); + + +#endif /* PROJECT_INC_DRIVER_I2C_DRV_H_ */ diff --git a/project/inc/ina219/ina219.h b/project/inc/ina219/ina219.h new file mode 100644 index 0000000..019b664 --- /dev/null +++ b/project/inc/ina219/ina219.h @@ -0,0 +1,91 @@ +/**************************************************************************/ +/**************************************************************************/ +#ifndef _INA219_H_ +#define _INA219_H_ + +/*========================================================================= + I2C ADDRESS/BITS + -----------------------------------------------------------------------*/ + #define INA219_ADDRESS (0x80) // 1000000r (A0+A1=GND) + #define INA219_READ (0x01) +/*=========================================================================*/ + +/*========================================================================= + CONFIG REGISTER (R/W) + -----------------------------------------------------------------------*/ + #define INA219_REG_CONFIG (0x00) + /*---------------------------------------------------------------------*/ + #define INA219_CONFIG_RESET (0x8000) // Reset Bit + + #define INA219_CONFIG_BVOLTAGERANGE_MASK (0x2000) // Bus Voltage Range Mask + #define INA219_CONFIG_BVOLTAGERANGE_16V (0x0000) // 0-16V Range + #define INA219_CONFIG_BVOLTAGERANGE_32V (0x2000) // 0-32V Range + + #define INA219_CONFIG_GAIN_MASK (0x1800) // Gain Mask + #define INA219_CONFIG_GAIN_1_40MV (0x0000) // Gain 1, 40mV Range + #define INA219_CONFIG_GAIN_2_80MV (0x0800) // Gain 2, 80mV Range + #define INA219_CONFIG_GAIN_4_160MV (0x1000) // Gain 4, 160mV Range + #define INA219_CONFIG_GAIN_8_320MV (0x1800) // Gain 8, 320mV Range + + #define INA219_CONFIG_BADCRES_MASK (0x0780) // Bus ADC Resolution Mask + #define INA219_CONFIG_BADCRES_9BIT (0x0080) // 9-bit bus res = 0..511 + #define INA219_CONFIG_BADCRES_10BIT (0x0100) // 10-bit bus res = 0..1023 + #define INA219_CONFIG_BADCRES_11BIT (0x0200) // 11-bit bus res = 0..2047 + #define INA219_CONFIG_BADCRES_12BIT (0x0400) // 12-bit bus res = 0..4097 + + #define INA219_CONFIG_SADCRES_MASK (0x0078) // Shunt ADC Resolution and Averaging Mask + #define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0000) // 1 x 9-bit shunt sample + #define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x0008) // 1 x 10-bit shunt sample + #define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x0010) // 1 x 11-bit shunt sample + #define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x0018) // 1 x 12-bit shunt sample + #define INA219_CONFIG_SADCRES_12BIT_1S_532US_ (0x0040) // 1 x 12-bit shunt sample + #define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x0048) // 2 x 12-bit shunt samples averaged together + #define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0x0050) // 4 x 12-bit shunt samples averaged together + #define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0x0058) // 8 x 12-bit shunt samples averaged together + #define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0x0060) // 16 x 12-bit shunt samples averaged together + #define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0x0068) // 32 x 12-bit shunt samples averaged together + #define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0x0070) // 64 x 12-bit shunt samples averaged together + #define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0x0078) // 128 x 12-bit shunt samples averaged together + + #define INA219_CONFIG_MODE_MASK (0x0007) // Operating Mode Mask + #define INA219_CONFIG_MODE_POWERDOWN (0x0000) + #define INA219_CONFIG_MODE_SVOLT_TRIGGERED (0x0001) + #define INA219_CONFIG_MODE_BVOLT_TRIGGERED (0x0002) + #define INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED (0x0003) + #define INA219_CONFIG_MODE_ADCOFF (0x0004) + #define INA219_CONFIG_MODE_SVOLT_CONTINUOUS (0x0005) + #define INA219_CONFIG_MODE_BVOLT_CONTINUOUS (0x0006) + #define INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS (0x0007) +/*=========================================================================*/ + +/*========================================================================= + SHUNT VOLTAGE REGISTER (R) + -----------------------------------------------------------------------*/ + #define INA219_REG_SHUNTVOLTAGE (0x01) +/*=========================================================================*/ + +/*========================================================================= + BUS VOLTAGE REGISTER (R) + -----------------------------------------------------------------------*/ + #define INA219_REG_BUSVOLTAGE (0x02) +/*=========================================================================*/ + +/*========================================================================= + POWER REGISTER (R) + -----------------------------------------------------------------------*/ + #define INA219_REG_POWER (0x03) +/*=========================================================================*/ + +/*========================================================================= + CURRENT REGISTER (R) + -----------------------------------------------------------------------*/ + #define INA219_REG_CURRENT (0x04) +/*=========================================================================*/ + +/*========================================================================= + CALIBRATION REGISTER (R/W) + -----------------------------------------------------------------------*/ + #define INA219_REG_CALIBRATION (0x05) +/*=========================================================================*/ + +#endif // _INA219_H_ diff --git a/project/inc/ina219/ina219buf.h b/project/inc/ina219/ina219buf.h new file mode 100644 index 0000000..2127ea6 --- /dev/null +++ b/project/inc/ina219/ina219buf.h @@ -0,0 +1,43 @@ +/************************************************************************** + * Драйвер для INA219 + **************************************************************************/ +#ifndef _INA219DRV_H_ +#define _INA219DRV_H_ +#include "ina219/ina219.h" +#include "device.h" +#include "timer_api.h" +#include "driver/i2c_drv.h" + +typedef struct _ina219data { + signed short voltage; // Voltage, 1mV + signed short current; // Current, 50uA? + signed short power; // Power, 1mW + unsigned short shunt; // 10uV +} INA219DATA, *PINA219DATA; + +typedef struct _ina219drv { + unsigned char status; + unsigned char addr; + signed char init; + unsigned char tmp; + unsigned short config; // регистр конфигурации INA219 + unsigned short calibration; // коэф. шунта для INA219 + unsigned int count; + unsigned int errs; + gtimer_t timer; + union { // буфер + unsigned char uc[4]; + unsigned short us[2]; + signed short ss[2]; + unsigned int ui; + } buf_i2c; + volatile i2c_drv_t i2c; +} INA219DRV, *PINA219DRV; + + +#define INA219_I2C_PIN_SDA PC_4 +#define INA219_I2C_PIN_SCL PC_5 +#define INA219_I2C_BUS_CLK 300000 //hz +#define INA219_TIMER TIMER3 // используемый таймер + +#endif // _INA219DRV_H_ diff --git a/project/inc/tcpsrv/tcp_srv_conn.h b/project/inc/tcpsrv/tcp_srv_conn.h index ad7b6ca..c2d376e 100644 --- a/project/inc/tcpsrv/tcp_srv_conn.h +++ b/project/inc/tcpsrv/tcp_srv_conn.h @@ -43,11 +43,8 @@ enum srvconn_state { #define TCP_SRV_SERVER_PORT 80 #endif -/* уровень вывода отладочной инфы по умолчанию -#ifndef DEBUGSOO - #define DEBUGSOO 2 -#endif -*/ + +#define SRV_WDGREFESH_IN_POOL // использовать WDGRefresh() в tcpsrv_poll() // время (сек), по умолчанию, ожидания запроса (передачи пакета) от клиента, до авто-закрытия соединения, // при = 0 заменяется на эти 5 сек. diff --git a/project/src/driver/i2c_drv.c b/project/src/driver/i2c_drv.c new file mode 100644 index 0000000..da9e1b6 --- /dev/null +++ b/project/src/driver/i2c_drv.c @@ -0,0 +1,452 @@ +/* + * i2c_drv.c + * + * Created on: 02/05/2017. + * Author: pvvx + */ +#include "driver/i2c_drv.h" + +#if CONFIG_I2C_EN + +#include "pinmap.h" + +typedef struct { + unsigned char sda; + unsigned char scl; + unsigned char sel; + unsigned char id; +} PinMapI2C; + +#define I2C_SEL(idx, ps) ((idx<<4) | ps) + +static const PinMapI2C PinMap_I2C[] = { + // sda, scl, sel, id + // I2C0 + {PD_4, PD_5, I2C_SEL(0, S0), I2C0}, + {PH_1, PH_0, I2C_SEL(0, S1), I2C0}, + {PC_8, PC_9, I2C_SEL(0, S2), I2C0}, + {PE_7, PE_6, I2C_SEL(0, S3), I2C0}, + // I2C1 + {PC_4, PC_5, I2C_SEL(1, S0), I2C1}, + {PH_3, PH_2, I2C_SEL(1, S1), I2C1}, + {PD_7, PD_6, I2C_SEL(1, S2), I2C1}, + // I2C2 + {PB_7, PB_6, I2C_SEL(2, S0), I2C2}, + {PE_1, PE_0, I2C_SEL(2, S1), I2C2}, + {PC_7, PC_6, I2C_SEL(2, S2), I2C2}, + // I2C3 + {PB_3, PB_2, I2C_SEL(3, S0), I2C3}, + {PE_3, PE_2, I2C_SEL(3, S1), I2C3}, + {PE_5, PE_4, I2C_SEL(3, S2), I2C3}, + {PD_9, PD_8, I2C_SEL(3, S3), I2C3}, + + {0xff, 0xff, 0, 0} +}; + +static void * i2c_base_reg[4] = { + I2C0_REG_BASE, + I2C1_REG_BASE, + I2C2_REG_BASE, + I2C3_REG_BASE +}; + +#if 1 +#define test_printf +#define i2c_dump_regs(p) +#else +#define test_printf rtl_printf +LOCAL int i2c_dump_regs(i2c_drv_t *pi2c) +{ + uint32 *ptr = pi2c->base_regs; + test_printf("%s:", __func__); + for(int i = 0; i < (0xA0>>2); i++) { + if(!(i%4)) { + test_printf("\n%08x:", &ptr[i]); + } + test_printf("\t%08x", ptr[i]); + } + test_printf("\n"); +} +#endif + +#define i2c_reg(r) *((volatile uint32 *)(pi2c->base_regs + r)) + +// flg =0 write, =1 Read +LOCAL int i2c_ready(i2c_drv_t *pi2c, unsigned char flg) +{ + test_printf("%s:\n", __func__); + // Test enable i2c + if(!(i2c_reg(REG_DW_I2C_IC_ENABLE) & BIT_IC_ENABLE)) { + error_printf("I2C%d disable!\n", pi2c->idx); + pi2c->status = DRV_I2C_IC_OFF; + return DRV_I2C_IC_OFF; + } + // Wait Receive FIFO is empty & Transmit FIFO Completely Empty + int poll_count = DRV_I2C_POOL_TIMEOUT; + do { + if(i2c_reg(REG_DW_I2C_IC_RAW_INTR_STAT) & BIT_IC_RAW_INTR_STAT_TX_ABRT) { + error_printf("I2C%d Abort!\n", pi2c->idx); + // Clear abort status. + (volatile)i2c_reg(REG_DW_I2C_IC_CLR_TX_ABRT); + // Be sure that all interrupts flag are cleared. +// (volatile)i2c_reg(REG_DW_I2C_IC_CLR_INTR); + pi2c->status = DRV_I2C_ABORT; + return DRV_I2C_ABORT; + } + if(flg) { + // Receive FIFO ready ? + if(i2c_reg(REG_DW_I2C_IC_STATUS) & (BIT_IC_STATUS_RFNE | BIT_IC_STATUS_RFF)) { + // pi2c->status = DRV_I2C_IC_ENABLE; + return DRV_I2C_OK; + } + } + else { + // Transmit FIFO is not full ? + if(i2c_reg(REG_DW_I2C_IC_STATUS) & BIT_IC_STATUS_TFNF) { + // pi2c->status = DRV_I2C_IC_ENABLE; + return DRV_I2C_OK; + } + } + } while(poll_count--); + error_printf("I2C%d Timeout!\n", pi2c->idx); + pi2c->status = DRV_I2C_TIMEOUT; + return DRV_I2C_TIMEOUT; +} + +int _i2c_break(i2c_drv_t *pi2c) +{ + test_printf("%s\n", __func__); +// (volatile)i2c_reg(REG_DW_I2C_IC_CLR_INTR); + // ABORT operation + int poll_count = DRV_I2C_POOL_TIMEOUT; + i2c_reg(REG_DW_I2C_IC_ENABLE) |= 2; + // Wait until controller is disabled. + while(i2c_reg(REG_DW_I2C_IC_ENABLE) & 2) { + if(poll_count-- <= 0) { + error_printf("Error abort i2c%d\n", pi2c->idx); + pi2c->status = DRV_I2C_TIMEOUT; + return DRV_I2C_TIMEOUT; + }; + }; + pi2c->status = DRV_I2C_OFF; + // All interrupts flag are cleared. + (volatile)i2c_reg(REG_DW_I2C_IC_CLR_INTR); + return DRV_I2C_OK; +} + +/* (!) вызывать после _i2c_init */ +int _i2c_set_speed(i2c_drv_t *pi2c, uint32 clk_hz) +{ + test_printf("%s:\n", __func__); + if(clk_hz < 10000 || clk_hz > HalGetCpuClk()/16) { + error_printf("I2C%d Error clk!\n", pi2c->idx); + return DRV_I2C_ERR; + } + uint32 tmp; + uint32 CpuClkTmp = HalGetCpuClk()/clk_hz; + switch(pi2c->mode) { + case I2C_SS_MODE: + // Standard Speed Clock SCL High Count + tmp = (CpuClkTmp * I2C_SS_MIN_SCL_HTIME)/(I2C_SS_MIN_SCL_HTIME + I2C_SS_MIN_SCL_LTIME); + i2c_reg(REG_DW_I2C_IC_SS_SCL_HCNT) = BIT_CTRL_IC_SS_SCL_HCNT(tmp); + // Standard Speed Clock SCL Low Count + tmp = (CpuClkTmp * I2C_SS_MIN_SCL_LTIME)/(I2C_SS_MIN_SCL_HTIME + I2C_SS_MIN_SCL_LTIME); + i2c_reg(REG_DW_I2C_IC_SS_SCL_LCNT) = BIT_CTRL_IC_SS_SCL_LCNT(tmp); + break; + case I2C_HS_MODE: + // Standard Speed Clock SCL High Count + i2c_reg(REG_DW_I2C_IC_SS_SCL_HCNT) = BIT_CTRL_IC_SS_SCL_HCNT(400); + // Standard Speed Clock SCL Low Count + i2c_reg(REG_DW_I2C_IC_SS_SCL_LCNT) = BIT_CTRL_IC_SS_SCL_LCNT(470); + // Fast Speed Clock SCL High Count + i2c_reg(REG_DW_I2C_IC_FS_SCL_HCNT) = BIT_CTRL_IC_FS_SCL_HCNT(85); + // Fast Speed I2C Clock SCL Low Count + i2c_reg(REG_DW_I2C_IC_FS_SCL_LCNT) = BIT_CTRL_IC_FS_SCL_LCNT(105); + // High Speed I2C Clock SCL High Count + tmp = (CpuClkTmp * I2C_HS_MIN_SCL_HTIME_100)/(I2C_HS_MIN_SCL_HTIME_100 + I2C_HS_MIN_SCL_LTIME_100); + if (tmp > 8) tmp -= 3; + i2c_reg(REG_DW_I2C_IC_HS_SCL_HCNT) = BIT_CTRL_IC_HS_SCL_HCNT(tmp); + // High Speed I2C Clock SCL Low Count + tmp = (CpuClkTmp * I2C_HS_MIN_SCL_LTIME_100)/(I2C_HS_MIN_SCL_HTIME_100 + I2C_HS_MIN_SCL_LTIME_100); + if (tmp > 6) tmp -= 6; + i2c_reg(REG_DW_I2C_IC_HS_SCL_LCNT) = BIT_CTRL_IC_FS_SCL_LCNT(tmp); + break; +// case I2C_FS_MODE: + default: + pi2c->mode = I2C_FS_MODE; + // Fast Speed Clock SCL High Count + tmp = (CpuClkTmp * I2C_FS_MIN_SCL_HTIME)/(I2C_FS_MIN_SCL_HTIME + I2C_FS_MIN_SCL_LTIME); + if (tmp > 4) tmp -= 4;// this part is according to the fine-tune result + i2c_reg(REG_DW_I2C_IC_FS_SCL_HCNT) = BIT_CTRL_IC_FS_SCL_HCNT(tmp); + // Fast Speed I2C Clock SCL Low Count + tmp = (CpuClkTmp * I2C_FS_MIN_SCL_LTIME)/(I2C_FS_MIN_SCL_HTIME + I2C_FS_MIN_SCL_LTIME); + if (tmp > 3) tmp -= 3; // this part is according to the fine-tune result + i2c_reg(REG_DW_I2C_IC_FS_SCL_LCNT) = BIT_CTRL_IC_FS_SCL_LCNT(tmp); + } + return DRV_I2C_OK; +} + +LOCAL int i2c_disable(i2c_drv_t *pi2c) +{ + test_printf("%s:\n", __func__); + pi2c->status = DRV_I2C_IC_OFF; + if(i2c_reg(REG_DW_I2C_IC_ENABLE_STATUS) & BIT_IC_ENABLE_STATUS_IC_EN) { + test_printf("I2C%d Already disable!\n", pi2c->idx); + return DRV_I2C_OK; + } + // Disable controller. + int poll_count = DRV_I2C_POOL_TIMEOUT; + i2c_reg(REG_DW_I2C_IC_ENABLE) &= ~BIT_IC_ENABLE; + // Wait until controller is disabled. + while(i2c_reg(REG_DW_I2C_IC_ENABLE_STATUS) & BIT_IC_ENABLE_STATUS_IC_EN) { + if(poll_count-- <= 0) { + error_printf("I2C%d Error disable!\n", pi2c->idx); + pi2c->status = DRV_I2C_TIMEOUT; + return DRV_I2C_TIMEOUT; + }; + }; + return DRV_I2C_OK; +} + +LOCAL int i2c_enable(i2c_drv_t *pi2c) +{ + test_printf("%s:\n", __func__); + int poll_count = DRV_I2C_POOL_TIMEOUT; + if(!(i2c_reg(REG_DW_I2C_IC_ENABLE_STATUS) & BIT_IC_ENABLE_STATUS_IC_EN)) { + // Enable controller. + i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE; + // Wait until controller is enabled + while(!(i2c_reg(REG_DW_I2C_IC_ENABLE_STATUS) & BIT_IC_ENABLE_STATUS_IC_EN)) { + if(poll_count-- <= 0) { + error_printf("I2C%d Error enable\n", pi2c->idx); + pi2c->status = DRV_I2C_TIMEOUT; + return DRV_I2C_TIMEOUT; + }; + }; + }; + // Be sure that all interrupts flag are cleared. + (volatile)i2c_reg(REG_DW_I2C_IC_CLR_INTR); + pi2c->status = DRV_I2C_IC_ENABLE; + return DRV_I2C_OK; +} + +// IC On & Enable CLK +LOCAL void _i2c_ic_on(i2c_drv_t *pi2c) +{ + test_printf("%s:\n", __func__); + uint32 tmp = 1 << (pi2c->idx << 1); + HAL_PERI_ON_WRITE32(REG_PESOC_PERI_CLK_CTRL1, + HAL_PERI_ON_READ32(REG_PESOC_PERI_CLK_CTRL1) | tmp); + HAL_PERI_ON_WRITE32(REG_PESOC_PERI_CLK_CTRL1, + HAL_PERI_ON_READ32(REG_PESOC_PERI_CLK_CTRL1) | (tmp << 1)); + tmp = BIT_PERI_I2C0_EN << pi2c->idx; + HAL_PERI_ON_WRITE32(REG_SOC_PERI_FUNC0_EN, + HAL_PERI_ON_READ32(REG_SOC_PERI_FUNC0_EN) & (~tmp)); + HAL_PERI_ON_WRITE32(REG_SOC_PERI_FUNC0_EN, + HAL_PERI_ON_READ32(REG_SOC_PERI_FUNC0_EN) | tmp); + + tmp = HAL_READ32(PERI_ON_BASE, REG_PESOC_CLK_SEL); + tmp &= (~(BIT_PESOC_PERI_SCLK_SEL(3))); + HAL_WRITE32(PERI_ON_BASE, REG_PESOC_CLK_SEL, tmp); + + HalPinCtrlRtl8195A(I2C0 + pi2c->idx, pi2c->io_sel, 1); +} + +// IC Off & Disable CLK +void _i2c_ic_off(i2c_drv_t *pi2c) +{ + test_printf("%s:\n", __func__); + if(pi2c->status) { + // mask all interrupts + i2c_reg(REG_DW_I2C_IC_INTR_MASK) = 0; + // Disable (Abort I2C Controller) + _i2c_break(pi2c); + i2c_disable(pi2c); + uint32 mask = BIT_PERI_I2C0_EN << pi2c->idx; + HAL_PERI_ON_WRITE32(REG_SOC_PERI_FUNC0_EN, + HAL_PERI_ON_READ32(REG_SOC_PERI_FUNC0_EN) | mask); + HalPinCtrlRtl8195A(I2C0 + pi2c->idx, pi2c->io_sel, 0); +#ifdef CONFIG_SOC_PS_MODULE + REG_POWER_STATE i2cPwrState; + // To register a new peripheral device power state + i2cPwrState.FuncIdx = I2C0 + pi2c->idx; + i2cPwrState.PwrState = INACT; + RegPowerState(i2cPwrState); +#endif + pi2c->status = DRV_I2C_OFF; + } +} + +/* (!) вызывать до _i2c_init, если параметрв драйвера не заданы в i2c_drv_t */ +int _i2c_setup(i2c_drv_t *pi2c, PinName sda, PinName scl, unsigned char mode) +{ + test_printf("%s:\n", __func__); + if(mode < DRV_I2C_SS_MODE || mode > DRV_I2C_HS_MODE) { + error_printf("I2C Error mode!\n"); + return DRV_I2C_ERR; + } + // Pins -> index + PinMapI2C *p = PinMap_I2C; + while(p->sda != 0xFF) { + if(p->sda == sda && p->scl == scl) { + pi2c->io_sel = RTL_GET_PERI_SEL(p->sel); + pi2c->idx = RTL_GET_PERI_IDX(p->sel); + pi2c->mode = mode; + return DRV_I2C_OK; + } + p++; + } + error_printf("I2C Error pins!\n"); + return DRV_I2C_ERR; +} + +/* (!) Использует заполненную структуру i2c_drv_t */ +int _i2c_init(i2c_drv_t *pi2c) +{ + test_printf("%s:\n", __func__); + // Set base address regs i2c + pi2c->base_regs = i2c_base_reg[pi2c->idx]; + // IC On & Enable CLK + if(pi2c->status == DRV_I2C_OFF) _i2c_ic_on(pi2c); + // mask all interrupts + i2c_reg(REG_DW_I2C_IC_INTR_MASK) = 0; + // disable i2c + if(i2c_disable(pi2c)) return pi2c->status; + // Set Control Register: + // bit0: master enabled, + // bit1..2: fast mode (400 kbit/s), ... + // bit2: Slave Addressing Mode 7-bit + // bit4: Master Addressing Mode 7-bit + // bit5: Restart disable + // bit6: Slave Mode Disable + // bit7: STOP_DET_IFADDRESSED + // bit8: TX_EMPTY_CTRL + // bit9: RX_FIFO_FULL_HLD_CTRL + // Set MASTER_MODE + i2c_reg(REG_DW_I2C_IC_CON) = + BIT_CTRL_IC_CON_MASTER_MODE(1) + | BIT_IC_CON_SPEED(pi2c->mode) + | BIT_CTRL_IC_CON_IC_10BITADDR_SLAVE(0) + | BIT_CTRL_IC_CON_IC_10BITADDR_MASTER(0) + | BIT_CTRL_IC_CON_IC_RESTART_EN(1) + | BIT_CTRL_IC_CON_IC_SLAVE_DISABLE(1); + // Master Target Address + // i2c_reg(REG_DW_I2C_IC_TAR) = 0x40; + // Slave Address + // i2c_reg(REG_DW_I2C_IC_SAR) = 0x55; + // High Speed Master ID (00001xxx) bit0..2 +// i2c_reg(REG_DW_I2C_IC_HS_MADDR) = BIT_CTRL_IC_HS_MADDR(0x4); + // Standard Speed Clock SCL High Count (100kHz) + i2c_reg(REG_DW_I2C_IC_SS_SCL_HCNT) = BIT_CTRL_IC_SS_SCL_HCNT(400); + // Standard Speed Clock SCL Low Count (100kHz) + i2c_reg(REG_DW_I2C_IC_SS_SCL_LCNT) = BIT_CTRL_IC_SS_SCL_LCNT(470); + // Fast Speed Clock SCL High Count (400kHz) + i2c_reg(REG_DW_I2C_IC_FS_SCL_HCNT) = BIT_CTRL_IC_FS_SCL_HCNT(80); + // Fast Speed I2C Clock SCL Low Count (400kHz) + i2c_reg(REG_DW_I2C_IC_FS_SCL_LCNT) = BIT_CTRL_IC_FS_SCL_LCNT(100); + // High Speed I2C Clock SCL High Count (1MHz) + i2c_reg(REG_DW_I2C_IC_HS_SCL_HCNT) = BIT_CTRL_IC_HS_SCL_HCNT(30); + // High Speed I2C Clock SCL Low Count (1MHz) + i2c_reg(REG_DW_I2C_IC_HS_SCL_LCNT) = BIT_CTRL_IC_FS_SCL_LCNT(40); + // SDA Hold (IC_CLK period, when I2C controller acts as a transmitter/receiver) + i2c_reg(REG_DW_I2C_IC_SDA_HOLD) = BIT_CTRL_IC_SDA_HOLD(10); + // General Call Ack + i2c_reg(REG_DW_I2C_IC_ACK_GENERAL_CALL) = BIT_CTRL_IC_ACK_GENERAL_CALL(1); + // Receive FIFO Threshold Level + // i2c_reg(REG_DW_I2C_IC_RX_TL) = 0x0; + // Transmit FIFO Threshold Level + // i2c_reg(REG_DW_I2C_IC_TX_TL) = 0x0; + // Transmit Abort Source + // i2c_reg(REG_DW_I2C_IC_TX_ABRT_SOURCE) = 0x0; + // DMA Transmit Data Level Register + // i2c_reg(REG_DW_I2C_IC_DMA_TDLR) = 0x09; + +#ifdef CONFIG_SOC_PS_MODULE + REG_POWER_STATE i2cPwrState; + // To register a new peripheral device power state + i2cPwrState.FuncIdx = I2C0 + pi2c->idx; + i2cPwrState.PwrState = ACT; + RegPowerState(i2cPwrState); +#endif + i2c_dump_regs(pi2c); +// pi2c->status = DRV_I2C_IC_OFF; + return DRV_I2C_OK; +} + +int _i2c_write(i2c_drv_t *pi2c, uint32 address, const char *data, int length, int stop) +{ + test_printf("%s: [%d]%d\n", __func__, length, stop); + uint8_t *d = (uint8_t *)data; + // Write slave address to TAR. + // bit12: = 1 - 10-bit addressing mode when acting as a master + // bit11: = 1 - Special Command Enable + // bit10: = 1 - Special Command Type START BYTE + i2c_reg(REG_DW_I2C_IC_TAR) = address; + // Enable controller + if(i2c_enable(pi2c)) return pi2c->status; + while (length--) { + // Transmit FIFO is not full + if(i2c_ready(pi2c, 0)) return pi2c->status; // BIT_IC_STATUS_TFNF + // Fill IC_DATA_CMD[7:0] with the data. + // Send stop after last byte ? + if(length == 0 && stop) i2c_reg(REG_DW_I2C_IC_DATA_CMD) = *d | BIT_IC_DATA_CMD_STOP; + else i2c_reg(REG_DW_I2C_IC_DATA_CMD) = *d; + d++; + } + // Disable controller. + if(stop) { + if(i2c_disable(pi2c)) return pi2c->status; + } + return DRV_I2C_OK; +} + +int _i2c_read(i2c_drv_t *pi2c, uint32 address, const char *data, int length, int stop) +{ + test_printf("%s: [%d]%d\n", __func__, length, stop); + uint8_t *d = (uint8_t *)data; + int len = length; + // Write slave address to TAR. + // bit12: = 1 - 10-bit addressing mode when acting as a master + // bit11: = 1 - Special Command Enable + // bit10: = 1 - Special Command Type START BYTE + i2c_reg(REG_DW_I2C_IC_TAR) = address; + // Enable controller. + if(i2c_enable(pi2c)) return pi2c->status; + while (len--) { + // Transmit FIFO is not full + if(i2c_ready(pi2c, 0)) return pi2c->status; // BIT_IC_STATUS_TFE + // Send stop after last byte ? + if (len == 0 && stop) { + // bit10: = 1 - Restart Bit Control + // bit9: = 1 - Stop Bit Control + // bit8: = 1 - Command read / = 0 Command write + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP; + } else { + // Read command -IC_DATA_CMD[8] = 1. + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD; + } + // Receive FIFO ready? + if(i2c_reg(REG_DW_I2C_IC_STATUS) & (BIT_IC_STATUS_RFNE | BIT_IC_STATUS_RFF)) { + // IC_DATA_CMD[7:0] contains received data. + if(length) { + *d++ = i2c_reg(REG_DW_I2C_IC_DATA_CMD); + length--; + } + else (volatile) i2c_reg(REG_DW_I2C_IC_DATA_CMD); + }; + } + while(length) { + // Receive FIFO ready? + if(i2c_ready(pi2c, 1)) return pi2c->status; // BIT_IC_STATUS_TFE + // IC_DATA_CMD[7:0] contains received data. + *d++ = i2c_reg(REG_DW_I2C_IC_DATA_CMD); + length--; + }; + // Disable controller. + if(stop) { + if(i2c_disable(pi2c)) return pi2c->status; + } + return DRV_I2C_OK; +} + +#endif // CONFIG_I2C_EN diff --git a/project/src/ina219/ina219buf.c b/project/src/ina219/ina219buf.c new file mode 100644 index 0000000..ee1aebf --- /dev/null +++ b/project/src/ina219/ina219buf.c @@ -0,0 +1,274 @@ +/* + * ina219buf.c + * + * Created on: 02/05/2017 + * Author: pvvx + */ +#include +#include "rtl8195a.h" +#include "device.h" +#include "PinNames.h" + +#include "basic_types.h" +#include "diag.h" +#include "osdep_api.h" + +//#include "i2c_api.h" +//#include "i2c_ex_api.h" +#include "pinmap.h" +#include "rtl_lib.h" +#include "ina219/ina219buf.h" +#include "rtl8195a/rtl_libc.h" +#include "driver/i2c_drv.h" + +INA219DRV ina219drv = { + .addr = INA219_ADDRESS>>1, + .config = + INA219_CONFIG_BVOLTAGERANGE_16V | // INA219_CONFIG_BVOLTAGERANGE_32V + INA219_CONFIG_GAIN_8_320MV | // INA219_CONFIG_GAIN_1_40MV | + INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_2S_1060US | // INA219_CONFIG_SADCRES_12BIT_128S_69MS | + INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS, + .calibration = 8192, + .i2c.status = DRV_I2C_OFF, + .i2c.idx = 1, // I2C1 + .i2c.io_sel = S0, // PC_4, PC_5 + .i2c.mode = DRV_I2C_FS_MODE // DRV_I2C_HS_MODE +}; + +void ina219_write(unsigned char reg, unsigned short data) +{ + PINA219DRV p = &ina219drv; + p->buf_i2c.uc[0] = reg; + p->buf_i2c.uc[1] = (unsigned char)((unsigned short)(data >> 8)); + p->buf_i2c.uc[2] = (unsigned char)data; + _i2c_write(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 3, 1); +} + +unsigned int ina219_read(unsigned char reg) +{ + PINA219DRV p = &ina219drv; + p->buf_i2c.uc[0] = reg; + _i2c_write(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 1, 1); + p->buf_i2c.ui = 0; + _i2c_read(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 2, 1); + return (p->buf_i2c.uc[0] << 8) | p->buf_i2c.uc[1]; +} + +#define i2c_reg(r) *((volatile uint32 *)(pi2c->base_regs + r)) + +/* Пример непрерывного чтения регистров + * тока и напряжения IN219 по прерыванию таймера */ +void ina_tick_handler(void *par) { + PINA219DRV p = &ina219drv; + i2c_drv_t *pi2c = &p->i2c; + switch(p->status) { + default: + // Disable controller. + i2c_reg(REG_DW_I2C_IC_ENABLE) = 0; + p->status = 1; + break; + case 1: + // Master Target Address + i2c_reg(REG_DW_I2C_IC_TAR) = p->addr; + // Enable controller. + i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE; + p->status = 2; + break; + case 2: + // Заполним FIFO ic I2C командами инициализации INA219 + // Write addr reg. + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CONFIG; + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = p->config >> 8; + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (p->config & 0x0FF) | BIT_IC_DATA_CMD_STOP; + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CALIBRATION; + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = p->calibration >> 8; + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (p->calibration & 0x0FF) | BIT_IC_DATA_CMD_STOP; + // + p->status = 3; + break; + case 4: + if (i2c_reg(REG_DW_I2C_IC_RAW_INTR_STAT) & BIT_IC_RAW_INTR_STAT_TX_ABRT) { + uint32 tmp = i2c_reg(REG_DW_I2C_IC_CLR_INTR); + p->errs++; + p->status = 0; + break; + } else { + // Считаем готовые значения из FIFO ic I2C + p->buf_i2c.uc[1] = i2c_reg(REG_DW_I2C_IC_DATA_CMD); + p->buf_i2c.uc[0] = i2c_reg(REG_DW_I2C_IC_DATA_CMD); + p->buf_i2c.uc[3] = i2c_reg(REG_DW_I2C_IC_DATA_CMD); + p->buf_i2c.uc[2] = i2c_reg(REG_DW_I2C_IC_DATA_CMD); + p->count++; + } + case 3: + // Заполним FIFO ic I2C командами чтения + // Write addr reg. + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_BUSVOLTAGE | BIT_IC_DATA_CMD_STOP; + // Read command. + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD; + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP; + // Write addr reg. + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_SHUNTVOLTAGE | BIT_IC_DATA_CMD_STOP; + // Read command. + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD; + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP; + p->status = 4; + break; + } +} + +void ina219_init(void) +{ + PINA219DRV p = &ina219drv; + if(p->init <= 0) { + rtl_printf("Init INA219\n"); + p->status = 0; + p->count = 0; + p->errs = 0; +// (!) Установки драйвера I2C заданы в структуре ina219drv +// _i2c_setup(&p->i2c, INA219_I2C_PIN_SDA , INA219_I2C_PIN_SCL, DRV_I2C_FS_MODE); // == DRV_I2C_OK? + _i2c_init(&p->i2c); +// _i2c_set_speed(&p->i2c, INA219_I2C_BUS_CLK); + rtl_printf("I2C%d mode = %d, drvStatus = %d\n", p->i2c.idx, p->i2c.mode, p->i2c.status); +// (!) Инициализация INA219 перенесена в прерывание таймера +// ina219_write(INA219_REG_CONFIG, p->config); +// ina219_write(INA219_REG_CALIBRATION, p->calibration); + // Initial a periodical timer + gtimer_init(&p->timer, INA219_TIMER); + // Tick every 0.000532 sec (N*532 μs) + uint32 tus = (1 << ((p->config >> 3) & 7)); + tus *= 532; + gtimer_start_periodical(&p->timer, tus, (void*)ina_tick_handler, (uint32_t)&ina219drv); + rtl_printf("INA219 Read Period = %u us\n", tus); + p->init = 1; + } +} + +void ina219_deinit(void) +{ + PINA219DRV p = &ina219drv; + i2c_drv_t *pi2c = &p->i2c; + if(p->init > 0) { + rtl_printf("Deinit INA219\n"); + gtimer_stop(&p->timer); + gtimer_deinit(&p->timer); +// (!) Не используется ina219_write / ina219_read для сокращения кода +// ina219_write(INA219_REG_CONFIG, INA219_CONFIG_MODE_POWERDOWN); + // Break controller. + i2c_reg(REG_DW_I2C_IC_ENABLE) |= 2; + vTaskDelay(2); // +WDT + // Disable controller. + i2c_reg(REG_DW_I2C_IC_ENABLE) = 0; + vTaskDelay(2); // +WDT + // Master Target Address + i2c_reg(REG_DW_I2C_IC_TAR) = p->addr; + // Enable controller. + i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE; + // Заполним FIFO ic I2C командой отключения INA219 + vTaskDelay(2); // +WDT + // Write addr reg. INA219 POWER_DOWN + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = INA219_REG_CONFIG; + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (INA219_CONFIG_MODE_POWERDOWN >> 8); + i2c_reg(REG_DW_I2C_IC_DATA_CMD) = (INA219_CONFIG_MODE_POWERDOWN & 0x0F) | BIT_IC_DATA_CMD_STOP; + vTaskDelay(2); // +WDT + _i2c_deinit(&p->i2c); + } + p->init = -1; +} + +LOCAL void ShowIna(void) +{ + PINA219DRV p = &ina219drv; + rtl_printf("INA219: %d, %d\n", p->buf_i2c.us[0], p->buf_i2c.ss[1]); + rtl_printf("INA219: Cnt = %u, Err = %u\n", p->count, p->errs); +} + +LOCAL void fATINA(int argc, char *argv[]) +{ + if(argc > 1) { + if(atoi(argv[1])) { + ina219_init(); + vTaskDelay(10); // +WDT + } + else ina219_deinit(); + } + ShowIna(); +} + + +extern void dump_bytes(uint32 addr, int size); +extern uint32 hextoul(uint8 *s); + +i2c_drv_t ti2c; +/* Sample: + * ati2c i + * ati2c w 40 5 + * ati2c r 40 2 + */ +LOCAL void fATI2C(int argc, char *argv[]) +{ + i2c_drv_t *pi2c = &ti2c; + uint8 buf[32]; + if(argc > 1) { + if(argv[1][0] == 'i') { + if(!pi2c->status) { + uint8 sda = 0; + uint8 scl = 0; + uint8 mode = 0; + uint32 speed = 0; + if(argc > 2) sda = hextoul(argv[2]); + else if(argc > 3) scl = hextoul(argv[3]); + else if(argc > 4) mode = hextoul(argv[4]); + else if(argc > 5) speed = hextoul(argv[5]); + if(!sda) sda = PC_4; + if(!scl) scl = PC_5; + if(!mode) mode = DRV_I2C_FS_MODE; + if(!speed) speed = 400000; + if(_i2c_setup(pi2c, sda, scl, mode) == DRV_I2C_OK + && _i2c_init(pi2c) == DRV_I2C_OK + && _i2c_set_speed(pi2c, speed) == DRV_I2C_OK) { + rtl_printf("I2C%d Init\n", pi2c->idx); + }; + } else { + rtl_printf("Already init!\n"); + return; + }; + } else { + if(pi2c->status) { + if(argv[1][0] == 'd') { + _i2c_ic_off(pi2c); + rtl_printf("I2C%d DeInit\n", pi2c->idx); + return; + }; + int i; + for(i = 0; i + 2 < argc; i++) { + buf[i] = hextoul(argv[i+2]); + }; + if(i) { + if(argv[1][0] == 'w') { + _i2c_write(pi2c, buf[0], &buf[1], i-1, 1); + rtl_printf("I2C%d write[%d]:\n", pi2c->idx, i-1); + dump_bytes(&buf[0], i); + } + else if(argv[1][0] == 'r') { + i = buf[1]; + if(i > sizeof(buf) - 1) i = sizeof(buf) - 1; + _i2c_read(pi2c, buf[0], &buf[1], i, 1); + rtl_printf("I2C%d read[%d]:\n", pi2c->idx, i); + dump_bytes(&buf[0], i+1); + }; + + }; + }; + }; + }; + rtl_printf("I2C%d drvStatus = %d\n", pi2c->idx, pi2c->status); + return; +} + +MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_ina219[] = { + {"ATI2C", 0, fATI2C, ": Test I2C, nit, einit, rite, ead"}, + {"ATINA", 0, fATINA, "=[0/1]: INA219 =1 start, =0 stop"} +}; + diff --git a/project/src/tcpsrv/tcp_srv_conn.c b/project/src/tcpsrv/tcp_srv_conn.c index 35760ee..1d26704 100644 --- a/project/src/tcpsrv/tcp_srv_conn.c +++ b/project/src/tcpsrv/tcp_srv_conn.c @@ -685,6 +685,9 @@ static err_t TCP_SRV_CODE_ATTR tcpsrv_poll(void *arg, struct tcp_pcb *pcb) { else tcpsrv_server_close(ts_conn); } else tcpsrv_server_close(ts_conn); +#ifdef SRV_WDGREFESH_IN_POOL + WDGRefresh(); +#endif return ERR_OK; } /****************************************************************************** diff --git a/sdkset.mk b/sdkset.mk index 0b0f279..ea0fc81 100644 --- a/sdkset.mk +++ b/sdkset.mk @@ -1,5 +1,6 @@ #USE_FATFS = 1 #USE_POLARSSL = 1 +#USE_P2P_WPS = 1 # FLAGS # ------------------------------------------------------------------- @@ -14,7 +15,7 @@ LFLAGS += -Wl,--gc-sections -Wl,--cref -Wl,--entry=Reset_Handler -Wl,--no-enum-s # LIBS # ------------------------------------------------------------------- LIBS = -all: LIBS +=_platform_new _wlan _wps _p2p _websocket _sdcard _xmodem +all: LIBS +=_platform_new _wlan _p2p _wps _websocket _sdcard _xmodem # _mdns m c nosys gcc _wps _p2p _websocket _sdcard _xmodem mp: LIBS +=_platform_new _wlan_mp _wps _p2p _websocket _sdcard _xmodem PATHLIBS = sdk/component/soc/realtek/8195a/misc/bsp/lib/common/gcc @@ -106,8 +107,11 @@ SRC_C += sdk/component/soc/realtek/8195a/misc/driver/rtl_console_new.c #SRC_C += sdk/component/soc/realtek/8195a/misc/driver/rtl_consol.c #network - api -SRC_C += sdk/component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_eap_config.c +ifdef USE_P2P_WPS SRC_C += sdk/component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_p2p_config.c +SRC_C += sdk/component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_wps_config.c +endif +SRC_C += sdk/component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_eap_config.c SRC_C += sdk/component/common/api/wifi/wifi_conf.c SRC_C += sdk/component/common/api/wifi/wifi_ind.c SRC_C += sdk/component/common/api/wifi/wifi_promisc.c @@ -261,7 +265,6 @@ SRC_C += sdk/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_uart.c ifdef USE_POLARSSL INCLUDES += sdk/component/common/network/ssl/polarssl-1.3.8/include -SRC_C += sdk/component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_wps_config.c SRC_C += sdk/component/common/network/ssl/polarssl-1.3.8/library/bignum.c DRAM_C += sdk/component/common/network/ssl/ssl_ram_map/rom/rom_ssl_ram_map.c @@ -412,6 +415,9 @@ ADD_SRC_C += project/src/console/atcmd_user.c ADD_SRC_C += project/src/console/wifi_console.c #ADD_SRC_C += project/src/console/pwm_tst.c #ADD_SRC_C += project/src/console/wlan_tst.c +#ADD_SRC_C += project/src/ina219/ina219drv.c +##ADD_SRC_C += project/src/driver/i2c_drv.c +##ADD_SRC_C += project/src/ina219/ina219buf.c #Web-свалка INCLUDES += project/inc/web