Ny structure. Start of the "main" branch
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Licensed under the GNU General Public License version 2 with exceptions. See
|
||||
* LICENSE file in the project root for full license information
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief
|
||||
* ESC hardware layer functions.
|
||||
*
|
||||
* Function to read and write commands to the ESC. Used to read/write ESC
|
||||
* registers and memory.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "esc.h"
|
||||
#include "spi_utils.h"
|
||||
#include "rst.h"
|
||||
|
||||
#define MAX_READ_SIZE 128
|
||||
|
||||
#define ESC_CMD_READ 0x02
|
||||
#define ESC_CMD_READWS 0x03
|
||||
#define ESC_CMD_WRITE 0x04
|
||||
#define ESC_CMD_NOP 0x00
|
||||
#define ESC_TERM 0xff
|
||||
#define ESC_NEXT 0x00
|
||||
|
||||
#define ESCREG_PDI_CONTROL 0x0140
|
||||
#define ESCREG_ESC_CONFIG 0x0141
|
||||
#define DC_SYNC_OUT 0x04
|
||||
#define ESCREG_CYCLIC_UNIT_CONTROL 0x0980
|
||||
#define SYNC_OUT_UNIT_CONTROL_MASK 0x01
|
||||
#define SYNC_OUT_ECAT_CONTROL 0x00
|
||||
#define SYNC_OUT_PDI_CONTROL 0x01
|
||||
#define ESCREG_SYNC0_CYCLE_TIME 0x09A0
|
||||
#define ESCREG_SYNC_START_TIME 0x0990
|
||||
// measured with 21MHz SPI PDI
|
||||
#define SYNC_START_OFFSET 2342840
|
||||
|
||||
static int et1100 = -1;
|
||||
static uint8_t read_termination[MAX_READ_SIZE] = {0};
|
||||
|
||||
#define GPIO_ECAT_RESET 1 /* specific function to hold ESC reset on startup \
|
||||
* when emulating EEPROM \
|
||||
*/
|
||||
|
||||
static void esc_address(uint16_t address, uint8_t command)
|
||||
{
|
||||
/* Device is selected already.
|
||||
* We use 2 bytes addressing.
|
||||
*/
|
||||
uint8_t data[2];
|
||||
|
||||
/* address 12:5 */
|
||||
data[0] = (address >> 5);
|
||||
/* address 4:0 and cmd 2:0 */
|
||||
data[1] = ((address & 0x1F) << 3) | command;
|
||||
|
||||
/* Write (and read AL interrupt register) */
|
||||
spi_bidirectionally_transfer(et1100, (uint8_t *)&ESCvar.ALevent,
|
||||
data, sizeof(data));
|
||||
ESCvar.ALevent = etohs(ESCvar.ALevent);
|
||||
}
|
||||
|
||||
/** ESC read function used by the Slave stack.
|
||||
*
|
||||
* @param[in] address = address of ESC register to read
|
||||
* @param[out] buf = pointer to buffer to read in
|
||||
* @param[in] len = number of bytes to read
|
||||
*/
|
||||
|
||||
void ESC_read(uint16_t address, void *buf, uint16_t len)
|
||||
{
|
||||
if (len > MAX_READ_SIZE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Select device. */
|
||||
spi_select(et1100);
|
||||
|
||||
/* Write address and command to device. */
|
||||
esc_address(address, ESC_CMD_READ);
|
||||
|
||||
/* Here we want to read data and keep MOSI low (0x00) during
|
||||
* all bytes except the last one where we want to pull it high (0xFF).
|
||||
* Read (and write termination bytes).
|
||||
*/
|
||||
spi_bidirectionally_transfer(et1100, buf, read_termination + (MAX_READ_SIZE - len), len);
|
||||
|
||||
/* Un-select device. */
|
||||
spi_unselect(et1100);
|
||||
}
|
||||
|
||||
/** ESC write function used by the Slave stack.
|
||||
*
|
||||
* @param[in] address = address of ESC register to write
|
||||
* @param[out] buf = pointer to buffer to write from
|
||||
* @param[in] len = number of bytes to write
|
||||
*/
|
||||
void ESC_write(uint16_t address, void *buf, uint16_t len)
|
||||
{
|
||||
/* Select device. */
|
||||
spi_select(et1100);
|
||||
/* Write address and command to device. */
|
||||
esc_address(address, ESC_CMD_WRITE);
|
||||
/* Write data. */
|
||||
spi_write(et1100, buf, len);
|
||||
/* Un-select device. */
|
||||
spi_unselect(et1100);
|
||||
}
|
||||
|
||||
static void task_delay(uint32_t time_us)
|
||||
{
|
||||
#define DELAY_1_uS 168 // todo tweak to used clock speed
|
||||
uint32_t delay_ticks = DELAY_1_uS * time_us;
|
||||
|
||||
for (int32_t i = 0; i < delay_ticks; ++i)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
void ESC_reset(void)
|
||||
{
|
||||
volatile uint32_t timeout;
|
||||
|
||||
DPRINT("esc_reset_started\n");
|
||||
|
||||
rst_low();
|
||||
task_delay(1000);
|
||||
|
||||
rst_check_start();
|
||||
|
||||
while (timeout < 10000000)
|
||||
{
|
||||
/* ECAT releases resetpin, typically takes 40 us
|
||||
Reset to operational PDI is max 70 ms */
|
||||
if (is_esc_reset())
|
||||
{
|
||||
rst_high();
|
||||
break; // OK
|
||||
}
|
||||
timeout++;
|
||||
task_delay(30);
|
||||
}
|
||||
DPRINT("esc_reset_ended\n");
|
||||
}
|
||||
|
||||
void ESC_init(const esc_cfg_t *config)
|
||||
{
|
||||
rst_setup();
|
||||
rst_high();
|
||||
spi_setup();
|
||||
et1100 = 1;
|
||||
read_termination[MAX_READ_SIZE - 1] = 0xFF;
|
||||
|
||||
// uint8_t device_symbol = 0;
|
||||
// while (device_symbol == 0)
|
||||
// {
|
||||
// ESC_read(et1100, (void *)&device_symbol, sizeof(uint8_t));
|
||||
// if ((device_symbol != 0) || (device_symbol != 0xFF))
|
||||
// {
|
||||
// DPRINT("ESC init successful");
|
||||
// }
|
||||
// }
|
||||
// task_delay(1000); // allow ESC to load EEPROM, or if EEP_DONE can be read
|
||||
// then wait while EEP_DONE is low.
|
||||
}
|
||||
|
||||
/** ESC enable Distributed Clocks (DC)
|
||||
*
|
||||
* @return SYNC0 cycle time
|
||||
*/
|
||||
uint32_t ESC_enable_DC()
|
||||
{
|
||||
uint8_t data = 0x00;
|
||||
|
||||
// check DC Sync Out bit: 0x140:10
|
||||
ESC_read(ESCREG_ESC_CONFIG, &data, sizeof(data));
|
||||
if (!(data & DC_SYNC_OUT))
|
||||
{
|
||||
return 0; // DC sync is not enabled in ESI
|
||||
}
|
||||
|
||||
// read set SYNC0 Cycle Time from 0x09A0
|
||||
uint32_t setsync0cycleTime = 0;
|
||||
ESC_read(ESCREG_SYNC0_CYCLE_TIME, &setsync0cycleTime, sizeof(uint32_t));
|
||||
setsync0cycleTime = etohl(setsync0cycleTime);
|
||||
|
||||
// check Sync Unit assign 0x0980:0 ( 0 for ECAT, 1 for PDI )
|
||||
ESC_read(ESCREG_CYCLIC_UNIT_CONTROL, &data, sizeof(data));
|
||||
if (data == SYNC_OUT_PDI_CONTROL)
|
||||
{
|
||||
// Sync Unit assigned to PDI, configuration needs to be finished by slave
|
||||
|
||||
// set sync start time: read system time, add offset for writing start time and activation
|
||||
ESC_read(ESCREG_LOCALTIME, (void *)&ESCvar.Time, sizeof(ESCvar.Time));
|
||||
ESCvar.Time = etohl(ESCvar.Time);
|
||||
uint32_t startTime = ESCvar.Time + SYNC_START_OFFSET;
|
||||
|
||||
ESC_write(ESCREG_SYNC_START_TIME, &startTime, sizeof(startTime));
|
||||
|
||||
// activate cyclic operation and SYNC0
|
||||
ESC_read(ESCREG_SYNC_ACT, &data, sizeof(data));
|
||||
data = data | ESCREG_SYNC_ACT_ACTIVATED | ESCREG_SYNC_SYNC0_EN;
|
||||
ESC_write(ESCREG_SYNC_ACT, &data, sizeof(data));
|
||||
data = 0x00;
|
||||
while (!(data & (ESCREG_SYNC_ACT_ACTIVATED | ESCREG_SYNC_SYNC0_EN)))
|
||||
{
|
||||
ESC_read(ESCREG_SYNC_ACT, &data, sizeof(data));
|
||||
}
|
||||
}
|
||||
|
||||
return setsync0cycleTime;
|
||||
}
|
||||
Reference in New Issue
Block a user