BioWolf2000 3 5 июня, 2020 Опубликовано 5 июня, 2020 · Жалоба Добрый день. Я пытаюсь достучаться до встроенного загрузчика через другой микроконтроллер по протоколу I2C. RST выставляю в 0, BOOT0 в 1 и отпускаю RST //i2c 100kHz HAL_StatusTypeDef status; uint8_t tmp[2]; uint8_t dat[21]; uint8_t ACK; while(HAL_I2C_GetState(I2cHandle) != HAL_I2C_STATE_READY); status = HAL_I2C_Master_Transmit_IT(I2cHandle, 0xa6, dat, 1); while (HAL_I2C_GetState(I2cHandle) != HAL_I2C_STATE_READY) ; status = HAL_I2C_Master_Receive_IT(I2cHandle, 0xa6, &ACK, 1); while(1) { tmp[0] = 1;//Get Version command tmp[1] = 0xfe;//XOR tmp[0] while (HAL_I2C_GetState(I2cHandle) != HAL_I2C_STATE_READY) ; status = HAL_I2C_Master_Transmit_IT(I2cHandle, 0xa6, tmp, 2); memset(dat, 0, sizeof(dat)); while (HAL_I2C_GetState(I2cHandle) != HAL_I2C_STATE_READY) ; status = HAL_I2C_Master_Receive_IT(I2cHandle, 0xa6, &ACK, 1); if (ACK == 0x79) { while (HAL_I2C_GetState(I2cHandle) != HAL_I2C_STATE_READY) ; status = HAL_I2C_Master_Receive_IT(I2cHandle, 0xa6, dat, 2); //Практически всегда получаю нули. Иногда приходит 0x12 0xff } else if (ACK == 0x1f)//nack { //Иногда попадаю сюда } else if(ACK == 0x76)//busy { } else { } } В документе AN2606 слэйв адрес указан 0b1010100x. У меня получилось достучаться только по адресу 0b1010011x. Это ошибка документации? В AN4221 очень мало информации по протоколу. По коду, что выше, слэйв часто притягивает линию SCL до 10 секунд. ACK (0x76) получаю, иногда NACK. В ответ в массиве нули. Иногда проскакивает 0x12 0xff Как правильно работать с бутом по этому протоколу? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BioWolf2000 3 9 июня, 2020 Опубликовано 9 июня, 2020 · Жалоба Разобрался как принимать байты. Загрузчик работает только побайтно if (ACK == 0x79) { status = HAL_I2C_Master_Receive_IT(I2cHandle, 0xa6, &dat[0], 1); //https://www.st.com/resource/en/application_note/dm00072315-i2c-protocol-used-in-the-stm32-bootloader-stmicroelectronics.pdf //page 11 //Byte 2: Bootloader version (0 < Version ≤ 255) (for example, 0x10 = Version 1.0) while (HAL_I2C_GetState(I2cHandle) != HAL_I2C_STATE_READY) ; status = HAL_I2C_Master_Receive_IT(I2cHandle, 0xa6, &dat[1], 1); //Byte 3: ACK while (HAL_I2C_GetState(I2cHandle) != HAL_I2C_STATE_READY) ; } Пропали залипания линии SCL и начали приходить адекватные ответы Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BioWolf2000 3 11 июня, 2020 Опубликовано 11 июня, 2020 · Жалоба Привожу код, который заработал. Из-за дурацкой документации AN4221, пришлось повозиться и поподбирать последовательность команд #define GET_CMD_COMMAND 0x00U /*!< Get CMD command */ #define GET_VER_COMMAND 0x01U /*!< Get Version command */ #define GET_ID_COMMAND 0x02U /*!< Get ID command */ #define RMEM_COMMAND 0x11U /*!< Read Memory command */ #define GO_COMMAND 0x21U /*!< Go command */ #define WMEM_COMMAND 0x31U /*!< Write Memory command */ #define EMEM_COMMAND 0x44U /*!< Erase Memory command */ #define WP_COMMAND 0x63U /*!< Write Protect command */ #define WU_COMMAND 0x73U /*!< Write Unprotect command */ #define RP_COMMAND 0x82U /*!< Readout Protect command */ #define RU_COMMAND 0x92U /*!< Readout Unprotect command */ I2C_HandleTypeDef *I2cHandle; void BL_Init(I2C_HandleTypeDef *hi2c) { I2cHandle = hi2c; } HAL_StatusTypeDef BL_Transmit(uint8_t *pDat, uint16_t num) { HAL_StatusTypeDef status; while (HAL_I2C_GetState(I2cHandle) != HAL_I2C_STATE_READY) ; status = HAL_I2C_Master_Transmit_IT(I2cHandle, 0xa6, pDat, num); while (HAL_I2C_GetState(I2cHandle) != HAL_I2C_STATE_READY) ; return status; } HAL_StatusTypeDef BL_Receive(uint8_t *pDat, uint16_t num) { HAL_StatusTypeDef status; while (HAL_I2C_GetState(I2cHandle) != HAL_I2C_STATE_READY) ; status = HAL_I2C_Master_Receive_IT(I2cHandle, 0xa6, pDat, num); while (HAL_I2C_GetState(I2cHandle) != HAL_I2C_STATE_READY) ; return status; } uint8_t BL_GetVersion(void) { HAL_StatusTypeDef status; uint8_t ACK; uint8_t cmd_frame[2]; uint8_t version = 0x00U; cmd_frame[0] = GET_VER_COMMAND; cmd_frame[1] = GET_VER_COMMAND ^ 0xFFU; status = BL_Transmit(cmd_frame, 2); status = BL_Receive(&ACK, 1); if (ACK == 0x79) { status = BL_Receive(&version, 1); status = BL_Receive(&ACK, 1); if (ACK == 0x79) return version; } return 0xff; } HAL_StatusTypeDef BL_ReadMemory(uint32_t address, uint16_t nob, uint8_t *pData) { HAL_StatusTypeDef status; uint8_t ACK; uint8_t frame[5]; frame[0] = RMEM_COMMAND; frame[1] = RMEM_COMMAND ^ 0xFFU; status = BL_Transmit(frame, 2); status = BL_Receive(&ACK, 1); if (ACK == 0x79) { frame[0] = (uint8_t)((address >> 24) & 0xFFU); frame[1] = (uint8_t)((address >> 16) & 0xFFU); frame[2] = (uint8_t)((address >> 8) & 0xFFU); frame[3] = (uint8_t)(address & 0xFFU); frame[4] = xor_checksum(frame, 4U); status = BL_Transmit(frame, 5); ACK = 0; status = BL_Receive(&ACK, 1); if (ACK == 0x79) { frame[0] = (nob - 1U); frame[1] = (nob - 1U) ^ 0xFFU; status = BL_Transmit(frame, 2); ACK = 0; status = BL_Receive(&ACK, 1); if (ACK == 0x79) { status = BL_Receive(pData, nob);//data+ack ACK = 0; } else return HAL_ERROR; } else return HAL_ERROR; } else return HAL_ERROR; return HAL_OK; } HAL_StatusTypeDef BL_WriteMemory(uint32_t address, uint16_t nob, uint8_t *pData) { HAL_StatusTypeDef status; uint8_t ACK=0; uint8_t frame[258]; uint8_t checksum = xor_checksum(pData, nob) ^ (nob - 1U ); frame[0] = WMEM_COMMAND; frame[1] = WMEM_COMMAND ^ 0xFFU; status = BL_Transmit(frame, 2); ACK = 0; status = BL_Receive(&ACK, 1); if (ACK == 0x79) { frame[0] = ((uint8_t)(address >> 24) & 0xFFU); frame[1] = ((uint8_t)(address >> 16) & 0xFFU); frame[2] = ((uint8_t)(address >> 8) & 0xFFU); frame[3] = ((uint8_t) address & 0xFFU); frame[4] = xor_checksum(frame, 4U); status = BL_Transmit(frame, 5); ACK = 0; status = BL_Receive(&ACK, 1); if (ACK == 0x79) { frame[0] = nob - 1U; memcpy(&frame[1], pData, nob); frame[nob + 1] = checksum; status = BL_Transmit(frame, (uint16_t) nob + 2); status = BL_Receive(&ACK, 1); } else return HAL_ERROR; } else return HAL_ERROR; return HAL_OK; } HAL_StatusTypeDef BL_EraseMemory(uint16_t nb, uint8_t code) { HAL_StatusTypeDef status; uint8_t ACK; uint8_t frame[3]; frame[0] = EMEM_COMMAND; frame[1] = EMEM_COMMAND ^ 0xFFU; status = BL_Transmit(frame, 2); status = BL_Receive(&ACK, 1); if (ACK == 0x79) { frame[0] = (uint8_t)(nb >> 8) & 0xFFU; frame[1] = (uint8_t) nb & 0xFFU; frame[2] = frame[0] ^ frame[1]; status = BL_Transmit(frame, 3); status = BL_Receive(&ACK, 1); if (ACK == 0x79) { if ((nb >> 4) != 0xFFF) { frame[0] = (uint8_t)(code >> 8) & 0xFFU; frame[1] = code & 0xFFU; frame[2] = frame[0] ^ frame[1]; status = BL_Transmit(frame, 3); status = BL_Receive(&ACK, 1); } } else return HAL_ERROR; } else return HAL_ERROR; return HAL_OK; } static uint8_t xor_checksum(const uint8_t pData[], uint16_t len) { uint8_t sum = *pData; for (uint16_t i = 1U; i < len; i++) sum ^= pData[i]; return sum; } В кубе в i2c не забыть поставить галочки на прерываниях. Код для тестирования uint8_t trsmt[256]; uint8_t recv[257];//add ack HAL_StatusTypeDef status; uint8_t tmp; for (uint16_t i = 0; i < 256; i++) trsmt[i] = i; BL_Init(&hi2c2); while (1) { tmp = BL_GetVersion(); status = BL_EraseMemory(0xffff, 1); tmp = 0; tmp = BL_GetVersion(); status = BL_ReadMemory(0x08000000, 256, recv); tmp = 0; tmp = BL_GetVersion(); status = BL_WriteMemory(0x08000000, 256, trsmt); tmp = 0; tmp = BL_GetVersion(); status = BL_ReadMemory(0x08000000, 256, recv); } ps. Допилил http server на основном контроллере, теперь 4 слэйва обновляю через вебморду. Мастер обновляю через http IAP Bootloader ))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться