feat: Replies to pings (ignoring crc)

This commit is contained in:
2026-04-07 16:44:45 +01:00
parent e32700cc98
commit 3de4ab3af1
17 changed files with 338 additions and 85 deletions

View File

@@ -94,5 +94,5 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/incp.cmake)
find_program(OPENOCD openocd)
add_custom_target(flash
COMMAND ${OPENOCD} -f interface/stlink.cfg -f target/${FW_OPENOCD_TARGET} -c "program $<TARGET_FILE:${EXECUTABLE}> verify reset exit"
COMMAND ${OPENOCD} -f interface/stlink.cfg -f target/${FW_OPENOCD_TARGET} -s ${CMAKE_CURRENT_SOURCE_DIR} -f stlink_serial.cfg -c "program $<TARGET_FILE:${EXECUTABLE}> verify reset exit"
)

View File

@@ -2,4 +2,7 @@ target_sources(${EXECUTABLE} PRIVATE
main.c
incp_handler.c
msg_buf.c
my_i2c.c
)
add_subdirectory(i3c)

View File

@@ -0,0 +1,6 @@
target_sources(${EXECUTABLE} PRIVATE
i3c.c
checksum.c
)
target_include_directories(${EXECUTABLE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})

69
app/src/i3c/checksum.c Normal file
View File

@@ -0,0 +1,69 @@
#include "checksum.h"
// CRC8 with reflected result (0xFF)
// Ref: http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
const uint8_t _table[256] = {
// clang-format off
0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15,
0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5,
0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85,
0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2,
0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32,
0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c,
0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec,
0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c,
0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b,
0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb,
0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb,
0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3
// clang-format on
};
void crc8_init(crc8_t *crc) { *crc = 0; }
void crc8_add(crc8_t *crc, uint8_t value) { *crc = _table[*crc ^ value]; }
void crc8_addSlice(crc8_t *crc, const void *data, size_t size) {
const uint8_t *data8 = (const uint8_t *)data;
size_t i;
for (i = 0; i < size; i += 1)
crc8_add(crc, data8[i]);
}
void crc8_finish(crc8_t *crc) { *crc = (crc8_t)(0xFF ^ *crc); }
crc8_t crc8_calc(const void *data, size_t size) {
crc8_t crc;
crc8_init(&crc);
crc8_addSlice(&crc, data, size);
crc8_finish(&crc);
return crc;
}
bool crc8_eq(const crc8_t *a, const crc8_t *b) { return *a == *b; }
bool crc8_valid(const crc8_t *crc, const void *data, size_t size) {
return *crc == crc8_calc(data, size);
}

18
app/src/i3c/checksum.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef __UTIL_CHECKSUM_H_
#define __UTIL_CHECKSUM_H_
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
typedef uint8_t crc8_t;
void crc8_init(crc8_t *crc);
void crc8_add(crc8_t *crc, uint8_t value);
void crc8_addSlice(crc8_t *crc, const void *data, size_t size);
void crc8_finish(crc8_t *crc);
crc8_t crc8_calc(const void *data, size_t size);
bool crc8_eq(const crc8_t *a, const crc8_t *b);
bool crc8_valid(const crc8_t *crc, const void *data, size_t size);
#endif

33
app/src/i3c/i3c.c Normal file
View File

@@ -0,0 +1,33 @@
#include "i3c.h"
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "checksum.h"
uint8_t i3c_crc(uint8_t dst, uint8_t *msg, size_t len) {
uint8_t crc;
crc8_init(&crc);
crc8_add(&crc, dst);
crc8_add(&crc, msg[0]); // src
crc8_add(&crc, msg[1]); // size
crc8_add(&crc, 0); // crc
crc8_addSlice(&crc, &msg[I3C_HEADER_SIZE], len - I3C_HEADER_SIZE);
crc8_finish(&crc);
return crc;
}
bool i3c_validate(uint8_t *msg, size_t len)
{
uint8_t computed_crc8;
uint8_t rcvd_crc8 = msg[2];
msg[2] = 0;
crc8_init(&computed_crc8);
crc8_addSlice(&computed_crc8, msg, len);
crc8_finish(&computed_crc8);
msg[2] = rcvd_crc8;
return computed_crc8 == rcvd_crc8;
}

