提交 b145e659 编写于 作者: M me-no-dev

API Optimizations

- Support Wire::end() for Slave
- Prevent Master operations when in Slave mode
上级 951c3205
......@@ -181,6 +181,7 @@ static inline bool i2c_ll_slave_rw(i2c_dev_t *hw)//not exposed by hal_ll
}
//-------------------------------------- PRIVATE (Function Prototypes) ------------------------------------------------
static void i2c_slave_free_resources(i2c_slave_struct_t * i2c);
static void i2c_slave_delay_us(uint64_t us);
static void i2c_slave_gpio_mode(int8_t pin, gpio_mode_t mode);
static bool i2c_slave_check_line_state(int8_t sda, int8_t scl);
......@@ -199,7 +200,7 @@ static void i2c_slave_task(void *pv_args);
//-------------------------------------- Public Functions -------------------------------------------------------------
//=====================================================================================================================
esp_err_t i2c_slave_attach_callbacks(uint8_t num, i2c_slave_request_cb_t request_callback, i2c_slave_receive_cb_t receive_callback, void * arg){
esp_err_t i2cSlaveAttachCallbacks(uint8_t num, i2c_slave_request_cb_t request_callback, i2c_slave_receive_cb_t receive_callback, void * arg){
if(num >= SOC_I2C_NUM){
log_e("Invalid port num: %u", num);
return ESP_ERR_INVALID_ARG;
......@@ -213,57 +214,7 @@ esp_err_t i2c_slave_attach_callbacks(uint8_t num, i2c_slave_request_cb_t request
return ESP_OK;
}
esp_err_t i2c_slave_deinit(uint8_t num){
if(num >= SOC_I2C_NUM){
log_e("Invalid port num: %u", num);
return ESP_ERR_INVALID_ARG;
}
i2c_slave_struct_t * i2c = &_i2c_bus_array[num];
I2C_SLAVE_MUTEX_LOCK();
i2c_slave_detach_gpio(i2c);
i2c_ll_set_slave_addr(i2c->dev, 0, false);
i2c_ll_disable_intr_mask(i2c->dev, I2C_LL_INTR_MASK);
i2c_ll_clr_intsts_mask(i2c->dev, I2C_LL_INTR_MASK);
if (i2c->intr_handle) {
esp_intr_free(i2c->intr_handle);
i2c->intr_handle = NULL;
}
if(i2c->task_handle){
vTaskDelete(i2c->task_handle);
i2c->task_handle = NULL;
}
#if I2C_SLAVE_USE_RX_QUEUE
if (i2c->rx_queue) {
vQueueDelete(i2c->rx_queue);
i2c->rx_queue = NULL;
}
#else
if (i2c->rx_ring_buf) {
vRingbufferDelete(i2c->rx_ring_buf);
i2c->rx_ring_buf = NULL;
}
#endif
if (i2c->tx_queue) {
vQueueDelete(i2c->tx_queue);
i2c->tx_queue = NULL;
}
if (i2c->event_queue) {
vQueueDelete(i2c->event_queue);
i2c->event_queue = NULL;
}
i2c->rx_data_count = 0;
I2C_SLAVE_MUTEX_UNLOCK();
return ESP_OK;
}
esp_err_t i2c_slave_init(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t frequency, size_t rx_len, size_t tx_len) {
esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t frequency, size_t rx_len, size_t tx_len) {
if(num >= SOC_I2C_NUM){
log_e("Invalid port num: %u", num);
return ESP_ERR_INVALID_ARG;
......@@ -274,6 +225,12 @@ esp_err_t i2c_slave_init(uint8_t num, int sda, int scl, uint16_t slaveID, uint32
return ESP_ERR_INVALID_ARG;
}
if(!frequency){
frequency = 100000;
} else if(frequency > 1000000){
frequency = 1000000;
}
log_i("Initialising I2C Slave: sda=%d scl=%d freq=%d, addr=0x%x", sda, scl, frequency, slaveID);
i2c_slave_struct_t * i2c = &_i2c_bus_array[num];
......@@ -288,9 +245,9 @@ esp_err_t i2c_slave_init(uint8_t num, int sda, int scl, uint16_t slaveID, uint32
}
}
#endif
i2c_slave_deinit(num);
I2C_SLAVE_MUTEX_LOCK();
i2c_slave_free_resources(i2c);
#if I2C_SLAVE_USE_RX_QUEUE
i2c->rx_queue = xQueueCreate(rx_len, sizeof(uint8_t));
......@@ -391,18 +348,39 @@ esp_err_t i2c_slave_init(uint8_t num, int sda, int scl, uint16_t slaveID, uint32
return ret;
fail:
i2c_slave_free_resources(i2c);
I2C_SLAVE_MUTEX_UNLOCK();
i2c_slave_deinit(num);
return ret;
}
size_t i2c_slave_write(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms) {
esp_err_t i2cSlaveDeinit(uint8_t num){
if(num >= SOC_I2C_NUM){
log_e("Invalid port num: %u", num);
return ESP_ERR_INVALID_ARG;
}
i2c_slave_struct_t * i2c = &_i2c_bus_array[num];
if(!i2c->lock){
log_e("Lock is not initialized! Did you call i2c_slave_init()?");
return ESP_ERR_NO_MEM;
}
I2C_SLAVE_MUTEX_LOCK();
i2c_slave_free_resources(i2c);
I2C_SLAVE_MUTEX_UNLOCK();
return ESP_OK;
}
size_t i2cSlaveWrite(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms) {
if(num >= SOC_I2C_NUM){
log_e("Invalid port num: %u", num);
return 0;
}
size_t to_queue = 0, to_fifo = 0;
i2c_slave_struct_t * i2c = &_i2c_bus_array[num];
if(!i2c->lock){
log_e("Lock is not initialized! Did you call i2c_slave_init()?");
return ESP_ERR_NO_MEM;
}
if(!i2c->tx_queue){
return 0;
}
......@@ -460,6 +438,47 @@ size_t i2c_slave_write(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t t
//-------------------------------------- Private Functions ------------------------------------------------------------
//=====================================================================================================================
static void i2c_slave_free_resources(i2c_slave_struct_t * i2c){
i2c_slave_detach_gpio(i2c);
i2c_ll_set_slave_addr(i2c->dev, 0, false);
i2c_ll_disable_intr_mask(i2c->dev, I2C_LL_INTR_MASK);
i2c_ll_clr_intsts_mask(i2c->dev, I2C_LL_INTR_MASK);
if (i2c->intr_handle) {
esp_intr_free(i2c->intr_handle);
i2c->intr_handle = NULL;
}
if(i2c->task_handle){
vTaskDelete(i2c->task_handle);
i2c->task_handle = NULL;
}
#if I2C_SLAVE_USE_RX_QUEUE
if (i2c->rx_queue) {
vQueueDelete(i2c->rx_queue);
i2c->rx_queue = NULL;
}
#else
if (i2c->rx_ring_buf) {
vRingbufferDelete(i2c->rx_ring_buf);
i2c->rx_ring_buf = NULL;
}
#endif
if (i2c->tx_queue) {
vQueueDelete(i2c->tx_queue);
i2c->tx_queue = NULL;
}
if (i2c->event_queue) {
vQueueDelete(i2c->event_queue);
i2c->event_queue = NULL;
}
i2c->rx_data_count = 0;
}
static bool i2c_slave_set_frequency(i2c_slave_struct_t * i2c, uint32_t clk_speed)
{
if (i2c == NULL) {
......@@ -610,7 +629,7 @@ static bool i2c_slave_send_event(i2c_slave_struct_t * i2c, i2c_slave_queue_event
bool pxHigherPriorityTaskWoken = false;
if(i2c->event_queue) {
if(xQueueSendFromISR(i2c->event_queue, event, (BaseType_t * const)&pxHigherPriorityTaskWoken) != pdTRUE){
log_e("event_queue_full");
//log_e("event_queue_full");
}
}
return pxHigherPriorityTaskWoken;
......@@ -684,7 +703,7 @@ static void i2c_slave_isr_handler(void* arg)
if(rx_fifo_len){ //READ RX FIFO
pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len);
}
if(!slave_rw || i2c->rx_data_count){ //WRITE or RepeatedStart
if(i2c->rx_data_count){ //WRITE or RepeatedStart
//SEND RX Event
i2c_slave_queue_event_t event;
event.event = I2C_SLAVE_EVT_RX;
......
......@@ -24,11 +24,11 @@ extern "C" {
typedef void (*i2c_slave_request_cb_t) (uint8_t num, void * arg);
typedef void (*i2c_slave_receive_cb_t) (uint8_t num, uint8_t * data, size_t len, bool stop, void * arg);
esp_err_t i2c_slave_attach_callbacks(uint8_t num, i2c_slave_request_cb_t request_callback, i2c_slave_receive_cb_t receive_callback, void * arg);
esp_err_t i2cSlaveAttachCallbacks(uint8_t num, i2c_slave_request_cb_t request_callback, i2c_slave_receive_cb_t receive_callback, void * arg);
esp_err_t i2c_slave_init(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t frequency, size_t rx_len, size_t tx_len);
esp_err_t i2c_slave_deinit(uint8_t num);
size_t i2c_slave_write(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms);
esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t frequency, size_t rx_len, size_t tx_len);
esp_err_t i2cSlaveDeinit(uint8_t num);
size_t i2cSlaveWrite(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms);
#ifdef __cplusplus
}
......
......@@ -63,6 +63,47 @@ TwoWire::~TwoWire()
#endif
}
bool TwoWire::initPins(int sdaPin, int sclPin)
{
if(sdaPin < 0) { // default param passed
if(num == 0) {
if(sda==-1) {
sdaPin = SDA; //use Default Pin
} else {
sdaPin = sda; // reuse prior pin
}
} else {
if(sda==-1) {
log_e("no Default SDA Pin for Second Peripheral");
return false; //no Default pin for Second Peripheral
} else {
sdaPin = sda; // reuse prior pin
}
}
}
if(sclPin < 0) { // default param passed
if(num == 0) {
if(scl == -1) {
sclPin = SCL; // use Default pin
} else {
sclPin = scl; // reuse prior pin
}
} else {
if(scl == -1) {
log_e("no Default SCL Pin for Second Peripheral");
return false; //no Default pin for Second Peripheral
} else {
sclPin = scl; // reuse prior pin
}
}
}
sda = sdaPin;
scl = sclPin;
return true;
}
bool TwoWire::setPins(int sdaPin, int sclPin)
{
#if !CONFIG_DISABLE_HAL_LOCKS
......@@ -80,8 +121,7 @@ bool TwoWire::setPins(int sdaPin, int sclPin)
}
#endif
if(!i2cIsInit(num)){
sda = sdaPin;
scl = sclPin;
initPins(sdaPin, sclPin);
} else {
log_e("bus already initialized. change pins only when not.");
}
......@@ -92,10 +132,10 @@ bool TwoWire::setPins(int sdaPin, int sclPin)
return !i2cIsInit(num);
}
bool TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
// Slave Begin
bool TwoWire::begin(uint8_t addr, int sdaPin, int sclPin, uint32_t frequency)
{
bool started = false;
esp_err_t err = ESP_OK;
#if !CONFIG_DISABLE_HAL_LOCKS
if(lock == NULL){
lock = xSemaphoreCreateMutex();
......@@ -110,46 +150,64 @@ bool TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
return false;
}
#endif
if(i2cIsInit(num)){
if(is_slave){
log_w("Bus already started in Slave Mode.");
started = true;
goto end;
}
if(sdaPin < 0) { // default param passed
if(num == 0) {
if(sda==-1) {
sdaPin = SDA; //use Default Pin
} else {
sdaPin = sda; // reuse prior pin
}
} else {
if(sda==-1) {
log_e("no Default SDA Pin for Second Peripheral");
goto end; //no Default pin for Second Peripheral
} else {
sdaPin = sda; // reuse prior pin
}
}
if(i2cIsInit(num)){
log_e("Bus already started in Master Mode.");
goto end;
}
if(!initPins(sdaPin, sclPin)){
goto end;
}
i2cSlaveAttachCallbacks(num, onRequestService, onReceiveService, this);
if(i2cSlaveInit(num, sda, scl, addr, frequency, I2C_BUFFER_LENGTH, I2C_BUFFER_LENGTH) != ESP_OK){
log_e("Slave Init ERROR");
goto end;
}
is_slave = true;
started = true;
end:
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(lock);
#endif
return started;
}
if(sclPin < 0) { // default param passed
if(num == 0) {
if(scl == -1) {
sclPin = SCL; // use Default pin
} else {
sclPin = scl; // reuse prior pin
}
} else {
if(scl == -1) {
log_e("no Default SCL Pin for Second Peripheral");
goto end; //no Default pin for Second Peripheral
} else {
sclPin = scl; // reuse prior pin
}
// Master Begin
bool TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
{
bool started = false;
esp_err_t err = ESP_OK;
#if !CONFIG_DISABLE_HAL_LOCKS
if(lock == NULL){
lock = xSemaphoreCreateMutex();
if(lock == NULL){
log_e("xSemaphoreCreateMutex failed");
return false;
}
}
sda = sdaPin;
scl = sclPin;
//acquire lock
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
log_e("could not acquire lock");
return false;
}
#endif
if(is_slave){
log_e("Bus already started in Slave Mode.");
goto end;
}
if(i2cIsInit(num)){
log_w("Bus already started in Master Mode.");
started = true;
goto end;
}
if(!initPins(sdaPin, sclPin)){
goto end;
}
err = i2cInit(num, sda, scl, frequency);
started = (err == ESP_OK);
......@@ -173,7 +231,12 @@ bool TwoWire::end()
return false;
}
#endif
if(i2cIsInit(num)){
if(is_slave){
err = i2cSlaveDeinit(num);
if(err == ESP_OK){
is_slave = false;
}
} else if(i2cIsInit(num)){
err = i2cDeinit(num);
}
#if !CONFIG_DISABLE_HAL_LOCKS
......@@ -193,7 +256,11 @@ uint32_t TwoWire::getClock()
log_e("could not acquire lock");
} else {
#endif
i2cGetClock(num, &frequency);
if(is_slave){
log_e("Bus is in Slave Mode");
} else {
i2cGetClock(num, &frequency);
}
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(lock);
......@@ -212,7 +279,12 @@ bool TwoWire::setClock(uint32_t frequency)
return false;
}
#endif
err = i2cSetClock(num, frequency);
if(is_slave){
log_e("Bus is in Slave Mode");
err = ESP_FAIL;
} else {
err = i2cSetClock(num, frequency);
}
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(lock);
......@@ -232,6 +304,10 @@ uint16_t TwoWire::getTimeOut()
void TwoWire::beginTransmission(uint16_t address)
{
if(is_slave){
log_e("Bus is in Slave Mode");
return;
}
#if !CONFIG_DISABLE_HAL_LOCKS
if(nonStop && nonStopTask == xTaskGetCurrentTaskHandle()){
log_e("Unfinished Repeated Start transaction! Expected requestFrom, not beginTransmission! Clearing...");
......@@ -251,6 +327,10 @@ void TwoWire::beginTransmission(uint16_t address)
uint8_t TwoWire::endTransmission(bool sendStop)
{
if(is_slave){
log_e("Bus is in Slave Mode");
return 4;
}
esp_err_t err = ESP_OK;
if(sendStop){
err = i2cWrite(num, txAddress, txBuffer, txLength, _timeOutMillis);
......@@ -276,6 +356,10 @@ uint8_t TwoWire::endTransmission(bool sendStop)
uint8_t TwoWire::requestFrom(uint16_t address, uint8_t size, bool sendStop)
{
if(is_slave){
log_e("Bus is in Slave Mode");
return 0;
}
esp_err_t err = ESP_OK;
if(nonStop
#if !CONFIG_DISABLE_HAL_LOCKS
......@@ -406,62 +490,9 @@ uint8_t TwoWire::endTransmission(void)
return endTransmission(true);
}
bool TwoWire::begin(uint8_t addr, int sdaPin, int sclPin, uint32_t frequency)
{
if(!frequency){
frequency = 100000;
} else if(frequency > 1000000){
frequency = 1000000;
}
if(sdaPin < 0) { // default param passed
if(num == 0) {
if(sda==-1) {
sdaPin = SDA; //use Default Pin
} else {
sdaPin = sda; // reuse prior pin
}
} else {
if(sda==-1) {
log_e("no Default SDA Pin for Second Peripheral");
return false; //no Default pin for Second Peripheral
} else {
sdaPin = sda; // reuse prior pin
}
}
}
if(sclPin < 0) { // default param passed
if(num == 0) {
if(scl == -1) {
sclPin = SCL; // use Default pin
} else {
sclPin = scl; // reuse prior pin
}
} else {
if(scl == -1) {
log_e("no Default SCL Pin for Second Peripheral");
return false; //no Default pin for Second Peripheral
} else {
sclPin = scl; // reuse prior pin
}
}
}
sda = sdaPin;
scl = sclPin;
i2c_slave_attach_callbacks(num, onRequestService, onReceiveService, this);
if(i2c_slave_init(num, sda, scl, addr, frequency, I2C_BUFFER_LENGTH, I2C_BUFFER_LENGTH) != ESP_OK){
Serial.println("INIT ERROR");
return false;
}
is_slave = true;
return true;
}
size_t TwoWire::slaveWrite(const uint8_t * buffer, size_t len)
{
return i2c_slave_write(num, buffer, len, _timeOutMillis);
return i2cSlaveWrite(num, buffer, len, _timeOutMillis);
}
void TwoWire::onReceiveService(uint8_t num, uint8_t* inBytes, size_t numBytes, bool stop, void * arg)
......
......@@ -67,6 +67,7 @@ private:
void (*user_onReceive)(int);
static void onRequestService(uint8_t, void *);
static void onReceiveService(uint8_t, uint8_t*, size_t, bool, void *);
bool initPins(int sdaPin, int sclPin);
public:
TwoWire(uint8_t bus_num);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册