From 01a18ef9cb1698706d501af95d2b828f6e4008cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 2 Apr 2022 03:54:53 +0200 Subject: [PATCH] make it work! --- Core/Inc/i2c_gateway.h | 9 + Core/Inc/stm32f1xx_it.h | 2 + Core/Src/freertos.c | 4 +- Core/Src/i2c.c | 11 +- Core/Src/i2c_gateway.c | 181 ++++++++++++++++++ Core/Src/stm32f1xx_it.c | 29 +++ .../Src/stm32f1xx_hal_i2c.c | 7 +- Makefile | 3 +- USB_DEVICE/App/usbd_cdc_if.c | 6 +- USB_DEVICE/App/usbd_cdc_if.h | 1 + bluepill-i2c-gw.ioc | 4 +- 11 files changed, 247 insertions(+), 10 deletions(-) create mode 100644 Core/Inc/i2c_gateway.h create mode 100644 Core/Src/i2c_gateway.c diff --git a/Core/Inc/i2c_gateway.h b/Core/Inc/i2c_gateway.h new file mode 100644 index 0000000..db9d789 --- /dev/null +++ b/Core/Inc/i2c_gateway.h @@ -0,0 +1,9 @@ +#ifndef I2C_GATEWAY_H +#define I2C_GATEWAY_H + +#include +#include + +void i2c_command(uint8_t *packet, size_t len); + +#endif //I2C_GATEWAY_H diff --git a/Core/Inc/stm32f1xx_it.h b/Core/Inc/stm32f1xx_it.h index 4667992..4b98923 100644 --- a/Core/Inc/stm32f1xx_it.h +++ b/Core/Inc/stm32f1xx_it.h @@ -55,6 +55,8 @@ void DebugMon_Handler(void); void USB_HP_CAN1_TX_IRQHandler(void); void USB_LP_CAN1_RX0_IRQHandler(void); void TIM1_UP_IRQHandler(void); +void I2C1_EV_IRQHandler(void); +void I2C1_ER_IRQHandler(void); /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ diff --git a/Core/Src/freertos.c b/Core/Src/freertos.c index f7e4313..15e67d6 100644 --- a/Core/Src/freertos.c +++ b/Core/Src/freertos.c @@ -150,14 +150,14 @@ void StartDefaultTask(void *argument) //HAL_HalfDuplex_EnableTransmitter(&huart1); /* Infinite loop */ - int cnt = 0; + //int cnt = 0; for (;;) { vTaskDelay(pdMS_TO_TICKS(500)); HAL_IWDG_Refresh(&hiwdg); HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); - printf("Hello, count is %d\r\n", cnt++); + //printf("Hello, count is %d\r\n", cnt++); } /* USER CODE END StartDefaultTask */ diff --git a/Core/Src/i2c.c b/Core/Src/i2c.c index e3a7339..93b83d4 100644 --- a/Core/Src/i2c.c +++ b/Core/Src/i2c.c @@ -45,7 +45,7 @@ void MX_I2C1_Init(void) hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; - hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_ENABLE; + hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); @@ -78,6 +78,12 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle) /* I2C1 clock enable */ __HAL_RCC_I2C1_CLK_ENABLE(); + + /* I2C1 interrupt Init */ + HAL_NVIC_SetPriority(I2C1_EV_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(I2C1_EV_IRQn); + HAL_NVIC_SetPriority(I2C1_ER_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(I2C1_ER_IRQn); /* USER CODE BEGIN I2C1_MspInit 1 */ /* USER CODE END I2C1_MspInit 1 */ @@ -103,6 +109,9 @@ void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle) HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7); + /* I2C1 interrupt Deinit */ + HAL_NVIC_DisableIRQ(I2C1_EV_IRQn); + HAL_NVIC_DisableIRQ(I2C1_ER_IRQn); /* USER CODE BEGIN I2C1_MspDeInit 1 */ /* USER CODE END I2C1_MspDeInit 1 */ diff --git a/Core/Src/i2c_gateway.c b/Core/Src/i2c_gateway.c new file mode 100644 index 0000000..85eaa36 --- /dev/null +++ b/Core/Src/i2c_gateway.c @@ -0,0 +1,181 @@ +#include +#include +#include "main.h" +#include "usbd_cdc_if.h" + +#define I2C_DEBUG 0 + +#define I2C_MTU 512 + +#define HAL_CHECK(x) do { \ + int rv = (x); \ + if (rv != HAL_OK) { \ + printf("HAL ERR %d at %s:%d\r\n", rv, __FILE__, __LINE__); \ + }\ +} while (0) + +/** + * Packet format: + * + * Transmit packets + * LEN_MSB LEN_LSB ADDR Bytes... + * + * LEN does not include the length field itself! + * + * Command packets are sent as ADDR=255 + * 0xFF CMD ARGs... + * - Set address: 0x01 ADDR + * - Set speed: 0x02 Speed TODO!! + * - Speed 1 ... 100kHz + * - Speed 4 ... 400kHz + */ + +#define COMMAND_ADDRESS 0xFF +#define CMD_SET_ADDR 1 // the next param is the address, without shifting (i.e. 1-127) +#define CMD_SET_SPEED 2 // speed is 1 or 4 (100khz, 400khz) + +enum FrameState { + FRAME_LEN_MSB, + FRAME_LEN_LSB, + FRAME_PAYLOAD, +}; + +static uint16_t framelen = 0; +static uint8_t i2c_recbuf[I2C_MTU + 3] = {}; +static size_t recbuf_wp = 0; +static size_t framestate = FRAME_LEN_MSB; +static uint32_t last_rx_tick; +#define CMD_TIMEOUT_TICKS 500 + + +static void handle_pkt(uint8_t *packet, size_t len); +static void handle_control_pkt(uint8_t *packet, size_t len); + +void i2c_command(uint8_t *packet, size_t len) +{ + uint32_t now = HAL_GetTick(); + if (framestate != FRAME_LEN_MSB && (now - last_rx_tick) > CMD_TIMEOUT_TICKS) { + framestate = FRAME_LEN_MSB; + } + last_rx_tick = now; + + for (int i=0; i= framelen) { + handle_pkt(i2c_recbuf, framelen); + framestate = FRAME_LEN_MSB; + } + break; + } + } +} + +static void handle_pkt(uint8_t *packet, size_t len) +{ +#if I2C_DEBUG + printf("Handle packet (%d bytes): ", len); + for(int i=0; i%d\r\n", len - 1, dest); +#endif + + // Blocking transfer + HAL_CHECK(HAL_I2C_DisableListen_IT(&hi2c1)); + HAL_CHECK(HAL_I2C_Master_Transmit(&hi2c1, (dest & 0x7F) << 1, &packet[1], len - 1, 100)); + HAL_CHECK(HAL_I2C_EnableListen_IT(&hi2c1)); + } +} + +static void handle_control_pkt(uint8_t *packet, size_t len) +{ + uint8_t cmd = packet[1]; + uint8_t arg; + + switch (cmd) { + case CMD_SET_ADDR: + if (len < 3) return; + arg = packet[2]; + printf("Addr=0x%02x\r\n", arg); + MODIFY_REG(hi2c1.Instance->OAR1, + (I2C_OAR1_ADDMODE | I2C_OAR1_ADD8_9 | I2C_OAR1_ADD1_7 | I2C_OAR1_ADD0), + (I2C_ADDRESSINGMODE_7BIT | ((arg & 0x7F) << 1) )); + HAL_CHECK(HAL_I2C_EnableListen_IT(&hi2c1)); + break; + + default: + printf("bad cmd!\r\n"); + } +} + +/** + * @brief Slave Address Match callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param TransferDirection Master request Transfer Direction (Write/Read), value of @ref I2C_XferDirection_definition + * @param AddrMatchCode Address Match Code + * @retval None + */ +void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) +{ + HAL_CHECK(HAL_I2C_Slave_Seq_Receive_IT(hi2c, i2c_recbuf, I2C_MTU, I2C_FIRST_AND_LAST_FRAME)); +} + +/** + * @brief Slave Rx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + int numBytes = I2C_MTU - hi2c->XferCount; +#if I2C_DEBUG + printf("rxd %d\r\n", numBytes); +#endif + + UserTxBufferFS[0] = (numBytes >> 8) & 0xFF; + UserTxBufferFS[1] = numBytes & 0xFF; + memcpy(&UserTxBufferFS[2], i2c_recbuf, numBytes); + + CDC_Transmit_FS(UserTxBufferFS, numBytes + 2); +} + +/** + * @brief Listen Complete callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c) +{ + // Start again + HAL_CHECK(HAL_I2C_EnableListen_IT(hi2c)); +} diff --git a/Core/Src/stm32f1xx_it.c b/Core/Src/stm32f1xx_it.c index 05982aa..830a83a 100644 --- a/Core/Src/stm32f1xx_it.c +++ b/Core/Src/stm32f1xx_it.c @@ -56,6 +56,7 @@ /* External variables --------------------------------------------------------*/ extern PCD_HandleTypeDef hpcd_USB_FS; +extern I2C_HandleTypeDef hi2c1; extern TIM_HandleTypeDef htim1; /* USER CODE BEGIN EV */ @@ -202,6 +203,34 @@ void TIM1_UP_IRQHandler(void) /* USER CODE END TIM1_UP_IRQn 1 */ } +/** + * @brief This function handles I2C1 event interrupt. + */ +void I2C1_EV_IRQHandler(void) +{ + /* USER CODE BEGIN I2C1_EV_IRQn 0 */ + + /* USER CODE END I2C1_EV_IRQn 0 */ + HAL_I2C_EV_IRQHandler(&hi2c1); + /* USER CODE BEGIN I2C1_EV_IRQn 1 */ + + /* USER CODE END I2C1_EV_IRQn 1 */ +} + +/** + * @brief This function handles I2C1 error interrupt. + */ +void I2C1_ER_IRQHandler(void) +{ + /* USER CODE BEGIN I2C1_ER_IRQn 0 */ + + /* USER CODE END I2C1_ER_IRQn 0 */ + HAL_I2C_ER_IRQHandler(&hi2c1); + /* USER CODE BEGIN I2C1_ER_IRQn 1 */ + + /* USER CODE END I2C1_ER_IRQn 1 */ +} + /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ diff --git a/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c b/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c index 45506a2..47869d6 100644 --- a/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c +++ b/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c @@ -6356,12 +6356,13 @@ static void I2C_Slave_STOPF(I2C_HandleTypeDef *hi2c) if (hi2c->XferCount != 0U) { - /* Set ErrorCode corresponding to a Non-Acknowledge */ - hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; } } - if (hi2c->ErrorCode != HAL_I2C_ERROR_NONE) + // HACK - ignore HAL_I2C_ERROR_AF + if (hi2c->ErrorCode != HAL_I2C_ERROR_NONE && hi2c->ErrorCode != HAL_I2C_ERROR_AF) { /* Call the corresponding callback to inform upper layer of End of Transfer */ I2C_ITError(hi2c); diff --git a/Makefile b/Makefile index 865da83..167957d 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ ########################################################################################################################## -# File automatically-generated by tool: [projectgenerator] version: [3.16.0] date: [Fri Apr 01 20:27:44 CEST 2022] +# File automatically-generated by tool: [projectgenerator] version: [3.16.0] date: [Fri Apr 01 20:41:48 CEST 2022] ########################################################################################################################## .PHONY: flash @@ -40,6 +40,7 @@ BUILD_DIR = build C_SOURCES = \ Core/Src/main.c \ Core/Src/logging.c \ +Core/Src/i2c_gateway.c \ Core/Src/freertos.c \ Core/Src/stm32f1xx_it.c \ Core/Src/stm32f1xx_hal_msp.c \ diff --git a/USB_DEVICE/App/usbd_cdc_if.c b/USB_DEVICE/App/usbd_cdc_if.c index 182c490..f1175dc 100644 --- a/USB_DEVICE/App/usbd_cdc_if.c +++ b/USB_DEVICE/App/usbd_cdc_if.c @@ -22,6 +22,7 @@ #include "usbd_cdc_if.h" /* USER CODE BEGIN INCLUDE */ +#include "i2c_gateway.h" /* USER CODE END INCLUDE */ @@ -259,11 +260,12 @@ static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length) static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) { /* USER CODE BEGIN 6 */ - printf("Rx %d b\r\n", (int) *Len); - printf("Bytes: %.*s\r\n", (int) *Len, Buf); + + i2c_command(Buf, *Len); USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); USBD_CDC_ReceivePacket(&hUsbDeviceFS); + return (USBD_OK); /* USER CODE END 6 */ } diff --git a/USB_DEVICE/App/usbd_cdc_if.h b/USB_DEVICE/App/usbd_cdc_if.h index 40894db..f69dd12 100644 --- a/USB_DEVICE/App/usbd_cdc_if.h +++ b/USB_DEVICE/App/usbd_cdc_if.h @@ -51,6 +51,7 @@ #define APP_RX_DATA_SIZE 1000 #define APP_TX_DATA_SIZE 1000 /* USER CODE BEGIN EXPORTED_DEFINES */ +extern uint8_t UserTxBufferFS[APP_TX_DATA_SIZE]; /* USER CODE END EXPORTED_DEFINES */ diff --git a/bluepill-i2c-gw.ioc b/bluepill-i2c-gw.ioc index 83a5d95..8ba1864 100644 --- a/bluepill-i2c-gw.ioc +++ b/bluepill-i2c-gw.ioc @@ -52,6 +52,8 @@ NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:true NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:true NVIC.ForceEnableDMAVector=true NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:true +NVIC.I2C1_ER_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true +NVIC.I2C1_EV_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:true NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:true NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:false\:true @@ -148,7 +150,7 @@ USB_DEVICE.IPParameters=VirtualMode,VirtualModeFS,CLASS_NAME_FS,USBD_DEBUG_LEVEL USB_DEVICE.MANUFACTURER_STRING=VZLU USB_DEVICE.PID_CDC_FS=7717 USB_DEVICE.PRODUCT_STRING_CDC_FS=VZLU I2C GW -USB_DEVICE.USBD_DEBUG_LEVEL=2 +USB_DEVICE.USBD_DEBUG_LEVEL=0 USB_DEVICE.VirtualMode=Cdc USB_DEVICE.VirtualModeFS=Cdc_FS VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2