17
app/src/i3c/i3c.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef I3C_H
#define I3C_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#define I3C_ADDR_SIZE 1
#define I3C_PL_LEN_SIZE 1
#define I3C_CRC_SIZE 1
#define I3C_HEADER_SIZE (I3C_ADDR_SIZE + I3C_PL_LEN_SIZE + I3C_CRC_SIZE)
uint8_t i3c_crc(uint8_t dst, uint8_t *msg, size_t len);
bool i3c_validate(uint8_t *msg, size_t len);
#endif

View File

@@ -4,19 +4,78 @@
#define INCP_IMPL_CALC
#include "gen_wrapper.h"
#include "i3c.h"
#include "my_i2c.h"
static void handle_msg(uint8_t sender, uint8_t *msg, uint32_t len);
#define I2C_OWN_ADDR 0x01
void handle_incp(msg_buf_t *msgs)
{
uint8_t *bytes;
uint8_t *msg;
uint32_t len;
err_t err;
err = msg_buf_peek(msgs, (void**)&bytes, &len);
err = msg_buf_peek(msgs, (void**)&msg, &len);
if (err == ERR_EMPTY)
return;
if (err != ERR_OK)
Error_Handler();
//TODO: React to INCP
//FIXME: Fails everytime
// Check I3C
if (!i3c_validate(msg, len))
{
//return; // Ignore failed messages
}
uint8_t sender = msg[0];
handle_msg(sender, msg + I3C_HEADER_SIZE, len - I3C_HEADER_SIZE);
msg_buf_pop(msgs);
}
static void handle_msg(uint8_t sender, uint8_t *bytes, uint32_t len)
{
incp_msg_t msg = { 0 };
uint8_t *content;
size_t content_len;
if (incp_deserialize_base(&msg, (void**)&content, &content_len, bytes, len) != INCP_OK)
{
return; // Ignore failed messages
}
switch (msg.kind)
{
case Incp_header_t_kind_ping:
if (incp_convert_ping_inplace(bytes, len) != INCP_OK)
return; //Ignore (unlikely to happen)
bytes[-3] = I2C_OWN_ADDR;
bytes[-2] = len;
bytes[-1] = i3c_crc(I2C_OWN_ADDR, bytes, len);
I2C1_transmit_master(sender, bytes-I3C_HEADER_SIZE, len+I3C_HEADER_SIZE);
break;
case Incp_header_t_kind_manifest_req:
case Incp_header_t_kind_data_req:
case Incp_header_t_kind_data_set:
case Incp_header_t_kind_cmd_req:
//TODO:
return;
case Incp_header_t_kind_pong:
case Incp_header_t_kind_manifest_ret:
case Incp_header_t_kind_log_entry:
case Incp_header_t_kind_bulk_xfer:
case Incp_header_t_kind_event:
case Incp_header_t_kind_data_ret:
case Incp_header_t_kind_cmd_ret:
default:
// Ignore
return;
}
}

View File

