Browse Source

update

master
zhaohe 2 years ago
parent
commit
196ed167d7
  1. 3
      chip/chip.h
  2. 303
      components/tmc/ic/TMC5160/TMC5160.c
  3. 48
      components/tmc/ic/ztmc5130.cpp
  4. 61
      components/tmc/ic/ztmc5130.hpp
  5. 9
      hal/zhal_core.cpp
  6. 7
      hal/zhal_core.hpp

3
chip/chip.h

@ -121,7 +121,8 @@ extern "C" {
#endif #endif
typedef enum { typedef enum {
PA0 = 0x10,
PinNull = 0,
PA0 = 0x10,
PA1, PA1,
PA2, PA2,
PA3, PA3,

303
components/tmc/ic/TMC5160/TMC5160.c

@ -1,303 +0,0 @@
/*
* TMC5160.c
*
* Created on: 03.07.2017
* Author: LK
*/
#if 0
#include "TMC5160.h"
// => SPI wrapper
// Send [length] bytes stored in the [data] array over SPI and overwrite [data]
// with the reply. The first byte sent/received is data[0].
extern void tmc5160_readWriteArray(TMC5160TypeDef *tmc5160, uint8_t *data, size_t length);
// <= SPI wrapper
static void writeConfiguration(TMC5160TypeDef *tmc5160);
// Writes (x1 << 24) | (x2 << 16) | (x3 << 8) | x4 to the given address
void tmc5160_writeDatagram(TMC5160TypeDef *tmc5160, uint8_t address, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4)
{
uint8_t data[5] = { address | TMC5160_WRITE_BIT, x1, x2, x3, x4 };
tmc5160_readWriteArray(tmc5160, &data[0], 5);
int32_t value = ((uint32_t)x1 << 24) | ((uint32_t)x2 << 16) | (x3 << 8) | x4;
// Write to the shadow register and mark the register dirty
address = TMC_ADDRESS(address);
tmc5160->config->shadowRegister[address] = value;
tmc5160->registerAccess[address] |= TMC_ACCESS_DIRTY;
}
// Write an integer to the given address
void tmc5160_writeInt(TMC5160TypeDef *tmc5160, uint8_t address, int32_t value)
{
tmc5160_writeDatagram(tmc5160, address, BYTE(value, 3), BYTE(value, 2), BYTE(value, 1), BYTE(value, 0));
}
// Read an integer from the given address
int32_t tmc5160_readInt(TMC5160TypeDef *tmc5160, uint8_t address)
{
address = TMC_ADDRESS(address);
// register not readable -> shadow register copy
if(!TMC_IS_READABLE(tmc5160->registerAccess[address]))
return tmc5160->config->shadowRegister[address];
uint8_t data[5] = { 0, 0, 0, 0, 0 };
data[0] = address;
tmc5160_readWriteArray(tmc5160, &data[0], 5);
data[0] = address;
tmc5160_readWriteArray(tmc5160, &data[0], 5);
return ((uint32_t)data[1] << 24) | ((uint32_t)data[2] << 16) | (data[3] << 8) | data[4];
}
// Initialize a TMC5160 IC.
// This function requires:
// - tmc5160: The pointer to a TMC5160TypeDef struct, which represents one IC
// - channel: The channel index, which will be sent back in the SPI callback
// - config: A ConfigurationTypeDef struct, which will be used by the IC
// - registerResetState: An int32_t array with 128 elements. This holds the values to be used for a reset.
void tmc5160_init(TMC5160TypeDef *tmc5160, uint8_t channel, ConfigurationTypeDef *config, const int32_t *registerResetState)
{
tmc5160->velocity = 0;
tmc5160->oldTick = 0;
tmc5160->oldX = 0;
tmc5160->config = config;
tmc5160->config->callback = NULL;
tmc5160->config->channel = channel;
tmc5160->config->configIndex = 0;
tmc5160->config->state = CONFIG_READY;
size_t i;
for(i = 0; i < TMC5160_REGISTER_COUNT; i++)
{
tmc5160->registerAccess[i] = tmc5160_defaultRegisterAccess[i];
tmc5160->registerResetState[i] = registerResetState[i];
}
}
// Fill the shadow registers of hardware preset non-readable registers
// Only needed if you want to 'read' those registers e.g to display the value
// in the TMCL IDE register browser
void tmc5160_fillShadowRegisters(TMC5160TypeDef *tmc5160)
{
// Check if we have constants defined
if(ARRAY_SIZE(tmc5160_RegisterConstants) == 0)
return;
size_t i, j;
for(i = 0, j = 0; i < TMC5160_REGISTER_COUNT; i++)
{
// We only need to worry about hardware preset, write-only registers
// that have not yet been written (no dirty bit) here.
if(tmc5160->registerAccess[i] != TMC_ACCESS_W_PRESET)
continue;
// Search the constant list for the current address. With the constant
// list being sorted in ascended order, we can walk through the list
// until the entry with an address equal or greater than i
while(j < ARRAY_SIZE(tmc5160_RegisterConstants) && (tmc5160_RegisterConstants[j].address < i))
j++;
// Abort when we reach the end of the constant list
if (j == ARRAY_SIZE(tmc5160_RegisterConstants))
break;
// If we have an entry for our current address, write the constant
if(tmc5160_RegisterConstants[j].address == i)
{
tmc5160->config->shadowRegister[i] = tmc5160_RegisterConstants[j].value;
}
}
}
// Reset the TMC5160.
uint8_t tmc5160_reset(TMC5160TypeDef *tmc5160)
{
if(tmc5160->config->state != CONFIG_READY)
return false;
// Reset the dirty bits and wipe the shadow registers
size_t i;
for(i = 0; i < TMC5160_REGISTER_COUNT; i++)
{
tmc5160->registerAccess[i] &= ~TMC_ACCESS_DIRTY;
tmc5160->config->shadowRegister[i] = 0;
}
tmc5160->config->state = CONFIG_RESET;
tmc5160->config->configIndex = 0;
if(tmc5160->config->state != CONFIG_READY){
writeConfiguration(tmc5160);
}
return true;
}
// Restore the TMC5160 to the state stored in the shadow registers.
// This can be used to recover the IC configuration after a VM power loss.
uint8_t tmc5160_restore(TMC5160TypeDef *tmc5160)
{
if(tmc5160->config->state != CONFIG_READY)
return false;
tmc5160->config->state = CONFIG_RESTORE;
tmc5160->config->configIndex = 0;
if(tmc5160->config->state != CONFIG_READY){
writeConfiguration(tmc5160);
}
return true;
}
// Change the values the IC will be configured with when performing a reset.
void tmc5160_setRegisterResetState(TMC5160TypeDef *tmc5160, const int32_t *resetState)
{
size_t i;
for(i = 0; i < TMC5160_REGISTER_COUNT; i++)
{
tmc5160->registerResetState[i] = resetState[i];
}
}
// Register a function to be called after completion of the configuration mechanism
void tmc5160_setCallback(TMC5160TypeDef *tmc5160, tmc5160_callback callback)
{
tmc5160->config->callback = (tmc_callback_config) callback;
}
// Helper function: Configure the next register.
static void writeConfiguration(TMC5160TypeDef *tmc5160)
{
uint8_t *ptr = &tmc5160->config->configIndex;
const int32_t *settings;
if(tmc5160->config->state == CONFIG_RESTORE)
{
settings = tmc5160->config->shadowRegister;
// Find the next restorable register
while((*ptr < TMC5160_REGISTER_COUNT) && !TMC_IS_RESTORABLE(tmc5160->registerAccess[*ptr]))
{
(*ptr)++;
}
}
else
{
settings = tmc5160->registerResetState;
// Find the next resettable register
while((*ptr < TMC5160_REGISTER_COUNT) && !TMC_IS_RESETTABLE(tmc5160->registerAccess[*ptr]))
{
(*ptr)++;
}
}
if(*ptr < TMC5160_REGISTER_COUNT)
{
tmc5160_writeInt(tmc5160, *ptr, settings[*ptr]);
(*ptr)++;
}
else // Finished configuration
{
if(tmc5160->config->callback)
{
((tmc5160_callback)tmc5160->config->callback)(tmc5160, tmc5160->config->state);
}
tmc5160->config->state = CONFIG_READY;
}
}
// Call this periodically
void tmc5160_periodicJob(TMC5160TypeDef *tmc5160, uint32_t tick)
{
#if 0
if(tmc5160->config->state != CONFIG_READY)
{
writeConfiguration(tmc5160);
return;
}
#endif
int32_t XActual;
uint32_t tickDiff;
// Calculate velocity v = dx/dt
if((tickDiff = tick - tmc5160->oldTick) >= 5)
{
XActual = tmc5160_readInt(tmc5160, TMC5160_XACTUAL);
// ToDo CHECK 2: API Compatibility - write alternative algorithm w/o floating point? (LH)
tmc5160->velocity = (uint32_t) ((float32_t) ((XActual - tmc5160->oldX) / (float32_t) tickDiff) * (float32_t) 1048.576);
tmc5160->oldX = XActual;
tmc5160->oldTick = tick;
}
}
// Rotate with a given velocity (to the right)
void tmc5160_rotate(TMC5160TypeDef *tmc5160, int32_t velocity)
{
// Set absolute velocity
tmc5160_writeInt(tmc5160, TMC5160_VMAX, abs(velocity));
// Set direction
tmc5160_writeInt(tmc5160, TMC5160_RAMPMODE, (velocity >= 0) ? TMC5160_MODE_VELPOS : TMC5160_MODE_VELNEG);
}
// Rotate to the right
void tmc5160_right(TMC5160TypeDef *tmc5160, uint32_t velocity)
{
tmc5160_rotate(tmc5160, velocity);
}
// Rotate to the left
void tmc5160_left(TMC5160TypeDef *tmc5160, uint32_t velocity)
{
tmc5160_rotate(tmc5160, -velocity);
}
// Stop moving
void tmc5160_stop(TMC5160TypeDef *tmc5160)
{
tmc5160_rotate(tmc5160, 0);
}
// Move to a specified position with a given velocity
void tmc5160_moveTo(TMC5160TypeDef *tmc5160, int32_t position, uint32_t velocityMax)
{
tmc5160_writeInt(tmc5160, TMC5160_RAMPMODE, TMC5160_MODE_POSITION);
// VMAX also holds the target velocity in velocity mode.
// Re-write the position mode maximum velocity here.
tmc5160_writeInt(tmc5160, TMC5160_VMAX, velocityMax);
tmc5160_writeInt(tmc5160, TMC5160_XTARGET, position);
}
// Move by a given amount with a given velocity
// This function will write the absolute target position to *ticks
void tmc5160_moveBy(TMC5160TypeDef *tmc5160, int32_t *ticks, uint32_t velocityMax)
{
// determine actual position and add numbers of ticks to move
*ticks += tmc5160_readInt(tmc5160, TMC5160_XACTUAL);
tmc5160_moveTo(tmc5160, *ticks, velocityMax);
}
uint8_t tmc5160_consistencyCheck(TMC5160TypeDef *tmc5160)
{
// Config has not yet been written -> it cant be consistent
if(tmc5160->config->state != CONFIG_READY)
return 0;
// Check constant shadow registers consistent with actual registers
for(size_t i = 0; i < TMC5160_REGISTER_COUNT; i++)
if(tmc5160->config->shadowRegister[i] != tmc5160_readInt(tmc5160, i))
return 1;
// No inconsistency detected
return 0;
}
#endif

48
components/tmc/ic/ztmc5130.cpp

@ -12,18 +12,30 @@ using namespace iflytop;
#define PRV_FIELD_WRITE(address, mask, shift, value) (writeInt(address, FIELD_SET(readInt(address), mask, shift, value))) #define PRV_FIELD_WRITE(address, mask, shift, value) (writeInt(address, FIELD_SET(readInt(address), mask, shift, value)))
#define PRV_FIELD_READ(address, mask, shift) FIELD_GET(readInt(address), mask, shift) #define PRV_FIELD_READ(address, mask, shift) FIELD_GET(readInt(address), mask, shift)
#define SET_PIN(pin, val) \
if (pin) { \
pin->setState(val); \
}
TMC5130::TMC5130(/* args */) {} TMC5130::TMC5130(/* args */) {}
void TMC5130::createDeafultTMC5130Config(TMC5130Config_t *config, TMC5130Port *m_port) {
config->m_port = m_port;
config->autoReadEventRegisterInterval = 10;
config->autoReadEventRegister = true;
}
void TMC5130::initialize(uint8_t channel, TMC5130Config_t *config) {
m_channel = channel;
m_config = config;
m_port = config->m_port;
void TMC5130::initialize(cfg_t *cfg) {
m_cfg = *cfg;
// m_channel = channel;
// m_config = config;
// m_port = config->m_port;
m_registerAccessTable = &tmc5130_defaultRegisterAccess[0]; m_registerAccessTable = &tmc5130_defaultRegisterAccess[0];
m_defaultRegisterResetState = &tmc5130_defaultRegisterResetState[0]; m_defaultRegisterResetState = &tmc5130_defaultRegisterResetState[0];
if (cfg->csn_pin != PinNull) {
m_csnpin = new ZGPIO();
m_csnpin->initAsOutput(cfg->csn_pin, ZGPIO::kMode_nopull, false, true);
}
if (cfg->enn_pin != PinNull) {
m_ennpin = new ZGPIO();
m_ennpin->initAsOutput(cfg->enn_pin, ZGPIO::kMode_nopull, false, true);
}
ZGPIO *m_csnpin;
ZGPIO *m_ennpin;
enableIC(false); enableIC(false);
// tmc5130_init(&m_TMC5130, channel, &m_tmc_api_config, &tmc5130_defaultRegisterResetState[0]); // tmc5130_init(&m_TMC5130, channel, &m_tmc_api_config, &tmc5130_defaultRegisterResetState[0]);
@ -55,12 +67,18 @@ void TMC5130::initialize(uint8_t channel, TMC5130Config_t *config) {
enableIC(true); enableIC(true);
} }
void TMC5130::enableIC(bool enable) { m_port->TMC5130Port_setENNPinState(m_channel, !enable); }
void TMC5130::enableIC(bool enable) {
// m_port->TMC5130Port_setENNPinState(m_channel, !enable);
SET_PIN(m_ennpin, !enable);
}
uint8_t TMC5130::reset() { uint8_t TMC5130::reset() {
stop(); stop();
m_port->TMC5130Port_setResetNPinState(m_channel, false);
m_port->TMC5130Port_sleepus(1000);
m_port->TMC5130Port_setResetNPinState(m_channel, true);
// m_port->TMC5130Port_setResetNPinState(m_channel, false);
SET_PIN(m_csnpin, false);
// m_port->TMC5130Port_sleepus(1000);
chip_delay_us(1000);
// m_port->TMC5130Port_setResetNPinState(m_channel, true);
SET_PIN(m_csnpin, true);
for (uint32_t add = 0; add < TMC5130_REGISTER_COUNT; add++) { for (uint32_t add = 0; add < TMC5130_REGISTER_COUNT; add++) {
if (!TMC_IS_RESETTABLE(m_registerAccessTable[add])) { if (!TMC_IS_RESETTABLE(m_registerAccessTable[add])) {
@ -120,7 +138,6 @@ bool TMC5130::isReachTarget() {
} }
return false; return false;
} }
void TMC5130::periodicJob(uint32_t now) {}
/******************************************************************************* /*******************************************************************************
* basic * * basic *
*******************************************************************************/ *******************************************************************************/
@ -130,7 +147,8 @@ void TMC5130::writeSubRegister(uint8_t address, uint32_t mask, uint32_t shift, u
} }
void TMC5130::readWriteArray(uint8_t *data, size_t length) { void TMC5130::readWriteArray(uint8_t *data, size_t length) {
CriticalContext cc; CriticalContext cc;
m_port->TMC5130Port_readWriteArray(m_channel, data, length);
// m_port->TMC5130Port_readWriteArray(m_channel, data, length);
HAL_SPI_TransmitReceive(m_hspi, data, data, length, 100);
} }
void TMC5130::writeDatagram(uint8_t address, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4) { void TMC5130::writeDatagram(uint8_t address, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4) {
CriticalContext cc; CriticalContext cc;

61
components/tmc/ic/ztmc5130.hpp

@ -57,50 +57,28 @@ class Tmc5130RampStat {
bool isSetted(ramp_stat_bit_t bit) { return (m_state & bit) != 0; } bool isSetted(ramp_stat_bit_t bit) { return (m_state & bit) != 0; }
}; };
class TMC5130Port {
public:
/**
* @brief 使
*
* @param state
*/
virtual void TMC5130Port_setENNPinState(uint16_t channel, bool state) = 0;
/**
* @brief TMC5130没有复位引脚
*
* @param channel
* @param state
*/
virtual void TMC5130Port_setResetNPinState(uint16_t channel, bool state) = 0;
/**
* @brief us级别延时函数
*
* @param us
*/
virtual void TMC5130Port_sleepus(int32_t us) = 0;
/**
* @brief SPI读写接口
*
* @param data
* @param length
*/
virtual void TMC5130Port_readWriteArray(uint16_t channel, uint8_t *data, size_t length) = 0;
};
class TMC5130 : public IStepperMotor { class TMC5130 : public IStepperMotor {
public: public:
typedef struct { typedef struct {
bool autoReadEventRegister; // 是否自动读取事件寄存器
uint32_t autoReadEventRegisterInterval; // 自动读取事件寄存器的时间间隔,单位为ms
TMC5130Port *m_port;
} TMC5130Config_t;
SPI_HandleTypeDef *hspi;
Pin_t enn_pin;
Pin_t csn_pin;
} cfg_t;
protected: protected:
TMC5130Port *m_port;
TMC5130Config_t *m_config;
uint8_t m_channel;
uint32_t m_lastCallPeriodicJobTick;
int32_t m_shadowRegister[TMC_REGISTER_COUNT];
// TMC5130Port *m_port;
// TMC5130Config_t *m_config;
cfg_t m_cfg;
ZGPIO *m_csnpin;
ZGPIO *m_ennpin;
SPI_HandleTypeDef *m_hspi;
// uint8_t m_channel;
uint32_t m_lastCallPeriodicJobTick;
int32_t m_shadowRegister[TMC_REGISTER_COUNT];
const uint8_t *m_registerAccessTable; const uint8_t *m_registerAccessTable;
const int32_t *m_defaultRegisterResetState; const int32_t *m_defaultRegisterResetState;
@ -108,9 +86,8 @@ class TMC5130 : public IStepperMotor {
public: public:
TMC5130(/* args */); TMC5130(/* args */);
static void createDeafultTMC5130Config(TMC5130Config_t *config, TMC5130Port *m_port);
void initialize(uint8_t channel, TMC5130Config_t *config);
void periodicJob(uint32_t ticket);
// static void createDeafultTMC5130Config(TMC5130Config_t *config, TMC5130Port *m_port);
void initialize(cfg_t *cfg);
void enableIC(bool enable); void enableIC(bool enable);
uint8_t reset(); uint8_t reset();

9
hal/zhal_core.cpp

@ -31,3 +31,12 @@ void ZHALCORE::loop() {
periodJob->schedule_times++; periodJob->schedule_times++;
} }
} }
void ZHALCORE::initialize(cfg_t oscfg) {
iflytop_no_os_cfg_t cfg = {
.delayhtim = oscfg.delayhtim,
.debuguart = oscfg.debuguart,
};
iflytop_no_os_init(&cfg);
}

7
hal/zhal_core.hpp

@ -23,6 +23,11 @@ class ZHALCORE {
public: public:
}; };
typedef struct {
TIM_HandleTypeDef* delayhtim;
UART_HandleTypeDef* debuguart;
} cfg_t;
class PeriodJob { class PeriodJob {
public: public:
PeriodJob(function<void(Context& context)> job, uint32_t period_ms) { PeriodJob(function<void(Context& context)> job, uint32_t period_ms) {
@ -41,7 +46,7 @@ class ZHALCORE {
ZHALCORE() {} ZHALCORE() {}
static ZHALCORE* getInstance() { return &ZHALCORE_instance; } static ZHALCORE* getInstance() { return &ZHALCORE_instance; }
void initialize(){};
void initialize(cfg_t oscfg);
void regPeriodJob(function<void(Context& context)> job, uint32_t period_ms); void regPeriodJob(function<void(Context& context)> job, uint32_t period_ms);
void loop(); void loop();

Loading…
Cancel
Save