Ny structure. Start of the "main" branch

This commit is contained in:
Hakan Bastedt
2024-11-20 11:18:13 +01:00
parent 31b896871d
commit 1918604586
415 changed files with 202039 additions and 21080 deletions

View File

@@ -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;
}

View File

@@ -0,0 +1,32 @@
#include <Arduino.h>
#include "rst.h"
void rst_setup(void)
{
/* Set RSTN as ouput */
pinMode(ESC_Pin_RSTN, OUTPUT);
rst_high();
}
void rst_low(void)
{ /* Set RSTN line low */
digitalWrite(ESC_Pin_RSTN, LOW);
}
void rst_high(void)
{
/* Set RSTN line high */
digitalWrite(ESC_Pin_RSTN, HIGH);
}
void rst_check_start(void)
{
/* Setup NRST as GPIO input and pull it high */
pinMode(ESC_Pin_RSTN, INPUT_PULLUP);
}
uint8_t is_esc_reset(void)
{
/* Check if ESC pulled RSTN line up */
return digitalRead(ESC_Pin_RSTN);
}

View File

@@ -0,0 +1,21 @@
#ifndef __RST_H__
#define __RST_H__
#define ESC_Pin_RSTN PB12
#ifdef __cplusplus
extern "C" {
#endif
void rst_setup(void);
void rst_low(void);
void rst_high(void);
void rst_check_start(void);
uint8_t is_esc_reset(void);
#ifdef __cplusplus
}
#endif
#endif /* __RST_H__ */

View File

@@ -0,0 +1,66 @@
#include "spi_utils.h"
// #include <Arduino.h>
#include <SPI.h>
char SCS = ESC_GPIO_Pin_CS;
void spi_setup(void)
{
SPI.begin();
pinMode(SCS, OUTPUT);
spi_unselect(0);
delay(100);
SPI.beginTransaction(SPISettings(SPIX_ESC_SPEED, MSBFIRST, SPI_MODE3));
}
void spi_select (int8_t board)
{
// Soft CSN
#if SCS_ACTIVE_POLARITY == SCS_LOW
digitalWrite(SCS, LOW);
#endif
}
void spi_unselect (int8_t board)
{
// Soft CSN
#if SCS_ACTIVE_POLARITY == SCS_LOW
digitalWrite(SCS, HIGH);
#endif
}
inline static uint8_t spi_transfer_byte(uint8_t byte)
{
return SPI.transfer(byte);
// AVR will need handling last byte transfer difference,
// but then again they pobably wont even fit EtherCAT stack in RAM
// so no need to care for now
}
void spi_write (int8_t board, uint8_t *data, uint8_t size)
{
for(int i = 0; i < size; ++i)
{
spi_transfer_byte(data[i]);
}
}
void spi_read (int8_t board, uint8_t *result, uint8_t size)
{
for(int i = 0; i < size; ++i)
{
result[i] = spi_transfer_byte(DUMMY_BYTE);
}
}
void spi_bidirectionally_transfer (int8_t board, uint8_t *result, uint8_t *data, uint8_t size)
{
for(int i = 0; i < size; ++i)
{
result[i] = spi_transfer_byte(data[i]);
}
}

View File

@@ -0,0 +1,31 @@
#ifndef SRC_APP_SPI_H_
#define SRC_APP_SPI_H_
#include <stdint.h>
#define SCS_LOW LOW
#define SCS_HIGH HIGH
#define SCS_ACTIVE_POLARITY SCS_LOW
// 80 MHz
#define SPIX_ESC_SPEED 80000000
#define ESC_GPIO_Pin_CS PC4
#define DUMMY_BYTE 0xFF
#ifdef __cplusplus
extern "C" {
#endif
void spi_setup(void);
void spi_select (int8_t board);
void spi_unselect (int8_t board);
void spi_write (int8_t board, uint8_t *data, uint8_t size);
void spi_read (int8_t board, uint8_t *result, uint8_t size);
void spi_bidirectionally_transfer (int8_t board, uint8_t *result, uint8_t *data, uint8_t size);
#ifdef __cplusplus
}
#endif
#endif /* SRC_APP_SPI_H_ */