feat: Replies to pings (ignoring crc)
This commit is contained in:
@@ -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"
|
||||
)
|
||||
|
||||
@@ -2,4 +2,7 @@ target_sources(${EXECUTABLE} PRIVATE
|
||||
main.c
|
||||
incp_handler.c
|
||||
msg_buf.c
|
||||
my_i2c.c
|
||||
)
|
||||
|
||||
add_subdirectory(i3c)
|
||||
|
||||
6
app/src/i3c/CMakeLists.txt
Normal file
6
app/src/i3c/CMakeLists.txt
Normal 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
69
app/src/i3c/checksum.c
Normal 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
18
app/src/i3c/checksum.h
Normal 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
33
app/src/i3c/i3c.c
Normal 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
17
app/src/i3c/i3c.h
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
98
app/src/my_i2c.c
Normal 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
15
app/src/my_i2c.h
Normal 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
1
app/stlink_serial.cfg
Normal file
@@ -0,0 +1 @@
|
||||
adapter serial 066DFF495051727187065818
|
||||
Reference in New Issue
Block a user