Skip to content

Commit

Permalink
[driver] radio: dw3110 Add STS capabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
Javask committed Aug 28, 2024
1 parent 303cfc7 commit dbda6d2
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 3 deletions.
8 changes: 8 additions & 0 deletions src/modm/driver/radio/dw3110/dw3110_definitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ struct Dw3110
Code_64Mhz_12 = 12,
};

enum class STSMode : uint8_t
{
SP0 = 0b00, // No STS
SP1 = 0b01, // STS between SDF and PHR
SP2 = 0b10, // STS at the end (vulnerable to attack!)
SP3 = 0b11 // STS after SDF but no PHR or data
};

enum class StartFrameDelimiter : uint8_t
{
IEEE802_15_4_8 = 0,
Expand Down
53 changes: 52 additions & 1 deletion src/modm/driver/radio/dw3110/dw3110_phy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace modm
* Hardware abstraction layer for DW3110 \n
* Unsupported Features: AES encryption, Double buffering, GPIO, Temperature and
* Voltage, Pulse Generator calibration, RX antenna delay temp compensation,
* Soft reset, Sleep, Sniff mode, Delayed transmission, STS
* Soft reset, Sleep, Sniff mode
* @ingroup modm_driver_dw3110
* @author Elias H.
* @author Raphael Lehmann
Expand Down Expand Up @@ -305,6 +305,57 @@ class Dw3110Phy : public modm::SpiDevice<SpiMaster>, protected modm::NestedResum
modm::ResumableResult<void>
setIRQPolarity(bool high);

/// Set the length of the generated Secure timestamp
///@param len Length in units of 8 chips (~1µs), minimum supported is 32 chips(e.g a value of 3)
modm::ResumableResult<bool>
setSTSLength(uint8_t len);

/// Set the STS mode \n
/// @param mode Defines where to place the STS inside the packet
/// @param sdc If true IV and Key are ignored and a deterministic code is used
modm::ResumableResult<void>
setSTSMode(Dw3110::STSMode mode, bool sdc);

/// Return the 12-bit quality assessment of the last received STS
modm::ResumableResult<uint16_t>
getSTSQuality();

/// Return whether or not the STS quality is in an acceptable range
modm::ResumableResult<bool>
getSTSGood();

/// Set the Key to use for AES generation of the STS \n
/// Ignored if SDC is set in \ref setSTSMode()
modm::ResumableResult<void>
setSTSKey(std::span<const uint8_t, 16> key);

/// Set the IV to use for AES generation of the STS \n
/// Ignored if SDC is set in \ref setSTSMode()
modm::ResumableResult<void>
setSTSIV(std::span<const uint8_t, 16> iv);

/// Get the Key to use for AES generation of the STS
modm::ResumableResult<void>
getSTSKey(std::span<uint8_t, 16> key);

/// Get the IV to use for AES generation of the STS
/// @warning Will only return the programmed IV, to get the incremented value use \ref
/// getCurrentCounter()
modm::ResumableResult<void>
getSTSIV(std::span<uint8_t, 16> iv);

/// Get lower 32 bits of the currently used STS IV
modm::ResumableResult<uint32_t>
getCurrentCounter();

/// Reload the STS IV from the STSIV registers
modm::ResumableResult<void>
reloadSTSIV();

/// Don't increment the STS IV for the next RX/TX
modm::ResumableResult<void>
reuseLastSTSIV();

protected:
/// Transmit a given package using the current configuration and a specific command
/// @param payload Span to the desired payload
Expand Down
105 changes: 103 additions & 2 deletions src/modm/driver/radio/dw3110/dw3110_phy_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ modm::Dw3110Phy<SpiMaster, Cs>::initialize(Dw3110::Channel channel, Dw3110::Prea
RF_CALL(setEnableLongFrames(false));
RF_CALL(setSendHeaderFast(false));
RF_CALL(setCCATimeout(256));
RF_CALL(reloadSTSIV());
RF_END_RETURN(true);
}

Expand Down Expand Up @@ -1044,9 +1045,11 @@ modm::Dw3110Phy<SpiMaster, Cs>::fetchPacket(std::span<uint8_t> payload, size_t &
if (payload.size() < payload_len) { RF_RETURN(false); }
RF_CALL(readRegisterBank<Dw3110::RX_BUFFER_0_BANK>(payload, payload_len));

// Clear RXFR RXPHE RXFCG and RXFCE flag
// Clear most rx flags
RF_CALL(clearStatusBits(Dw3110::SystemStatus::RXFR | Dw3110::SystemStatus::RXPHE |
Dw3110::SystemStatus::RXFCG | Dw3110::SystemStatus::RXFCE));
Dw3110::SystemStatus::RXFCG | Dw3110::SystemStatus::RXFCE |
Dw3110::SystemStatus::RXSFDD | Dw3110::SystemStatus::RXPRD |
Dw3110::SystemStatus::RXPHD | Dw3110::SystemStatus::RXFSL));
RF_END_RETURN(true);
}

