diff --git a/libraries/FlashStorage/src/FlashStorage.h b/libraries/FlashStorage/src/FlashStorage.h index a2787c3a..d563edf7 100644 --- a/libraries/FlashStorage/src/FlashStorage.h +++ b/libraries/FlashStorage/src/FlashStorage.h @@ -63,6 +63,7 @@ class FlashStorage for (uint32_t i = 0; i < _storage_size; i++) { buffer_[i] = src[i]; } + fmc_lock(); } uint32_t length() @@ -98,12 +99,16 @@ class FlashStorage void commit() { + fmc_unlock(); uint32_t address = data_area_start; uint32_t *ptrs = (uint32_t *)buffer_; do { uint16_t page_size = pageSizeForAddress(address); + /* clear all pending flags */ + fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR); fmc_page_erase(address); + fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR); uint32_t word_count = page_size / 4; uint32_t i = 0; @@ -113,5 +118,7 @@ class FlashStorage address += 4U; } while (++i < word_count); } while (address < fmc_end_address); + fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR); + fmc_lock(); } }; diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index 7114b4b9..70887bf4 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -305,14 +305,11 @@ void TwoWire::onRequestService(void* pWireObj) pWire->_tx_buffer.tail = 0; // reset slave tx buffer iterator vars - pWire->_i2c.tx_buffer_ptr = pWire->_tx_buffer.buffer; + // pWire->_i2c.tx_buffer_ptr = pWire->_tx_buffer.buffer; pWire->_i2c.tx_count = 0; // alert user program pWire->user_onRequest(); - - // reset slave tx buffer iterator to let interrupt transmit the buffer - pWire->_i2c.tx_buffer_ptr = pWire->_tx_buffer.buffer; } } diff --git a/libraries/Wire/src/utility/twi.cpp b/libraries/Wire/src/utility/twi.cpp index 6728fe50..8f33e082 100644 --- a/libraries/Wire/src/utility/twi.cpp +++ b/libraries/Wire/src/utility/twi.cpp @@ -543,12 +543,13 @@ void i2c_attach_slave_tx_callback(i2c_t *obj, void (*function)(void*), void* pWi */ i2c_status_enum i2c_slave_write_buffer(i2c_t *obj, uint8_t *data, uint16_t length){ struct i2c_s *obj_s = I2C_S(obj); - if ( (obj_s->tx_count + length) > obj->tx_rx_buffer_size) + if ((obj_s->tx_count + length) > obj->tx_rx_buffer_size){ return I2C_DATA_TOO_LONG; + } - for (uint8_t i = 0; i < length; i++) - *obj_s->tx_buffer_ptr++ = *(data + i); - obj_s->tx_count += length; + for (uint8_t i = 0; i < length; i++){ + *(obj_s->tx_buffer_ptr + obj_s->tx_count++) = *(data + i); + } return I2C_OK; } @@ -614,6 +615,9 @@ void i2c_err_handler(uint32_t i2c) } } +volatile uint8_t snd_count; +volatile uint8_t rx_count; +volatile bool is_transmitter = false; /** This function handles I2C interrupt handler * @@ -629,34 +633,52 @@ static void i2c_irq(struct i2c_s *obj_s) if (i2c_interrupt_flag_get(i2c, I2C_INT_FLAG_ADDSEND)) { /* clear the ADDSEND bit */ i2c_interrupt_flag_clear(i2c, I2C_INT_FLAG_ADDSEND); - //memset(_rx_Buffer, _rx_count, 0); - obj_s->rx_count = 0; + if (i2c_flag_get(i2c, GD32_I2C_FLAG_IS_TRANSMTR_OR_RECVR)) { - obj_s->slave_transmit_callback(obj_s->pWireObj); + is_transmitter = true; + obj_s->slave_transmit_callback(obj_s->pWireObj); // onRequestService + snd_count = 0; } - } else if ((i2c_interrupt_flag_get(i2c, I2C_INT_FLAG_TBE)) && - (!i2c_interrupt_flag_get(i2c, I2C_INT_FLAG_AERR))) { - /* Send a data byte */ - if (obj_s->tx_count > 0) { - i2c_data_transmit(i2c, *obj_s->tx_buffer_ptr++); - obj_s->tx_count--; + else { + is_transmitter = false; + rx_count = 0; } - } else if (i2c_interrupt_flag_get(i2c, I2C_INT_FLAG_RBNE)) { - /* if reception data register is not empty, I2C1 will read a data from I2C_DATA */ - /* also check that our RX buffer has enough space for it */ - if(obj_s->rx_count < obj_s->tx_rx_buffer_size) { - *obj_s->rx_buffer_ptr++ = i2c_data_receive(i2c); - obj_s->rx_count++; - } else { - /* indicate RX buffer too small */ + } + + if (is_transmitter) + { + if ((i2c_interrupt_flag_get(i2c, I2C_INT_FLAG_TBE)) && + (!i2c_interrupt_flag_get(i2c, I2C_INT_FLAG_AERR))) + { + /* Send a data byte */ + if (snd_count < obj_s->tx_count) + { + i2c_data_transmit(i2c, *(obj_s->tx_buffer_ptr + snd_count++)); + } + } + else { + i2c_interrupt_flag_clear(i2c, I2C_INT_FLAG_AERR); } - } else if (i2c_interrupt_flag_get(i2c, I2C_INT_FLAG_STPDET)) { + } + else { + if (i2c_interrupt_flag_get(i2c, I2C_INT_FLAG_RBNE)) { + /* if reception data register is not empty, I2C1 will read a data from I2C_DATA */ + /* also check that our RX buffer has enough space for it */ + if(rx_count < obj_s->tx_rx_buffer_size) { + *(obj_s->rx_buffer_ptr + rx_count++) = i2c_data_receive(i2c); + } else { + /* indicate RX buffer too small */ + } + } + } + + if (i2c_interrupt_flag_get(i2c, I2C_INT_FLAG_STPDET)) { + if (!is_transmitter) { + obj_s->slave_receive_callback(obj_s->pWireObj, (uint8_t*)obj_s->rx_buffer_ptr, rx_count); // onReceiveService + } + /* clear the STPDET bit */ i2c_enable(i2c); - if (!i2c_flag_get(i2c, GD32_I2C_FLAG_IS_TRANSMTR_OR_RECVR)) { - obj_s->rx_buffer_ptr = obj_s->rx_buffer_ptr - obj_s->rx_count ; - obj_s->slave_receive_callback(obj_s->pWireObj, obj_s->rx_buffer_ptr, obj_s->rx_count); - } } } diff --git a/libraries/Wire/src/utility/twi.h b/libraries/Wire/src/utility/twi.h index f00763f3..89a70052 100644 --- a/libraries/Wire/src/utility/twi.h +++ b/libraries/Wire/src/utility/twi.h @@ -47,10 +47,10 @@ struct i2c_s { PinName sda; PinName scl; /* operating parameters */ - uint8_t *tx_buffer_ptr; - uint8_t *rx_buffer_ptr; - uint16_t tx_count; - uint16_t rx_count; + volatile uint8_t *tx_buffer_ptr; + volatile uint8_t *rx_buffer_ptr; + volatile uint16_t tx_count; + volatile uint16_t rx_count; /* TX and RX buffer are expected to be of this size */ uint16_t tx_rx_buffer_size;