parent
b6f7060516
commit
4bd8dc6cb0
@ -0,0 +1,130 @@ |
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2018/02/03.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "platform.h" |
||||||
|
#include "unit_1wire.h" |
||||||
|
|
||||||
|
// 1WIRE master
|
||||||
|
#define OW_INTERNAL |
||||||
|
#include "_ow_internal.h" |
||||||
|
#include "_ow_commands.h" |
||||||
|
#include "_ow_checksum.h" |
||||||
|
#include "_ow_low_level.h" |
||||||
|
|
||||||
|
/* Check presence of any devices on the bus */ |
||||||
|
error_t UU_1WIRE_CheckPresence(Unit *unit, bool *presence) |
||||||
|
{ |
||||||
|
CHECK_TYPE(unit, &UNIT_1WIRE); |
||||||
|
// reset
|
||||||
|
*presence = ow_reset(unit); |
||||||
|
return E_SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
/* Read address of a lone device on the bus */ |
||||||
|
error_t UU_1WIRE_ReadAddress(Unit *unit, uint64_t *address) |
||||||
|
{ |
||||||
|
CHECK_TYPE(unit, &UNIT_1WIRE); |
||||||
|
*address = 0; |
||||||
|
if (!ow_reset(unit)) return E_HW_TIMEOUT; |
||||||
|
|
||||||
|
// command
|
||||||
|
ow_write_u8(unit, OW_ROM_READ); |
||||||
|
|
||||||
|
// read the ROM code
|
||||||
|
*address = ow_read_u64(unit); |
||||||
|
|
||||||
|
const uint8_t *addr_as_bytes = (void*)address; |
||||||
|
if (0 != ow_checksum(addr_as_bytes, 8)) { |
||||||
|
*address = 0; |
||||||
|
return E_CHECKSUM_MISMATCH; // checksum mismatch
|
||||||
|
} |
||||||
|
return E_SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
/* Write bytes to a device */ |
||||||
|
error_t UU_1WIRE_Write(Unit *unit, uint64_t address, const uint8_t *buff, uint32_t len) |
||||||
|
{ |
||||||
|
CHECK_TYPE(unit, &UNIT_1WIRE); |
||||||
|
if (!ow_reset(unit)) return E_HW_TIMEOUT; |
||||||
|
|
||||||
|
// MATCH_ROM+addr, or SKIP_ROM
|
||||||
|
if (address != 0) { |
||||||
|
ow_write_u8(unit, OW_ROM_MATCH); |
||||||
|
ow_write_u64(unit, address); |
||||||
|
} else { |
||||||
|
ow_write_u8(unit, OW_ROM_SKIP); |
||||||
|
} |
||||||
|
|
||||||
|
// write the payload;
|
||||||
|
for (uint32_t i = 0; i < len; i++) { |
||||||
|
ow_write_u8(unit, *buff++); |
||||||
|
} |
||||||
|
return E_SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
/* Write a request to a device and read a response */ |
||||||
|
error_t UU_1WIRE_Read(Unit *unit, uint64_t address, |
||||||
|
const uint8_t *request_buff, uint32_t request_len, |
||||||
|
uint8_t *response_buff, uint32_t response_len, bool check_crc) |
||||||
|
{ |
||||||
|
CHECK_TYPE(unit, &UNIT_1WIRE); |
||||||
|
if (!ow_reset(unit)) return E_HW_TIMEOUT; |
||||||
|
|
||||||
|
uint8_t *rb = response_buff; |
||||||
|
|
||||||
|
// MATCH_ROM+addr, or SKIP_ROM
|
||||||
|
if (address != 0) { |
||||||
|
ow_write_u8(unit, OW_ROM_MATCH); |
||||||
|
ow_write_u64(unit, address); |
||||||
|
} else { |
||||||
|
ow_write_u8(unit, OW_ROM_SKIP); |
||||||
|
} |
||||||
|
|
||||||
|
// write the payload;
|
||||||
|
for (uint32_t i = 0; i < request_len; i++) { |
||||||
|
ow_write_u8(unit, *request_buff++); |
||||||
|
} |
||||||
|
|
||||||
|
// read the requested number of bytes
|
||||||
|
for (uint32_t i = 0; i < response_len; i++) { |
||||||
|
*rb++ = ow_read_u8(unit); |
||||||
|
} |
||||||
|
|
||||||
|
if (check_crc) { |
||||||
|
if (0 != ow_checksum(response_buff, response_len)) { |
||||||
|
return E_CHECKSUM_MISMATCH; |
||||||
|
} |
||||||
|
} |
||||||
|
return E_SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
/* Perform the search algorithm (start or continue) */ |
||||||
|
error_t UU_1WIRE_Search(Unit *unit, bool with_alarm, bool restart, |
||||||
|
uint64_t *buffer, uint32_t capacity, uint32_t *real_count, |
||||||
|
bool *have_more) |
||||||
|
{ |
||||||
|
CHECK_TYPE(unit, &UNIT_1WIRE); |
||||||
|
struct priv *priv = unit->data; |
||||||
|
|
||||||
|
if (restart) { |
||||||
|
uint8_t search_cmd = (uint8_t) (with_alarm ? OW_ROM_ALM_SEARCH : OW_ROM_SEARCH); |
||||||
|
ow_search_init(unit, search_cmd, true); |
||||||
|
} |
||||||
|
|
||||||
|
*real_count = ow_search_run(unit, (ow_romcode_t *) buffer, capacity); |
||||||
|
|
||||||
|
// resolve the code
|
||||||
|
switch (priv->searchState.status) { |
||||||
|
case OW_SEARCH_MORE: |
||||||
|
*have_more = priv->searchState.status == OW_SEARCH_MORE; |
||||||
|
|
||||||
|
case OW_SEARCH_DONE: |
||||||
|
return E_SUCCESS; |
||||||
|
|
||||||
|
case OW_SEARCH_FAILED: |
||||||
|
return priv->searchState.error; |
||||||
|
} |
||||||
|
|
||||||
|
return E_FAILURE; |
||||||
|
} |
@ -0,0 +1,124 @@ |
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2018/02/03.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "platform.h" |
||||||
|
#include "unit_base.h" |
||||||
|
#include "unit_i2c.h" |
||||||
|
|
||||||
|
#define I2C_INTERNAL |
||||||
|
#include "_i2c_internal.h" |
||||||
|
|
||||||
|
|
||||||
|
static void i2c_reset(struct priv *priv) |
||||||
|
{ |
||||||
|
LL_I2C_Disable(priv->periph); |
||||||
|
HAL_Delay(1); |
||||||
|
LL_I2C_Enable(priv->periph); |
||||||
|
} |
||||||
|
|
||||||
|
static error_t i2c_wait_until_flag(struct priv *priv, uint32_t flag, bool stop_state) |
||||||
|
{ |
||||||
|
uint32_t t_start = HAL_GetTick(); |
||||||
|
while (((priv->periph->ISR & flag)!=0) != stop_state) { |
||||||
|
if (HAL_GetTick() - t_start > 10) { |
||||||
|
i2c_reset(priv); |
||||||
|
return E_HW_TIMEOUT; |
||||||
|
} |
||||||
|
} |
||||||
|
return E_SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
error_t UU_I2C_Write(Unit *unit, uint16_t addr, const uint8_t *bytes, uint32_t bcount) |
||||||
|
{ |
||||||
|
CHECK_TYPE(unit, &UNIT_I2C); |
||||||
|
|
||||||
|
struct priv *priv = unit->data; |
||||||
|
|
||||||
|
uint8_t addrsize = (uint8_t) (((addr & 0x8000) == 0) ? 7 : 10); |
||||||
|
addr &= 0x3FF; |
||||||
|
uint32_t ll_addrsize = (addrsize == 7) ? LL_I2C_ADDRSLAVE_7BIT : LL_I2C_ADDRSLAVE_10BIT; |
||||||
|
if (addrsize == 7) addr <<= 1; // 7-bit address must be shifted to left for LL to use it correctly
|
||||||
|
|
||||||
|
TRY(i2c_wait_until_flag(priv, I2C_ISR_BUSY, 0)); |
||||||
|
|
||||||
|
bool first = true; |
||||||
|
while (bcount > 0) { |
||||||
|
uint32_t len = bcount; |
||||||
|
uint32_t chunk_remain = (uint8_t) ((len > 255) ? 255 : len); // if more than 255, first chunk is 255
|
||||||
|
LL_I2C_HandleTransfer(priv->periph, addr, ll_addrsize, chunk_remain, |
||||||
|
(len > 255) ? LL_I2C_MODE_RELOAD : LL_I2C_MODE_AUTOEND, // Autoend if this is the last chunk
|
||||||
|
first ? LL_I2C_GENERATE_START_WRITE : LL_I2C_GENERATE_NOSTARTSTOP); // no start/stop condition if we're continuing
|
||||||
|
first = false; |
||||||
|
bcount -= chunk_remain; |
||||||
|
|
||||||
|
for (; chunk_remain > 0; chunk_remain--) { |
||||||
|
TRY(i2c_wait_until_flag(priv, I2C_ISR_TXIS, 1)); |
||||||
|
uint8_t byte = *bytes++; |
||||||
|
LL_I2C_TransmitData8(priv->periph, byte); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
TRY(i2c_wait_until_flag(priv, I2C_ISR_STOPF, 1)); |
||||||
|
LL_I2C_ClearFlag_STOP(priv->periph); |
||||||
|
return E_SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
error_t UU_I2C_Read(Unit *unit, uint16_t addr, uint8_t *dest, uint32_t bcount) |
||||||
|
{ |
||||||
|
CHECK_TYPE(unit, &UNIT_I2C); |
||||||
|
|
||||||
|
struct priv *priv = unit->data; |
||||||
|
|
||||||
|
uint8_t addrsize = (uint8_t) (((addr & 0x8000) == 0) ? 7 : 10); |
||||||
|
addr &= 0x3FF; |
||||||
|
uint32_t ll_addrsize = (addrsize == 7) ? LL_I2C_ADDRSLAVE_7BIT : LL_I2C_ADDRSLAVE_10BIT; |
||||||
|
if (addrsize == 7) addr <<= 1; // 7-bit address must be shifted to left for LL to use it correctly
|
||||||
|
|
||||||
|
TRY(i2c_wait_until_flag(priv, I2C_ISR_BUSY, 0)); |
||||||
|
|
||||||
|
bool first = true; |
||||||
|
while (bcount > 0) { |
||||||
|
if (!first) { |
||||||
|
TRY(i2c_wait_until_flag(priv, I2C_ISR_TCR, 1)); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t chunk_remain = (uint8_t) ((bcount > 255) ? 255 : bcount); // if more than 255, first chunk is 255
|
||||||
|
LL_I2C_HandleTransfer(priv->periph, addr, ll_addrsize, chunk_remain, |
||||||
|
(bcount > 255) ? LL_I2C_MODE_RELOAD : LL_I2C_MODE_AUTOEND, // Autoend if this is the last chunk
|
||||||
|
first ? LL_I2C_GENERATE_START_READ : LL_I2C_GENERATE_NOSTARTSTOP); // no start/stop condition if we're continuing
|
||||||
|
first = false; |
||||||
|
bcount -= chunk_remain; |
||||||
|
|
||||||
|
for (; chunk_remain > 0; chunk_remain--) { |
||||||
|
TRY(i2c_wait_until_flag(priv, I2C_ISR_RXNE, 1)); |
||||||
|
|
||||||
|
uint8_t byte = LL_I2C_ReceiveData8(priv->periph); |
||||||
|
*dest++ = byte; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
TRY(i2c_wait_until_flag(priv, I2C_ISR_STOPF, 1)); |
||||||
|
LL_I2C_ClearFlag_STOP(priv->periph); |
||||||
|
return E_SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
error_t UU_I2C_ReadReg(Unit *unit, uint16_t addr, uint8_t regnum, uint8_t *dest, uint32_t width) |
||||||
|
{ |
||||||
|
TRY(UU_I2C_Write(unit, addr, ®num, 1)); |
||||||
|
TRY(UU_I2C_Read(unit, addr, dest, width)); |
||||||
|
return E_SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
error_t UU_I2C_WriteReg(Unit *unit, uint16_t addr, uint8_t regnum, const uint8_t *bytes, uint32_t width) |
||||||
|
{ |
||||||
|
CHECK_TYPE(unit, &UNIT_I2C); |
||||||
|
|
||||||
|
// we have to insert the address first - needs a buffer (XXX realistically the buffer needs 1-4 bytes + addr)
|
||||||
|
PayloadBuilder pb = pb_start((uint8_t*)unit_tmp512, UNIT_TMP_LEN, NULL); |
||||||
|
pb_u8(&pb, regnum); |
||||||
|
pb_buf(&pb, bytes, width); |
||||||
|
|
||||||
|
TRY(UU_I2C_Write(unit, addr, (uint8_t *) unit_tmp512, pb_length(&pb))); |
||||||
|
return E_SUCCESS; |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2018/02/03.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GEX_F072_I2C_INTERNAL_H |
||||||
|
#define GEX_F072_I2C_INTERNAL_H |
||||||
|
|
||||||
|
#ifndef I2C_INTERNAL |
||||||
|
#error bad include! |
||||||
|
#endif |
||||||
|
|
||||||
|
/** Private data structure */ |
||||||
|
struct priv { |
||||||
|
uint8_t periph_num; //!< 1 or 2
|
||||||
|
uint8_t remap; //!< I2C remap option
|
||||||
|
|
||||||
|
bool anf; //!< Enable analog noise filter
|
||||||
|
uint8_t dnf; //!< Enable digital noise filter (1-15 ... max spike width)
|
||||||
|
uint8_t speed; //!< 0 - Standard, 1 - Fast, 2 - Fast+
|
||||||
|
|
||||||
|
I2C_TypeDef *periph; |
||||||
|
|
||||||
|
// GPIO_TypeDef *port;
|
||||||
|
// uint32_t ll_pin_scl;
|
||||||
|
// uint32_t ll_pin_sda;
|
||||||
|
}; |
||||||
|
|
||||||
|
#endif //GEX_F072_I2C_INTERNAL_H
|
@ -1,74 +0,0 @@ |
|||||||
//
|
|
||||||
// Created by MightyPork on 2018/01/14.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "platform.h" |
|
||||||
#include "unit_base.h" |
|
||||||
|
|
||||||
#define UUSART_INTERNAL |
|
||||||
#include "_internal.h" |
|
||||||
|
|
||||||
/** Load from a binary buffer stored in Flash */ |
|
||||||
void UUSART_loadBinary(Unit *unit, PayloadParser *pp) |
|
||||||
{ |
|
||||||
struct priv *priv = unit->data; |
|
||||||
|
|
||||||
uint8_t version = pp_u8(pp); |
|
||||||
(void)version; |
|
||||||
|
|
||||||
priv->periph_num = pp_u8(pp); |
|
||||||
priv->remap = pp_u8(pp); |
|
||||||
|
|
||||||
priv->baudrate = pp_u32(pp); |
|
||||||
priv->parity = pp_u8(pp); |
|
||||||
priv->stopbits = pp_u8(pp); |
|
||||||
priv->direction = pp_u8(pp); |
|
||||||
|
|
||||||
priv->hw_flow_control = pp_u8(pp); |
|
||||||
priv->clock_output = pp_bool(pp); |
|
||||||
priv->cpol = pp_bool(pp); |
|
||||||
priv->cpha = pp_bool(pp); |
|
||||||
priv->lsb_first = pp_bool(pp); |
|
||||||
priv->width = pp_u8(pp); |
|
||||||
|
|
||||||
priv->data_inv = pp_bool(pp); |
|
||||||
priv->rx_inv = pp_bool(pp); |
|
||||||
priv->tx_inv = pp_bool(pp); |
|
||||||
|
|
||||||
priv->de_output = pp_bool(pp); |
|
||||||
priv->de_polarity = pp_bool(pp); |
|
||||||
priv->de_assert_time = pp_u8(pp); |
|
||||||
priv->de_clear_time = pp_u8(pp); |
|
||||||
} |
|
||||||
|
|
||||||
/** Write to a binary buffer for storing in Flash */ |
|
||||||
void UUSART_writeBinary(Unit *unit, PayloadBuilder *pb) |
|
||||||
{ |
|
||||||
struct priv *priv = unit->data; |
|
||||||
|
|
||||||
pb_u8(pb, 0); // version
|
|
||||||
|
|
||||||
pb_u8(pb, priv->periph_num); |
|
||||||
pb_u8(pb, priv->remap); |
|
||||||
|
|
||||||
pb_u32(pb, priv->baudrate); |
|
||||||
pb_u8(pb, priv->parity); |
|
||||||
pb_u8(pb, priv->stopbits); |
|
||||||
pb_u8(pb, priv->direction); |
|
||||||
|
|
||||||
pb_u8(pb, priv->hw_flow_control); |
|
||||||
pb_bool(pb, priv->clock_output); |
|
||||||
pb_bool(pb, priv->cpol); |
|
||||||
pb_bool(pb, priv->cpha); |
|
||||||
pb_bool(pb, priv->lsb_first); |
|
||||||
pb_u8(pb, priv->width); |
|
||||||
|
|
||||||
pb_bool(pb, priv->data_inv); |
|
||||||
pb_bool(pb, priv->rx_inv); |
|
||||||
pb_bool(pb, priv->tx_inv); |
|
||||||
|
|
||||||
pb_bool(pb, priv->de_output); |
|
||||||
pb_bool(pb, priv->de_polarity); |
|
||||||
pb_u8(pb, priv->de_assert_time); |
|
||||||
pb_u8(pb, priv->de_clear_time); |
|
||||||
} |
|
@ -0,0 +1,56 @@ |
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2018/02/03.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "platform.h" |
||||||
|
#include "unit_base.h" |
||||||
|
#include "unit_usart.h" |
||||||
|
|
||||||
|
#define UUSART_INTERNAL |
||||||
|
#include "_usart_internal.h" |
||||||
|
|
||||||
|
|
||||||
|
error_t UU_USART_Write(Unit *unit, const uint8_t *buffer, uint32_t len) |
||||||
|
{ |
||||||
|
CHECK_TYPE(unit, &UNIT_USART); |
||||||
|
struct priv *priv = unit->data; |
||||||
|
|
||||||
|
uint32_t t_start = HAL_GetTick(); |
||||||
|
while (len > 0) { |
||||||
|
// this should be long enough even for the slowest bitrates and 512 bytes
|
||||||
|
if (HAL_GetTick() - t_start > 5000) { |
||||||
|
return E_HW_TIMEOUT; |
||||||
|
} |
||||||
|
|
||||||
|
uint16_t chunk = UUSART_DMA_TxQueue(priv, buffer, (uint16_t) len); |
||||||
|
|
||||||
|
buffer += chunk; |
||||||
|
len -= chunk; |
||||||
|
|
||||||
|
// We give up control if there's another thread waiting and this isn't the last cycle
|
||||||
|
if (len > 0) { |
||||||
|
osThreadYield(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return E_SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
error_t UU_USART_WriteSync(Unit *unit, const uint8_t *buffer, uint32_t len) |
||||||
|
{ |
||||||
|
CHECK_TYPE(unit, &UNIT_USART); |
||||||
|
struct priv *priv = unit->data; |
||||||
|
|
||||||
|
TRY(UU_USART_Write(unit, buffer, len)); |
||||||
|
|
||||||
|
// Now wait for the last DMA to complete
|
||||||
|
uint32_t t_start = HAL_GetTick(); |
||||||
|
while (priv->tx_dma_busy) { |
||||||
|
if (HAL_GetTick() - t_start > 1000) { |
||||||
|
return E_HW_TIMEOUT; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return E_SUCCESS; |
||||||
|
} |
Loading…
Reference in new issue