feat: I2C drivers
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
FetchContent_Declare(
|
||||
pyincp
|
||||
GIT_REPOSITORY git@repo.dsi.tecnico.ulisboa.pt:nanosatlab/istsat-2/incp.git
|
||||
GIT_TAG temp/CMake-integration
|
||||
GIT_TAG feat/cli-rework
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(pyincp)
|
||||
|
||||
31
app/src/circular_buffer.h
Normal file
31
app/src/circular_buffer.h
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
#ifndef _CIRCULAR_BUFF_H_
|
||||
#define _CIRCULAR_BUFF_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define _CB_COUNT(buffer) (sizeof((buffer)->buf) / sizeof((buffer)->buf[0]))
|
||||
#define _CB_WRAP(buffer, idx) ((idx) % (_CB_COUNT(buffer)))
|
||||
|
||||
#define CIRCULAR_BUFFER_ALL(name, type, capacity) \
|
||||
typedef struct { \
|
||||
volatile uint32_t tail, count; \
|
||||
volatile type buf[capacity]; \
|
||||
} name##_t; \
|
||||
void name##_init(volatile name##_t *buffer) { buffer->tail = buffer->count = 0; } \
|
||||
bool name##_append(volatile name##_t *buffer, type element) { if (buffer->count == _CB_COUNT(buffer)) return false; buffer->buf[_CB_WRAP(buffer, buffer->tail + buffer->count)] = element; ++buffer->count; return true; } \
|
||||
bool name##_append_range(volatile name##_t *buffer, type *elements, int count) { \
|
||||
for (int i = 0; i < count; ++i) \
|
||||
if (!name##_append(buffer, elements[i])) return false; \
|
||||
return true; \
|
||||
} \
|
||||
int name##_take(volatile name##_t *buffer, type *dest, uint32_t count) { \
|
||||
count = count > buffer->count ? buffer->count : count; \
|
||||
for (uint32_t i = 0; i < count; ++i) { \
|
||||
dest[i] = buffer->buf[_CB_WRAP(buffer, buffer->tail)]; \
|
||||
++buffer->tail; --buffer->count; \
|
||||
} \
|
||||
return count; \
|
||||
} \
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,87 @@
|
||||
#include "main.h"
|
||||
#include "i2c.h"
|
||||
|
||||
#include "stm32f411xe.h"
|
||||
#include "stm32f4xx_hal.h"
|
||||
#include "stm32f4xx_hal_gpio.h"
|
||||
#include "stm32f4xx_ll_i2c.h"
|
||||
|
||||
#include "gen_wrapper.h"
|
||||
|
||||
#include "circular_buffer.h"
|
||||
|
||||
#define CIRC_BUF_SIZE (2*1024)
|
||||
CIRCULAR_BUFFER_ALL(circ_buff, uint8_t, CIRC_BUF_SIZE)
|
||||
|
||||
static volatile circ_buff_t i2c_buf;
|
||||
|
||||
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);
|
||||
|
||||
//Allow buffer to grow until full
|
||||
while (i2c_buf.count < _CB_COUNT(&i2c_buf))
|
||||
{
|
||||
//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
|
||||
{
|
||||
uint8_t data = LL_I2C_ReceiveData8(I2C1);
|
||||
circ_buff_append_range(&i2c_buf, &data, 1);
|
||||
}
|
||||
}
|
||||
|
||||
//Overflow or stop condition reached
|
||||
if (i2c_buf.count >= _CB_COUNT(&i2c_buf))
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user