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)
|
find_program(OPENOCD openocd)
|
||||||
|
|
||||||
add_custom_target(flash
|
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
|
main.c
|
||||||
incp_handler.c
|
incp_handler.c
|
||||||
msg_buf.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
|
#define INCP_IMPL_CALC
|
||||||
#include "gen_wrapper.h"
|
#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)
|
void handle_incp(msg_buf_t *msgs)
|
||||||
{
|
{
|
||||||
uint8_t *bytes;
|
uint8_t *msg;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
err_t err;
|
err_t err;
|
||||||
|
|
||||||
err = msg_buf_peek(msgs, (void**)&bytes, &len);
|
err = msg_buf_peek(msgs, (void**)&msg, &len);
|
||||||
if (err == ERR_EMPTY)
|
if (err == ERR_EMPTY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (err != ERR_OK)
|
if (err != ERR_OK)
|
||||||
Error_Handler();
|
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 "stm32f4xx_ll_i2c.h"
|
||||||
|
|
||||||
#include "incp_handler.h"
|
#include "incp_handler.h"
|
||||||
#include "msg_buf.h"
|
#include "my_i2c.h"
|
||||||
|
|
||||||
#define I2C_BUF_SIZE 512
|
|
||||||
uint8_t i2c_buf[I2C_BUF_SIZE];
|
|
||||||
|
|
||||||
#define MSG_BUF_CAPACITY (2*1024)
|
#define MSG_BUF_CAPACITY (2*1024)
|
||||||
uint8_t i2c_msg_store[MSG_BUF_CAPACITY];
|
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()
|
int my_main()
|
||||||
{
|
{
|
||||||
|
LL_I2C_EnableIT_EVT(I2C1);
|
||||||
|
|
||||||
msg_buf_init(&i2c_msgs, i2c_msg_store, sizeof(i2c_msg_store));
|
msg_buf_init(&i2c_msgs, i2c_msg_store, sizeof(i2c_msg_store));
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
|
|
||||||
for (int i = 0; i < 500; ++i)
|
for (int i = 0; i < 500; ++i)
|
||||||
{
|
{
|
||||||
HAL_Delay(1);
|
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
|
//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;
|
*(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->head += len_f;
|
||||||
buf->count += 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
|
||||||
@@ -56,6 +56,7 @@ void DebugMon_Handler(void);
|
|||||||
void PendSV_Handler(void);
|
void PendSV_Handler(void);
|
||||||
void SysTick_Handler(void);
|
void SysTick_Handler(void);
|
||||||
void TIM1_UP_TIM10_IRQHandler(void);
|
void TIM1_UP_TIM10_IRQHandler(void);
|
||||||
|
void I2C1_EV_IRQHandler(void);
|
||||||
/* USER CODE BEGIN EFP */
|
/* USER CODE BEGIN EFP */
|
||||||
|
|
||||||
/* USER CODE END EFP */
|
/* USER CODE END EFP */
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ void MX_I2C1_Init(void)
|
|||||||
/* Peripheral clock enable */
|
/* Peripheral clock enable */
|
||||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
|
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 BEGIN I2C1_Init 1 */
|
||||||
|
|
||||||
/* USER CODE END 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.PeripheralMode = LL_I2C_MODE_I2C;
|
||||||
I2C_InitStruct.ClockSpeed = 100000;
|
I2C_InitStruct.ClockSpeed = 100000;
|
||||||
I2C_InitStruct.DutyCycle = LL_I2C_DUTYCYCLE_2;
|
I2C_InitStruct.DutyCycle = LL_I2C_DUTYCYCLE_2;
|
||||||
I2C_InitStruct.OwnAddress1 = 0;
|
I2C_InitStruct.OwnAddress1 = 2;
|
||||||
I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
|
I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
|
||||||
I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
|
I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
|
||||||
LL_I2C_Init(I2C1, &I2C_InitStruct);
|
LL_I2C_Init(I2C1, &I2C_InitStruct);
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ CAD.formats=
|
|||||||
CAD.pinconfig=
|
CAD.pinconfig=
|
||||||
CAD.provider=
|
CAD.provider=
|
||||||
File.Version=6
|
File.Version=6
|
||||||
|
I2C1.IPParameters=OwnAddress,NoStretchMode
|
||||||
|
I2C1.NoStretchMode=I2C_NOSTRETCH_DISABLE
|
||||||
|
I2C1.OwnAddress=1
|
||||||
KeepUserPlacement=false
|
KeepUserPlacement=false
|
||||||
Mcu.CPN=STM32F411RET6
|
Mcu.CPN=STM32F411RET6
|
||||||
Mcu.Family=STM32F4
|
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.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false
|
||||||
NVIC.ForceEnableDMAVector=true
|
NVIC.ForceEnableDMAVector=true
|
||||||
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false
|
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.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:true\:false\:false
|
||||||
NVIC.NonMaskableInt_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
|
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ set -e
|
|||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
server)
|
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)
|
gdb)
|
||||||
arm-none-eabi-gdb build/app/incp-tester-app \
|
arm-none-eabi-gdb build/app/incp-tester-app \
|
||||||
|
|||||||
Reference in New Issue
Block a user