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