Expand Down Expand Up @@ -1312,3 +1315,101 @@ modm::Dw3110Phy<SpiMaster, Cs>::setIRQPolarity(bool high)
}
RF_END();
}

template<typename SpiMaster, typename Cs>
modm::ResumableResult<bool>
modm::Dw3110Phy<SpiMaster, Cs>::setSTSLength(uint8_t len)
{
RF_BEGIN();
if (len < 3) { RF_RETURN(false); }
scratch[0] = len;
RF_CALL(writeRegister<Dw3110::STS_CFG, 1>(std::span<const uint8_t>(scratch).first<1>()));
RF_END_RETURN(true);
}

template<typename SpiMaster, typename Cs>
modm::ResumableResult<void>
modm::Dw3110Phy<SpiMaster, Cs>::setSTSMode(Dw3110::STSMode mode, bool sdc)
{
RF_BEGIN();
scratch[0] = ((uint8_t)mode << 4) | (sdc ? 0x80 : 0x00);
scratch[1] = 0x4F | scratch[0];
RF_CALL(writeRegisterMasked<Dw3110::SYS_CFG, 1, 1>(
std::span<const uint8_t>(scratch).first<1>(),
std::span<const uint8_t>(scratch).subspan<1, 1>()));
RF_END();
}

template<typename SpiMaster, typename Cs>
modm::ResumableResult<uint16_t>
modm::Dw3110Phy<SpiMaster, Cs>::getSTSQuality()
{
RF_BEGIN();
RF_CALL(readRegister<Dw3110::STS_STS, 2>(std::span<uint8_t>(scratch).first<2>()));
RF_END_RETURN((uint16_t)(scratch[0] << 0 | (scratch[1] & 0x0F) << 8));
}

template<typename SpiMaster, typename Cs>
modm::ResumableResult<bool>
modm::Dw3110Phy<SpiMaster, Cs>::getSTSGood()
{
RF_BEGIN();
RF_CALL(readRegister<Dw3110::STS_CFG, 1>(std::span<uint8_t>(scratch).first<1>()));
RF_CALL(readRegister<Dw3110::STS_STS, 2>(std::span<uint8_t>(scratch).subspan<1, 2>()));
RF_END_RETURN((scratch[0] + 1) * 8.0f * 0.6f < (scratch[1] | (scratch[2] << 8)));
}

template<typename SpiMaster, typename Cs>
modm::ResumableResult<void>
modm::Dw3110Phy<SpiMaster, Cs>::setSTSKey(std::span<const uint8_t, 16> key)
{
return writeRegister<Dw3110::STS_KEY, 16, 0>(key);
}

template<typename SpiMaster, typename Cs>
modm::ResumableResult<void>
modm::Dw3110Phy<SpiMaster, Cs>::setSTSIV(std::span<const uint8_t, 16> iv)
{
return writeRegister<Dw3110::STS_IV, 16, 0>(iv);
}

template<typename SpiMaster, typename Cs>
modm::ResumableResult<void>
modm::Dw3110Phy<SpiMaster, Cs>::getSTSKey(std::span<uint8_t, 16> key)
{
return readRegister<Dw3110::STS_KEY, 16, 0>(key);
}

template<typename SpiMaster, typename Cs>
modm::ResumableResult<void>
modm::Dw3110Phy<SpiMaster, Cs>::getSTSIV(std::span<uint8_t, 16> iv)
{
return readRegister<Dw3110::STS_IV, 16, 0>(iv);
}

template<typename SpiMaster, typename Cs>
modm::ResumableResult<uint32_t>
modm::Dw3110Phy<SpiMaster, Cs>::getCurrentCounter()
{
RF_BEGIN();
RF_CALL(readRegister<Dw3110::CTR_DBG, 4, 0>(std::span<uint8_t>(scratch).first<4>()));
RF_END_RETURN((uint32_t)scratch[0] | (uint32_t)scratch[1] << 8 | (uint32_t)scratch[2] << 16 |
(uint32_t)scratch[3] << 24);
}

template<typename SpiMaster, typename Cs>
modm::ResumableResult<void>
modm::Dw3110Phy<SpiMaster, Cs>::reloadSTSIV()
{
constexpr static uint8_t sts_ctrl[] = {0x01};
return writeRegister<Dw3110::STS_CTRL, 1>(sts_ctrl);
}

template<typename SpiMaster, typename Cs>
modm::ResumableResult<void>
modm::Dw3110Phy<SpiMaster, Cs>::reuseLastSTSIV()
{

constexpr static uint8_t sts_ctrl[] = {0x02};
return writeRegister<Dw3110::STS_CTRL, 1>(sts_ctrl);
}

0 comments on commit dbda6d2

Please sign in to comment.