Signed-off-by: Bigbits <btx000@qq.com>
This commit is contained in:
Bigbits
2019-03-28 18:47:39 +08:00
parent d8b2123ba9
commit 04786cac13
8 changed files with 677 additions and 6 deletions

View File

@@ -0,0 +1,43 @@
/*
Copyright (c) 2016 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <inttypes.h>
#include "Stream.h"
class HardwareI2C : public Stream
{
public:
virtual void begin() = 0;
virtual void begin(uint8_t address) = 0;
virtual void end() = 0;
virtual void setClock(uint32_t freq) = 0;
virtual void beginTransmission(uint8_t address) = 0;
virtual uint8_t endTransmission(bool stopBit) = 0;
virtual uint8_t endTransmission(void) = 0;
virtual uint8_t requestFrom(uint8_t address, size_t len, bool stopBit) = 0;
virtual uint8_t requestFrom(uint8_t address, size_t len) = 0;
virtual void onReceive(void(*)(int)) = 0;
virtual void onRequest(void(*)(void)) = 0;
};

View File

@@ -27,7 +27,7 @@
// using a ring buffer (I think), in which head is the index of the location
// to which to write the next incoming character and tail is the index of the
// location from which to read.
#define SERIAL_BUFFER_SIZE 64
#define RING_BUFFER_SIZE 64
template <int N>
class RingBufferN
@@ -51,7 +51,7 @@ class RingBufferN
int nextIndex(int index);
};
typedef RingBufferN<SERIAL_BUFFER_SIZE> RingBuffer;
typedef RingBufferN<RING_BUFFER_SIZE> RingBuffer;
template <int N>

View File

@@ -0,0 +1,35 @@
#######################################
# Syntax Coloring Map For Wire
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
setClock KEYWORD2
setClockStretchLimit KEYWORD2
beginTransmission KEYWORD2
endTransmission KEYWORD2
requestFrom KEYWORD2
send KEYWORD2
receive KEYWORD2
onReceive KEYWORD2
onRequest KEYWORD2
#######################################
# Instances (KEYWORD2)
#######################################
Wire KEYWORD2
Wire1 KEYWORD2
Wire2 KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View File

@@ -0,0 +1,9 @@
name=Wire
version=1.0.0
author=Bigbits
maintainer=
sentence=Allows the communication between devices or sensors connected via Two Wire Interface Bus. For k210 boards.
paragraph=
category=Signal Input/Output
url=http://arduino.cc/en/Reference/Wire
architectures=riscv

458
libraries/Wire/src/Wire.cpp Normal file
View File

@@ -0,0 +1,458 @@
#include "Arduino.h"
#include "pins_arduino.h"
#include "Wire.h"
#include "fpioa.h"
#include "i2c.h"
static int maix_i2c_slave_irq(void *userdata);
TwoWire::TwoWire(i2c_device_number_t i2c_device)
{
_i2c_num = i2c_device;
switch(i2c_device)
{
case I2C_DEVICE_0:
sda_func = FUNC_I2C0_SDA;
scl_func = FUNC_I2C0_SCLK;
break;
case I2C_DEVICE_1:
sda_func = FUNC_I2C1_SDA;
scl_func = FUNC_I2C1_SCLK;
break;
case I2C_DEVICE_2:
sda_func = FUNC_I2C2_SDA;
scl_func = FUNC_I2C2_SCLK;
break;
default:
break;
}
}
TwoWire::~TwoWire()
{
//clear
}
void
TwoWire::begin(uint8_t sda, uint8_t scl, uint32_t frequency)
{
i2c_clk = frequency;
fpioa_set_function(sda, sda_func);
fpioa_set_function(scl, scl_func);
volatile i2c_t *i2c_adapter = i2c[_i2c_num];
uint8_t speed_mode = I2C_CON_SPEED_STANDARD;
//i2c_clk_init
sysctl_clock_enable((sysctl_clock_t)(SYSCTL_CLOCK_I2C0 + _i2c_num));
sysctl_clock_set_threshold((sysctl_threshold_t)(SYSCTL_THRESHOLD_I2C0 + _i2c_num), 3);
uint32_t v_i2c_freq = sysctl_clock_get_freq((sysctl_clock_t)(SYSCTL_CLOCK_I2C0 + _i2c_num));
uint16_t v_period_clk_cnt = floor( (v_i2c_freq*1.0 / i2c_clk / 2) + 0.5 );
if(v_period_clk_cnt <= 6)
v_period_clk_cnt = 6;
if(v_period_clk_cnt >= 65525)//65535-10
v_period_clk_cnt = 65525;
if((i2c_clk>100000) && (i2c_clk<=1000000))
speed_mode = I2C_CON_SPEED_FAST;
else
speed_mode = I2C_CON_SPEED_HIGH;
i2c_adapter->enable = 0;
i2c_adapter->con = I2C_CON_MASTER_MODE | I2C_CON_SLAVE_DISABLE | I2C_CON_RESTART_EN |
(address_width == 10 ? I2C_CON_10BITADDR_SLAVE : 0) | I2C_CON_SPEED(speed_mode);
i2c_adapter->ss_scl_hcnt = I2C_SS_SCL_HCNT_COUNT(v_period_clk_cnt);
i2c_adapter->ss_scl_lcnt = I2C_SS_SCL_LCNT_COUNT(v_period_clk_cnt);
i2c_adapter->intr_mask = 0;
i2c_adapter->dma_cr = 0x3;
i2c_adapter->dma_rdlr = 0;
i2c_adapter->dma_tdlr = 4;
i2c_adapter->enable = I2C_ENABLE_ENABLE;
is_master_mode = true;
i2c_tx_buff = new RingBuffer();
i2c_rx_buff = new RingBuffer();
}
void
TwoWire::begin(uint16_t slave_address, uint8_t sda, uint8_t scl)
{
fpioa_set_function(sda, sda_func);
fpioa_set_function(scl, scl_func);
volatile i2c_t *i2c_adapter = i2c[_i2c_num];
sysctl_clock_enable((sysctl_clock_t)(SYSCTL_CLOCK_I2C0 + _i2c_num));
sysctl_clock_set_threshold((sysctl_threshold_t)(SYSCTL_THRESHOLD_I2C0 + _i2c_num), 3);
i2c_adapter->enable = 0;
i2c_adapter->con = I2C_CON_SPEED(1) | I2C_CON_STOP_DET_IFADDRESSED;
i2c_adapter->ss_scl_hcnt = I2C_SS_SCL_HCNT_COUNT(37);
i2c_adapter->ss_scl_lcnt = I2C_SS_SCL_LCNT_COUNT(40);
i2c_adapter->sar = I2C_SAR_ADDRESS(slave_address);
i2c_adapter->rx_tl = I2C_RX_TL_VALUE(0);
i2c_adapter->tx_tl = I2C_TX_TL_VALUE(0);
i2c_adapter->intr_mask = I2C_INTR_MASK_RX_FULL | I2C_INTR_MASK_START_DET | I2C_INTR_MASK_STOP_DET | I2C_INTR_MASK_RD_REQ;
plic_set_priority((plic_irq_t)(IRQN_I2C0_INTERRUPT + _i2c_num), 1);
plic_irq_register((plic_irq_t)(IRQN_I2C0_INTERRUPT + _i2c_num), maix_i2c_slave_irq, this);
plic_irq_enable((plic_irq_t)(IRQN_I2C0_INTERRUPT + _i2c_num));
i2c_adapter->enable = I2C_ENABLE_ENABLE;
is_master_mode = false;
i2c_tx_buff = new RingBuffer();
i2c_rx_buff = new RingBuffer();
}
void
TwoWire::setTimeOut(uint16_t timeOutMillis)
{
_timeOutMillis = timeOutMillis;
}
uint16_t
TwoWire::getTimeOut()
{
return _timeOutMillis;
}
void
TwoWire::setClock(uint32_t frequency)
{
i2c_clk = frequency;
volatile i2c_t *i2c_adapter = i2c[_i2c_num];
uint8_t speed_mode = I2C_CON_SPEED_STANDARD;
uint32_t v_i2c_freq = sysctl_clock_get_freq((sysctl_clock_t)(SYSCTL_CLOCK_I2C0 + _i2c_num));
uint16_t v_period_clk_cnt = floor( (v_i2c_freq*1.0 / i2c_clk / 2) + 0.5 );
if(v_period_clk_cnt <= 6)
v_period_clk_cnt = 6;
if(v_period_clk_cnt >= 65525)//65535-10
v_period_clk_cnt = 65525;
if((i2c_clk>100000) && (i2c_clk<=1000000))
speed_mode = I2C_CON_SPEED_FAST;
else
speed_mode = I2C_CON_SPEED_HIGH;
i2c_adapter->enable = 0;
i2c_adapter->con = I2C_CON_MASTER_MODE | I2C_CON_SLAVE_DISABLE | I2C_CON_RESTART_EN |
(address_width == 10 ? I2C_CON_10BITADDR_SLAVE : 0) | I2C_CON_SPEED(speed_mode);
i2c_adapter->ss_scl_hcnt = I2C_SS_SCL_HCNT_COUNT(v_period_clk_cnt);
i2c_adapter->ss_scl_lcnt = I2C_SS_SCL_LCNT_COUNT(v_period_clk_cnt);
i2c_adapter->enable = I2C_ENABLE_ENABLE;
}
uint32_t
TwoWire::getClock()
{
return i2c_clk;
}
int
TwoWire::writeTransmission(uint16_t address, uint8_t* send_buf, size_t send_buf_len, bool sendStop)
{
volatile i2c_t* i2c_adapter = i2c[_i2c_num];
size_t fifo_len, index;
//uint32_t abrt_source;
if(is_master_mode)
i2c_adapter->tar = I2C_TAR_ADDRESS(address);
while (send_buf_len)
{
fifo_len = 8 - i2c_adapter->txflr;
fifo_len = send_buf_len < fifo_len ? send_buf_len : fifo_len;
for (index = 0; index < fifo_len; index++)
i2c_adapter->data_cmd = I2C_DATA_CMD_DATA(*send_buf++);
if (i2c_adapter->tx_abrt_source != 0)
{
i2c_adapter->clr_tx_abrt;
usleep(10);
return 4;
}
send_buf_len -= fifo_len;
}
while ( (i2c_adapter->status & I2C_STATUS_ACTIVITY) ||
!(i2c_adapter->status & I2C_STATUS_TFE) )
{
if (i2c_adapter->tx_abrt_source != 0)
{
i2c_adapter->clr_tx_abrt;
usleep(10);
return 4;
}
}
return 0;
}
int
TwoWire::readTransmission(uint16_t address, uint8_t* receive_buf, size_t receive_buf_len, bool sendStop)
{
size_t fifo_len, index;
// size_t buf_len;
size_t rx_len;
rx_len = receive_buf_len;
// buf_len = rx_len;
volatile i2c_t* i2c_adapter = i2c[_i2c_num];
uint32_t abrt_source;
if(is_master_mode)
i2c_adapter->tar = I2C_TAR_ADDRESS(address);
while (receive_buf_len || rx_len)
{
fifo_len = i2c_adapter->rxflr;
fifo_len = rx_len < fifo_len ? rx_len : fifo_len;
for (index = 0; index < fifo_len; index++)
*receive_buf++ = (uint8_t)i2c_adapter->data_cmd;
rx_len -= fifo_len;
fifo_len = 8 - i2c_adapter->txflr;
fifo_len = receive_buf_len < fifo_len ? receive_buf_len : fifo_len;
for (index = 0; index < fifo_len; index++)
i2c_adapter->data_cmd = I2C_DATA_CMD_CMD;
abrt_source = i2c_adapter->tx_abrt_source;
if (abrt_source != 0)
{
i2c_adapter->clr_tx_abrt;
usleep(10);
// if(receive_buf_len == buf_len)
return 4;
// retur_buf_len -= fifo_len;
}
receive_buf_len -= fifo_len;
}
return 0;
}
void
TwoWire::beginTransmission(uint16_t address)
{
transmitting = 1;
txAddress = address;
}
uint8_t
TwoWire::endTransmission(bool sendStop) //结束时从rxbuff发送数据
{
int state = -1;
int index = 0;
uint8_t temp = 0;
size_t tx_data_length = i2c_tx_buff->available();
if(tx_data_length == 0){
state = readTransmission(txAddress, &temp, 1, sendStop);
return state;
}
uint8_t tx_data[RING_BUFFER_SIZE];
while(i2c_tx_buff->available())
{
tx_data[index++] = i2c_tx_buff->read_char();
}
state = writeTransmission(txAddress, tx_data, tx_data_length,sendStop);
return state;
}
uint8_t
TwoWire::requestFrom(uint16_t address, uint8_t size, bool sendStop) //请求数据存入rxbuff供read读
{
int state,index = 0;
uint8_t rx_data[RING_BUFFER_SIZE];
state = readTransmission(address, rx_data, size, sendStop);
if(0 == state){
while(size)
{
i2c_rx_buff->store_char(rx_data[index++]);
size--;
}
}
return state;
}
size_t
TwoWire::write(uint8_t data) //写到txbuff
{
if(transmitting) {
i2c_tx_buff->store_char(data);
}
return 0;
}
size_t
TwoWire::write(const uint8_t *data, int quantity)
{
for(size_t i = 0; i < quantity; ++i) {
if(!write(data[i])) {
return i;
}
}
return quantity;
}
int TwoWire::available(void) //rxbuff.available
{
return i2c_rx_buff->available();
}
int TwoWire::read(void) //rxbuff.read
{
return i2c_rx_buff->read_char();
}
int TwoWire::peek(void)
{
return i2c_rx_buff->peek();
}
int TwoWire::flush(void)
{
i2c_rx_buff->clear();
i2c_tx_buff->clear();
return 0;
}
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
{
return requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(quantity), static_cast<bool>(sendStop));
}
uint8_t TwoWire::requestFrom(uint16_t address, uint8_t quantity, uint8_t sendStop)
{
return requestFrom(address, static_cast<size_t>(quantity), static_cast<bool>(sendStop));
}
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
{
return requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(quantity), true);
}
uint8_t TwoWire::requestFrom(uint16_t address, uint8_t quantity)
{
return requestFrom(address, static_cast<size_t>(quantity), true);
}
uint8_t TwoWire::requestFrom(int address, int quantity)
{
return requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(quantity), true);
}
uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop)
{
return static_cast<uint8_t>(requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(quantity), static_cast<bool>(sendStop)));
}
void TwoWire::beginTransmission(int address)
{
beginTransmission(static_cast<uint16_t>(address));
}
void TwoWire::beginTransmission(uint8_t address)
{
beginTransmission(static_cast<uint16_t>(address));
}
uint8_t TwoWire::endTransmission(void)
{
return endTransmission(true);
}
bool
TwoWire::busy(void){
return false;
}
void
TwoWire::onReceive( void (*handler)(int) )
{
slave_recv_handler = handler;
}
void
TwoWire::onRequest( void (*handler)(void) )
{
slave_send_handler = handler;
}
void
TwoWire::on_receive(uint8_t rec_data)
{
if(slave_irq_event_start)
{
i2c_rx_buff->store_char(rec_data);
(*slave_recv_handler)((int)1);//此处跳到接收事件函数
}
return;
}
uint8_t
TwoWire::on_transmit()
{
if(slave_irq_event_start){
(*slave_send_handler)();//跳到发送事件函数
return i2c_tx_buff->read_char();
}
return 0;
}
uint8_t
TwoWire::on_event(i2c_event_t event)
{
if(event == I2C_EV_START)
slave_irq_event_start = true ;
else
slave_irq_event_start = false;
return 0;
}
static int maix_i2c_slave_irq(void *userdata)
{
auto &driver = *reinterpret_cast<TwoWire *>(userdata);
volatile i2c_t *i2c_adapter = i2c[driver._i2c_num];
uint32_t status = i2c_adapter->intr_stat;
if (status & I2C_INTR_STAT_START_DET)
{
driver.on_event(I2C_EV_START);
readl(&i2c_adapter->clr_start_det);
}
if (status & I2C_INTR_STAT_RX_FULL)
{
driver.on_receive(i2c_adapter->data_cmd);
}
if (status & I2C_INTR_STAT_RD_REQ)
{
i2c_adapter->data_cmd = driver.on_transmit();
readl(&i2c_adapter->clr_rd_req);
}
if (status & I2C_INTR_STAT_STOP_DET)
{
driver.on_event(I2C_EV_STOP);
readl(&i2c_adapter->clr_stop_det);
}
return 0;
}
void
TwoWire::scan(){
uint8_t temp;
for (int addr = 0x08; addr < 0x78; ++addr) {
// int ret = i2c_p->writeto(self, addr, NULL, 0, true);
// printf("find %x\n",addr);
int ret = readTransmission(addr,&temp, 1, 1);
// printf("ret:%x\n",ret);
if (ret == 0) {
Serial.print("SCAN Find device:");
Serial.println(addr,HEX);
}
}
}
TwoWire Wire = TwoWire(I2C_DEVICE_0);
TwoWire Wire1 = TwoWire(I2C_DEVICE_1);
TwoWire Wire2 = TwoWire(I2C_DEVICE_2);

126
libraries/Wire/src/Wire.h Normal file
View File

@@ -0,0 +1,126 @@
#ifndef TwoWire_h
#define TwoWire_h
#include "Arduino.h"
#include "Stream.h"
#include "RingBuffer.h"
#include "fpioa.h"
#include "i2c.h"
#define I2C_BUFFER_LENGTH 128
#define I2C_CON_SPEED_STANDARD 1 // <=100Kbit/s
#define I2C_CON_SPEED_FAST 2 // <=400Kbit/s or <=1000Kbit/s
#define I2C_CON_SPEED_HIGH 3 // <=3.4Mbit/s
typedef void(*user_onRequest)(void);
typedef void(*user_onReceive)(uint8_t*, int);
class TwoWire : public Stream
{
public:
i2c_device_number_t _i2c_num;
TwoWire(i2c_device_number_t i2c_device);
~TwoWire();
void begin(uint8_t sda = SDA, uint8_t scl = SCL, uint32_t frequency = 500000);
void begin(uint16_t slave_address, uint8_t sda = SDA, uint8_t scl = SCL);
void setClock(uint32_t frequency);
uint32_t getClock();
void setTimeOut(uint16_t timeOutMillis);
uint16_t getTimeOut();
int writeTransmission(uint16_t address, uint8_t* send_buf, size_t send_buf_len, bool sendStop);
int readTransmission(uint16_t address, uint8_t* receive_buf, size_t receive_buf_len, bool sendStop);
void beginTransmission(uint16_t address);
void beginTransmission(uint8_t address);
void beginTransmission(int address);
uint8_t endTransmission(bool sendStop);
uint8_t endTransmission(void);
uint8_t requestFrom(uint16_t address, uint8_t size, bool sendStop);
uint8_t requestFrom(uint16_t address, uint8_t size, uint8_t sendStop);
uint8_t requestFrom(uint16_t address, uint8_t size);
uint8_t requestFrom(uint8_t address, uint8_t size, uint8_t sendStop);
uint8_t requestFrom(uint8_t address, uint8_t size);
uint8_t requestFrom(int address, int size, int sendStop);
uint8_t requestFrom(int address, int size);
size_t write(uint8_t);
size_t write(const uint8_t *, int);
int available(void);
int read(void);
int peek(void);
int flush(void);
inline int write(const char * s)
{
return write((uint8_t*) s, strlen(s));
}
inline int write(unsigned long n)
{
return write((uint8_t)n);
}
inline int write(long n)
{
return write((uint8_t)n);
}
inline int write(unsigned int n)
{
return write((uint8_t)n);
}
inline int write(int n)
{
return write((uint8_t)n);
}
void onReceive( void (*)(int) );
void onRequest( void (*)(void) );
uint8_t on_event(i2c_event_t event);
uint8_t on_transmit();
void on_receive(uint8_t rec_data);
bool busy();
void scan();
private:
uint16_t i2c_slave_address;
bool is_master_mode = false;
uint32_t address_width = 7;
uint8_t sda = FPIOA_NUM_IO;
uint8_t scl = FPIOA_NUM_IO;
uint32_t i2c_clk;
fpioa_function_t sda_func;
fpioa_function_t scl_func;
RingBuffer *i2c_tx_buff;
RingBuffer *i2c_rx_buff;
uint16_t txAddress;
uint8_t transmitting;
uint16_t _timeOutMillis;
bool slave_irq_event_start = false;
void (*slave_recv_handler)(int) ;
void (*slave_send_handler)(void) ;
};
extern volatile i2c_t* const i2c[3];
extern TwoWire Wire;
extern TwoWire Wire1;
extern TwoWire Wire2;
#endif //TwoWire_h

View File

@@ -62,8 +62,8 @@ extern class UARTClass Serial3;
#define RX1 6
#define TX1 7
#define SDA 10
#define SCL 9
#define SDA 31
#define SCL 30
static const uint8_t SS = SPI0_CS0 ;
static const uint8_t MOSI = SPI0_MOSI;

View File

@@ -62,8 +62,8 @@ extern class UARTClass Serial3;
#define RX1 6
#define TX1 7
#define SDA 10
#define SCL 9
#define SDA 31
#define SCL 30
static const uint8_t SS = SPI0_CS0 ;
static const uint8_t MOSI = SPI0_MOSI;