Skip to content

Commit 924e44b

Browse files
Fix I2C slave test on STM32 (#455)
* Start testing STM32U0 with test shield, make a few fixes * Fix I2C slave not working on STM if you set the frequency after initializing * Add handling of a partial write by the master * Fix wording
1 parent 37ace18 commit 924e44b

File tree

5 files changed

+41
-29
lines changed

5 files changed

+41
-29
lines changed

hal/include/hal/i2c_api.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ int i2c_slave_receive(i2c_t *obj);
323323
* @param obj The I2C object
324324
* @param data The buffer for receiving
325325
* @param length Number of bytes to read
326-
* @return non-zero if a value is available, or zero on error
326+
* @return Number of bytes read, or zero on error
327327
*/
328328
int i2c_slave_read(i2c_t *obj, char *data, int length);
329329

targets/TARGET_STM/TARGET_STM32U0/stm_dma_info.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@
2626

2727
/// Mapping from SPI index to DMA link info for Tx
2828
static const DMALinkInfo SPITxDMALinks[] = {
29-
{1, 0, DMA_REQUEST_SPI1_TX},
30-
{1, 2, DMA_REQUEST_SPI2_TX},
29+
{1, 2, DMA_REQUEST_SPI1_TX},
30+
{1, 4, DMA_REQUEST_SPI2_TX},
3131
#if defined (SPI3)
32-
{1, 4, DMA_REQUEST_SPI3_TX}
32+
{1, 6, DMA_REQUEST_SPI3_TX}
3333
#endif
3434
};
3535

targets/TARGET_STM/i2c_api.c

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,17 @@ void i2c_init_internal(i2c_t *obj, const i2c_pinmap_t *pinmap)
548548
obj_s->hz = 100000; // 100 kHz per default
549549
}
550550

551+
// Set remaining init parameters to defaults
552+
obj_s->handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
553+
obj_s->handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
554+
obj_s->handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
555+
obj_s->handle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
556+
obj_s->handle.Init.OwnAddress1 = 0;
557+
obj_s->handle.Init.OwnAddress2 = 0;
558+
#ifdef I2C_IP_VERSION_V2
559+
obj_s->handle.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
560+
#endif
561+
551562
// Reset to clear pending flags if any
552563
i2c_hw_reset(obj);
553564
i2c_frequency(obj, obj_s->hz);
@@ -784,19 +795,15 @@ void i2c_frequency(i2c_t *obj, int hz)
784795
/* hz value is stored for computing timing value next time */
785796
obj_s->current_hz = hz;
786797
#endif // I2C_IP_VERSION_V2
787-
788-
// I2C configuration
789-
handle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
790-
handle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
791-
handle->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
792-
handle->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
793-
handle->Init.OwnAddress1 = 0;
794-
handle->Init.OwnAddress2 = 0;
795-
#ifdef I2C_IP_VERSION_V2
796-
handle->Init.OwnAddress2Masks = I2C_OA2_NOMASK;
797-
#endif
798+
798799
HAL_I2C_Init(handle);
799800

801+
// In slave mode, reenable slave interrupts after calling init
802+
if(obj_s->slave != 0)
803+
{
804+
HAL_I2C_EnableListen_IT(&obj_s->handle);
805+
}
806+
800807
/* store frequency for timeout computation */
801808
obj_s->hz = hz;
802809
}
@@ -1120,11 +1127,11 @@ int i2c_byte_read(i2c_t *obj, int last)
11201127
if (last) {
11211128
/* Disable Address Acknowledge */
11221129
tmpreg = tmpreg & (~I2C_CR2_RELOAD);
1123-
tmpreg |= I2C_CR2_NACK | (I2C_CR2_NBYTES & (1 << 16));
1130+
tmpreg |= I2C_CR2_NACK | (1 << I2C_CR2_NBYTES_Pos);
11241131
} else {
11251132
/* Enable reload mode as we don't know how many bytes will be sent */
11261133
/* and set transfer size to 1 */
1127-
tmpreg |= I2C_CR2_RELOAD | (I2C_CR2_NBYTES & (1 << 16));
1134+
tmpreg |= I2C_CR2_RELOAD | (1 << I2C_CR2_NBYTES_Pos);
11281135
}
11291136

11301137
/* Set the prepared configuration */
@@ -1505,15 +1512,15 @@ void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
15051512
uint32_t event_code = 0;
15061513

15071514
#if DEVICE_I2CSLAVE
1508-
uint32_t address = 0;
1509-
/* Store address to handle it after reset */
1510-
if (obj_s->slave) {
1511-
address = handle->Init.OwnAddress1;
1515+
if(obj_s->slave_rx_transfer_in_progress && handle->ErrorCode == HAL_I2C_ERROR_AF) {
1516+
// We get here if the master ended a write operation after fewer than expected
1517+
// bytes. Just mark the slave transfer as done and return.
1518+
obj_s->slave_rx_transfer_in_progress = 0;
1519+
return;
15121520
}
15131521
#endif
15141522

1515-
1516-
if ((handle->ErrorCode & HAL_I2C_ERROR_AF) == HAL_I2C_ERROR_AF) {
1523+
if (handle->ErrorCode & HAL_I2C_ERROR_AF) {
15171524
/* Keep Set event flag */
15181525
event_code = (I2C_EVENT_TRANSFER_EARLY_NACK) | (I2C_EVENT_ERROR_NO_SLAVE);
15191526
}
@@ -1528,6 +1535,14 @@ void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
15281535

15291536
DEBUG_PRINTF("HAL_I2C_ErrorCallback:%d, index=%d\r\n", (int) hi2c->ErrorCode, obj_s->index);
15301537

1538+
#if DEVICE_I2CSLAVE
1539+
uint32_t address = 0;
1540+
/* Store address to handle it after reset */
1541+
if (obj_s->slave) {
1542+
address = handle->Init.OwnAddress1;
1543+
}
1544+
#endif
1545+
15311546
/* re-init IP to try and get back in a working state */
15321547
i2c_init_internal(obj, NULL);
15331548

@@ -1710,7 +1725,7 @@ int i2c_slave_read(i2c_t *obj, char *data, int length)
17101725
if (obj_s->slave == SLAVE_MODE_LISTEN) {
17111726
count = obj_s->slave_rx_count;
17121727
} else {
1713-
count = _length;
1728+
count = length - handle->XferCount;
17141729
}
17151730
} else {
17161731
DEBUG_PRINTF("TIMEOUT or error in i2c_slave_read\r\n");

targets/targets.json5

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4803,10 +4803,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.",
48034803
"TRNG",
48044804
//"USBDEVICE" // TODO
48054805
],
4806-
"device_has_remove": [
4807-
"I2C", // Not tested just prepared
4808-
"I2CSLAVE" // Not tested just prepared
4809-
],
48104806
"is_mcu_family_target": true
48114807
},
48124808
"MCU_STM32U083xC": {

tools/cmake/upload_methods/UploadMethodOPENOCD.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ function(gen_upload_target TARGET_NAME BINARY_FILE)
4848
${OPENOCD_ADAPTER_SERIAL_COMMAND}
4949
-c "gdb_port disabled" # Don't start a GDB server when just programming
5050
-c "program ${BINARY_FILE} ${MBED_UPLOAD_BASE_ADDR} reset exit"
51-
VERBATIM)
51+
VERBATIM
52+
USES_TERMINAL)
5253

5354
endfunction(gen_upload_target)
5455

0 commit comments

Comments
 (0)