@@ -7,94 +7,19 @@
#include "stm32f4xx_ll_i2c.h"
#include "incp_handler.h"
#include "msg_buf.h"
#define I2C_BUF_SIZE 512
uint8_t i2c_buf[I2C_BUF_SIZE];
#include "my_i2c.h"
#define MSG_BUF_CAPACITY (2*1024)
uint8_t i2c_msg_store[MSG_BUF_CAPACITY];
msg_buf_t i2c_msgs;
void I2C1_EV_IRQHandler()
{
if (!LL_I2C_IsActiveFlag_ADDR(I2C1))
Error_Handler();
//Skip checking matched addr (should only be one)
//Skip checking if receiving or transmitting (should always be false)
LL_I2C_ClearFlag_ADDR(I2C1);
int head = 0;
//Allow buffer to grow until full (and inclusive)
while (head <= I2C_BUF_SIZE)
{
//Wait for data or stop flag
while (!LL_I2C_IsActiveFlag_STOP(I2C1) && !LL_I2C_IsActiveFlag_RXNE(I2C1));
if (LL_I2C_IsActiveFlag_STOP(I2C1))
{
LL_I2C_ClearFlag_STOP(I2C1);
break;
}
else //Data received
{
if (head >= I2C_BUF_SIZE) //Overflow for sure
Error_Handler();
uint8_t data = LL_I2C_ReceiveData8(I2C1);
i2c_buf[head++] = data;
}
}
//Stop condition reached, save msg
msg_buf_push(&i2c_msgs, i2c_buf, head);
}
bool I2C1_transmit_master(uint8_t addr, uint8_t *buf, uint8_t count)
{
while (LL_I2C_IsActiveFlag_BUSY(I2C1));
//Transmit start
LL_I2C_GenerateStartCondition(I2C1);
while (!LL_I2C_IsActiveFlag_SB(I2C1));
//Transmit address + write
LL_I2C_TransmitData8(I2C1, addr << 1);
while (!LL_I2C_IsActiveFlag_ADDR(I2C1));
LL_I2C_ClearFlag_ADDR(I2C1);
for (int i = 0; i < count; ++i)
{
while (!LL_I2C_IsActiveFlag_TXE(I2C1));
if (LL_I2C_IsActiveFlag_AF(I2C1))
{
//REVIEW: Anything else neeeded?
LL_I2C_Disable(I2C1);
LL_I2C_Enable(I2C1);
return false;
}
LL_I2C_TransmitData8(I2C1, buf[i]);
}
LL_I2C_GenerateStopCondition(I2C1);
while (LL_I2C_IsActiveFlag_STOP(I2C1));
LL_I2C_Disable(I2C1);
LL_I2C_Enable(I2C1);
return true;
}
int my_main()
{
LL_I2C_EnableIT_EVT(I2C1);
msg_buf_init(&i2c_msgs, i2c_msg_store, sizeof(i2c_msg_store));
while (1)
{
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
for (int i = 0; i < 500; ++i)
{
HAL_Delay(1);

View File

@@ -49,7 +49,7 @@ int msg_buf_push(msg_buf_t *buf, void *data, uint32_t len)
//At this point head is at the first free location and there is enough space after it
*(len_prefix_t*)(buf->storage + buf->head) = len;
memcpy(buf->storage + buf->head + _LENGTH_SIZE, buf, len);
memcpy(buf->storage + buf->head + _LENGTH_SIZE, data, len);
buf->head += len_f;
buf->count += len_f;

98
app/src/my_i2c.c Normal file
View File

@@ -0,0 +1,98 @@
#include "my_i2c.h"
#include "main.h"
#include "stm32f4xx_ll_i2c.h"
uint8_t i2c_buf[I2C_BUF_SIZE];
msg_buf_t i2c_msgs;
static int enter_count = 0;
static int exit_count = 0;
void I2C1_EV_IRQHandler()
{
if (!LL_I2C_IsActiveFlag_ADDR(I2C1))
return;
//Skip checking matched addr (should only be one)
//Skip checking if receiving or transmitting (should always be false)
LL_I2C_ClearFlag_ADDR(I2C1);
++enter_count;
int head = 0;
//Allow buffer to grow until full (and inclusive)
while (head <= I2C_BUF_SIZE)
{
//Wait for data or stop flag
while (!LL_I2C_IsActiveFlag_STOP(I2C1) && !LL_I2C_IsActiveFlag_RXNE(I2C1));
if (LL_I2C_IsActiveFlag_STOP(I2C1))
{
LL_I2C_ClearFlag_STOP(I2C1);
break;
}
else //Data received
{
if (head >= I2C_BUF_SIZE) //Overflow for sure
Error_Handler();
uint8_t data = LL_I2C_ReceiveData8(I2C1);
i2c_buf[head++] = data;
}
}
//Stop condition reached, save msg
msg_buf_push(&i2c_msgs, i2c_buf, head);
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
++exit_count;
}
bool I2C1_transmit_master(uint8_t addr, uint8_t *buf, uint8_t count)
{
while (LL_I2C_IsActiveFlag_BUSY(I2C1));
LL_I2C_DisableIT_EVT(I2C1);
//Transmit start
LL_I2C_GenerateStartCondition(I2C1);
while (!LL_I2C_IsActiveFlag_SB(I2C1));
//Transmit address + write
LL_I2C_TransmitData8(I2C1, addr << 1);
while (!LL_I2C_IsActiveFlag_ADDR(I2C1));
LL_I2C_ClearFlag_ADDR(I2C1);
for (int i = 0; i < count; ++i)
{
while (!LL_I2C_IsActiveFlag_TXE(I2C1));
if (LL_I2C_IsActiveFlag_AF(I2C1))
{
//REVIEW: Anything else neeeded?
LL_I2C_Disable(I2C1);
LL_I2C_Enable(I2C1);
LL_I2C_EnableIT_EVT(I2C1);
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
return false;
}
LL_I2C_TransmitData8(I2C1, buf[i]);
}
while (!LL_I2C_IsActiveFlag_TXE(I2C1));
LL_I2C_GenerateStopCondition(I2C1);
while (LL_I2C_IsActiveFlag_STOP(I2C1));
LL_I2C_Disable(I2C1);
LL_I2C_Enable(I2C1);
LL_I2C_EnableIT_EVT(I2C1);
return true;
}

15
app/src/my_i2c.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef _MYI2C_H_
#define _MYI2C_H_
#include <stdint.h>
#include "msg_buf.h"
#define I2C_BUF_SIZE 512
extern uint8_t i2c_buf[I2C_BUF_SIZE];
extern msg_buf_t i2c_msgs;
bool I2C1_transmit_master(uint8_t addr, uint8_t *buf, uint8_t count);
#endif

1
app/stlink_serial.cfg Normal file
View File

@@ -0,0 +1 @@
adapter serial 066DFF495051727187065818

View File

@@ -56,6 +56,7 @@ void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
void TIM1_UP_TIM10_IRQHandler(void);
void I2C1_EV_IRQHandler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */

View File

@@ -52,6 +52,10 @@ void MX_I2C1_Init(void)
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
/* I2C1 interrupt Init */
NVIC_SetPriority(I2C1_EV_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(I2C1_EV_IRQn);
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
@@ -64,7 +68,7 @@ void MX_I2C1_Init(void)
I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
I2C_InitStruct.ClockSpeed = 100000;
I2C_InitStruct.DutyCycle = LL_I2C_DUTYCYCLE_2;
I2C_InitStruct.OwnAddress1 = 0;
I2C_InitStruct.OwnAddress1 = 2;
I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
LL_I2C_Init(I2C1, &I2C_InitStruct);

View File

@@ -3,6 +3,9 @@ CAD.formats=
CAD.pinconfig=
CAD.provider=
File.Version=6
I2C1.IPParameters=OwnAddress,NoStretchMode
I2C1.NoStretchMode=I2C_NOSTRETCH_DISABLE
I2C1.OwnAddress=1
KeepUserPlacement=false
Mcu.CPN=STM32F411RET6
Mcu.Family=STM32F4
@@ -37,6 +40,7 @@ NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false
NVIC.ForceEnableDMAVector=true
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false
NVIC.I2C1_EV_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false

View File

@@ -3,7 +3,7 @@ set -e
case "$1" in
server)
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg -f app/stlink_serial.cfg
;;
gdb)
arm-none-eabi-gdb build/app/incp-tester-app \