sync PikaStdDevice for SPI/SOFT_SPI enhance

This commit is contained in:
lyon 2024-02-11 21:43:49 +08:00
parent 6fba67f236
commit fdb9b1baa7
8 changed files with 291 additions and 75 deletions

View File

@ -436,6 +436,9 @@ class SPI(BaseDev):
def setPinMISO(self, pin: str):
"""Set the MISO pin."""
def setPinCS(self, pin: str):
"""Set the CS pin."""
def setName(self, name: str):
"""Use the device name to select the SPI pin.
exmpale: `"SPI0"`, `"SPI1"` ...
@ -473,25 +476,6 @@ class SPI(BaseDev):
def readBytes(self, length: int) -> bytes:
"""Read bytes from the SPI."""
@abstractmethod
def platformEnable(self): ...
@abstractmethod
def platformWrite(self): ...
@abstractmethod
def platformWriteBytes(self): ...
@abstractmethod
def platformRead(self): ...
@abstractmethod
def platformReadBytes(self): ...
@abstractmethod
def platformDisable(self): ...
class CAN(BaseDev):
def __init__(self): ...

View File

@ -4,50 +4,140 @@
void PikaStdDevice_SPI___init__(PikaObj* self) {
obj_setInt(self, "baudRate", 1000);
obj_setInt(self, "id", 0);
obj_setStr(self, "name", "none");
obj_setStr(self, "name", "SOFT");
obj_setInt(self, "phase", 0);
obj_setStr(self, "MISOpin", "none");
obj_setStr(self, "MOSIpin", "none");
obj_setStr(self, "SCKpin", "none");
obj_setInt(self, "polarity", 0);
obj_setPtr(self, "pika_dev", NULL);
}
static pika_dev* _get_dev(PikaObj* self) {
pika_dev* dev = PIKA_HAL_OBJ2DEV(self);
if (NULL != dev) {
return dev;
}
char* name = obj_getStr(self, "name");
if (0 == strcmp(name, "SOFT")) {
dev = pika_hal_open(PIKA_HAL_SOFT_SPI, name);
pika_debug("Open soft spi %s\r\n", name);
} else {
dev = pika_hal_open(PIKA_HAL_SPI, name);
pika_debug("Open spi %s\r\n", name);
}
if (NULL == dev) {
__platform_printf("Error: open IIC '%s' failed.\r\n",
obj_getStr(self, "name"));
return NULL;
}
obj_setPtr(self, "pika_dev", dev);
return dev;
}
void PikaStdDevice_SPI_disable(PikaObj* self) {
obj_runNativeMethod(self, "platformDisable", NULL);
pika_dev* dev = _get_dev(self);
if (NULL == dev) {
pika_platform_printf("Error: SPI '%s' not found.\r\n",
obj_getStr(self, "name"));
return;
}
pika_hal_ioctl(dev, PIKA_HAL_IOCTL_DISABLE);
}
void PikaStdDevice_SPI_enable(PikaObj* self) {
obj_runNativeMethod(self, "platformEnable", NULL);
pika_dev* dev = _get_dev(self);
if (NULL == dev) {
pika_platform_printf("Error: SPI '%s' not found.\r\n",
obj_getStr(self, "name"));
return;
}
pika_hal_ioctl(dev, PIKA_HAL_IOCTL_ENABLE);
}
void PikaStdDevice_SPI_write(PikaObj* self, char* data) {
obj_setStr(self, "writeData", data);
obj_runNativeMethod(self, "platformWrite", NULL);
pika_dev* dev = _get_dev(self);
if (NULL == dev) {
pika_platform_printf("Error: SPI '%s' not found.\r\n",
obj_getStr(self, "name"));
return;
}
pika_hal_write(dev, data, strlen(data));
}
void PikaStdDevice_SPI_writeBytes(PikaObj* self, uint8_t* data, int length) {
obj_setBytes(self, "writeData", data, length);
obj_runNativeMethod(self, "platformWriteBytes", NULL);
pika_dev* dev = _get_dev(self);
if (NULL == dev) {
pika_platform_printf("Error: SPI '%s' not found.\r\n",
obj_getStr(self, "name"));
return;
}
pika_hal_write(dev, data, length);
}
char* PikaStdDevice_SPI_read(PikaObj* self, int length) {
obj_setInt(self, "length", length);
obj_runNativeMethod(self, "platformRead", NULL);
return obj_getStr(self, "readData");
pika_dev* dev = _get_dev(self);
if (NULL == dev) {
pika_platform_printf("Error: SPI '%s' not found.\r\n",
obj_getStr(self, "name"));
return NULL;
}
char* data = (char*)pikaMalloc(length + 1);
if (NULL == data) {
pika_platform_printf("Error: SPI read failed, no memory.\r\n");
return NULL;
}
int ret = pika_hal_read(dev, data, length);
if (ret < 0) {
pikaFree(data, length + 1);
return NULL;
}
data[length] = '\0';
char* res = obj_cacheStr(self, data);
pikaFree(data, length + 1);
return res;
}
Arg* PikaStdDevice_SPI_readBytes(PikaObj* self, int length) {
obj_setInt(self, "length", length);
obj_runNativeMethod(self, "platformReadBytes", NULL);
return arg_copy(obj_getArg(self, "readData"));
pika_dev* dev = _get_dev(self);
if (NULL == dev) {
pika_platform_printf("Error: SPI '%s' not found.\r\n",
obj_getStr(self, "name"));
return NULL;
}
uint8_t* data = (uint8_t*)pikaMalloc(length);
if (NULL == data) {
pika_platform_printf("Error: SPI read failed, no memory.\r\n");
return NULL;
}
int ret = pika_hal_read(dev, data, length);
if (ret < 0) {
pikaFree(data, length);
return NULL;
}
Arg* res = arg_newBytes(data, length);
pikaFree(data, length);
return res;
}
void PikaStdDevice_SPI_setBaudRate(PikaObj* self, int baudRate) {
obj_setInt(self, "baudRate", baudRate);
pika_dev* dev = _get_dev(self);
if (NULL == dev) {
pika_platform_printf("Error: SPI '%s' not found.\r\n",
obj_getStr(self, "name"));
}
pika_hal_SPI_config cfg = {0};
cfg.speed = baudRate;
pika_hal_ioctl(dev, PIKA_HAL_IOCTL_CONFIG, &cfg);
}
void PikaStdDevice_SPI_setId(PikaObj* self, int id) {
obj_setInt(self, "id", id);
Args buffs = {0};
char* name = strsFormat(&buffs, 64, "SPI%d", id);
obj_setName(self, name);
args_deinit(&buffs);
}
void PikaStdDevice_SPI_setName(PikaObj* self, char* name) {
@ -60,40 +150,72 @@ void PikaStdDevice_SPI_setPhase(PikaObj* self, int phase) {
void PikaStdDevice_SPI_setPinMISO(PikaObj* self, char* pin) {
obj_setStr(self, "MISOpin", pin);
pika_dev* dev = _get_dev(self);
if (NULL == dev) {
pika_platform_printf("Error: SPI '%s' not found.\r\n",
obj_getStr(self, "name"));
return;
}
pika_hal_SPI_config cfg = {0};
cfg.MISO = pika_hal_open(PIKA_HAL_GPIO, pin);
if (NULL == cfg.MISO) {
pika_platform_printf("Error: open MISO '%s' failed.\r\n", pin);
return;
}
pika_hal_ioctl(dev, PIKA_HAL_IOCTL_CONFIG, &cfg);
}
void PikaStdDevice_SPI_setPinCS(PikaObj* self, char* pin) {
obj_setStr(self, "CSpin", pin);
pika_dev* dev = _get_dev(self);
if (NULL == dev) {
pika_platform_printf("Error: SPI '%s' not found.\r\n",
obj_getStr(self, "name"));
return;
}
pika_hal_SPI_config cfg = {0};
cfg.CS = pika_hal_open(PIKA_HAL_GPIO, pin);
if (NULL == cfg.CS) {
pika_platform_printf("Error: open CS '%s' failed.\r\n", pin);
return;
}
pika_hal_ioctl(dev, PIKA_HAL_IOCTL_CONFIG, &cfg);
}
void PikaStdDevice_SPI_setPinMOSI(PikaObj* self, char* pin) {
obj_setStr(self, "MOSIpin", pin);
pika_dev* dev = _get_dev(self);
if (NULL == dev) {
pika_platform_printf("Error: SPI '%s' not found.\r\n",
obj_getStr(self, "name"));
return;
}
pika_hal_SPI_config cfg = {0};
cfg.MOSI = pika_hal_open(PIKA_HAL_GPIO, pin);
if (NULL == cfg.MOSI) {
pika_platform_printf("Error: open MOSI '%s' failed.\r\n", pin);
return;
}
pika_hal_ioctl(dev, PIKA_HAL_IOCTL_CONFIG, &cfg);
}
void PikaStdDevice_SPI_setPinSCK(PikaObj* self, char* pin) {
obj_setStr(self, "SCKpin", pin);
pika_dev* dev = _get_dev(self);
if (NULL == dev) {
pika_platform_printf("Error: SPI '%s' not found.\r\n",
obj_getStr(self, "name"));
return;
}
pika_hal_SPI_config cfg = {0};
cfg.SCK = pika_hal_open(PIKA_HAL_GPIO, pin);
if (NULL == cfg.SCK) {
pika_platform_printf("Error: open SCK '%s' failed.\r\n", pin);
return;
}
pika_hal_ioctl(dev, PIKA_HAL_IOCTL_CONFIG, &cfg);
}
void PikaStdDevice_SPI_setPolarity(PikaObj* self, int polarity) {
obj_setInt(self, "polarity", polarity);
}
void PikaStdDevice_SPI_platformDisable(PikaObj* self) {
ABSTRACT_METHOD_NEED_OVERRIDE_ERROR();
}
void PikaStdDevice_SPI_platformEnable(PikaObj* self) {
ABSTRACT_METHOD_NEED_OVERRIDE_ERROR();
}
void PikaStdDevice_SPI_platformWrite(PikaObj* self) {
ABSTRACT_METHOD_NEED_OVERRIDE_ERROR();
}
void PikaStdDevice_SPI_platformRead(PikaObj* self) {
ABSTRACT_METHOD_NEED_OVERRIDE_ERROR();
}
void PikaStdDevice_SPI_platformWriteBytes(PikaObj* self) {
ABSTRACT_METHOD_NEED_OVERRIDE_ERROR();
}
void PikaStdDevice_SPI_platformReadBytes(PikaObj* self) {
ABSTRACT_METHOD_NEED_OVERRIDE_ERROR();
}

View File

@ -42,6 +42,8 @@ pika_dev* pika_hal_open(PIKA_HAL_DEV_TYPE dev_type, char* name) {
if (dev == NULL) {
goto __exit;
}
pika_debug("pika_hal_open, dev[0x%p], type[%d], name[%s]", dev, dev_type,
name);
memset(dev, 0, sizeof(pika_dev));
dev->type = dev_type;
dev->ioctl_config = pikaMalloc(_pika_hal_dev_config_size(dev_type));
@ -90,10 +92,16 @@ __exit:
int pika_hal_read(pika_dev* dev, void* buf, size_t len) {
if (dev == NULL) {
pika_platform_printf("Error: dev is NULL.\r\n");
return -1;
}
if (!dev->is_enabled) {
pika_platform_printf("Error: dev is not enabled.\r\n");
return -1;
}
pika_dev_impl* impl = _pika_dev_get_impl(dev->type);
if (impl->read == NULL) {
pika_platform_printf("Error: read not support.\r\n");
return -1;
}
return impl->read(dev, buf, len);
@ -101,10 +109,16 @@ int pika_hal_read(pika_dev* dev, void* buf, size_t len) {
int pika_hal_write(pika_dev* dev, void* buf, size_t len) {
if (dev == NULL) {
pika_platform_printf("Error: dev is NULL.\r\n");
return -1;
}
if (!dev->is_enabled) {
pika_platform_printf("Error: dev is not enabled.\r\n");
return -1;
}
pika_dev_impl* impl = _pika_dev_get_impl(dev->type);
if (impl->write == NULL) {
pika_platform_printf("Error: write not support.\r\n");
return -1;
}
return impl->write(dev, buf, len);
@ -133,14 +147,19 @@ int pika_hal_ioctl(pika_dev* dev, PIKA_HAL_IOCTL_CMD cmd, ...) {
int ret = -1;
PIKA_HAL_IOCTL_CMD cmd_origin = cmd;
if (dev == NULL) {
pika_platform_printf("Error: dev is NULL.\r\n");
return -1;
}
pika_debug("pika_hal_ioctl, dev[0x%p], type[%d], cmd[%d]", dev, dev->type,
cmd);
cmd = _pika_hal_get_arg_cnt(cmd_origin);
if (cmd < 0) {
pika_platform_printf("Error: cmd invalied.\r\n");
return -1;
}
pika_dev_impl* impl = _pika_dev_get_impl(dev->type);
if (impl->ioctl == NULL) {
pika_platform_printf("Error: ioctl not support.\r\n");
return -1;
}
void* arg_in = NULL;
@ -155,6 +174,7 @@ int pika_hal_ioctl(pika_dev* dev, PIKA_HAL_IOCTL_CMD cmd, ...) {
}
va_end(args);
if (0 != ret) {
pika_platform_printf("Error: ioctl merge config failed.\r\n");
return ret;
}
}
@ -263,6 +283,10 @@ int pika_hal_SPI_ioctl_merge_config(pika_hal_SPI_config* dst,
_IOCTL_CONFIG_USE_DEFAULT(data_width, PIKA_HAL_SPI_DATA_WIDTH_8);
_IOCTL_CONFIG_USE_DEFAULT(speed, PIKA_HAL_SPI_SPEED_2M);
_IOCTL_CONFIG_USE_DEFAULT(timeout, PIKA_HAL_SPI_TIMEOUT_1000MS);
_IOCTL_CONFIG_USE_DEFAULT(CS, NULL);
_IOCTL_CONFIG_USE_DEFAULT(SCK, NULL);
_IOCTL_CONFIG_USE_DEFAULT(MOSI, NULL);
_IOCTL_CONFIG_USE_DEFAULT(MISO, NULL);
_IOCTL_CONFIG_USE_DEFAULT(user_data, NULL);
return 0;
}

View File

@ -301,6 +301,8 @@ typedef enum {
PIKA_HAL_SPI_SPEED_100M = 100000000,
} PIKA_HAL_SPI_SPEED;
#define PIKA_HAL_SPI_RX_BUFFER_SIZE 32
typedef struct {
PIKA_HAL_SPI_LSB_OR_MSB lsb_or_msb;
PIKA_HAL_SPI_MASTER_OR_SLAVE master_or_slave;
@ -308,6 +310,11 @@ typedef struct {
PIKA_HAL_SPI_DATA_WIDTH data_width;
PIKA_HAL_SPI_SPEED speed;
PIKA_HAL_SPI_TIMEOUT timeout;
pika_dev* CS; // Just for MCU with pin mux like ESP32
pika_dev* SCK; // Just for MCU with pin mux like ESP32
pika_dev* MOSI; // Just for MCU with pin mux like ESP32
pika_dev* MISO; // Just for MCU with pin mux like ESP32
uint8_t tranfer_rx_buffer[PIKA_HAL_SPI_RX_BUFFER_SIZE];
void* user_data;
} pika_hal_SPI_config;
@ -318,12 +325,13 @@ typedef struct {
PIKA_HAL_SPI_DATA_WIDTH data_width;
PIKA_HAL_SPI_SPEED speed;
PIKA_HAL_SPI_TIMEOUT timeout;
void* user_data;
// Uper must be the same with SPI_config
pika_dev* CS;
pika_dev* SCK;
pika_dev* MOSI;
pika_dev* MISO;
uint8_t tranfer_rx_buffer[PIKA_HAL_SPI_RX_BUFFER_SIZE];
void* user_data;
// Uper must be the same with SPI_config
} pika_hal_SOFT_SPI_config;
typedef enum {

View File

@ -34,16 +34,11 @@ int pika_hal_platform_SOFT_SPI_close(pika_dev* dev) {
int pika_hal_platform_SOFT_SPI_ioctl_config(pika_dev* dev,
pika_hal_SOFT_SPI_config* cfg) {
if (cfg->SCK == NULL || cfg->MOSI == NULL) {
__platform_printf(
"Error: SOFT SPI config error, CS, SCK, MOSI, MISO must be "
"set\r\n");
return -1;
}
return 0;
}
int pika_hal_platform_SOFT_SPI_ioctl_enable(pika_dev* dev) {
pika_debug("SOFT_SPI_ioctl_enable, dev[0x%p]", dev);
pika_hal_SOFT_SPI_config* cfg =
(pika_hal_SOFT_SPI_config*)dev->ioctl_config;
if (cfg->SCK == NULL || cfg->MOSI == NULL) {
@ -62,20 +57,28 @@ int pika_hal_platform_SOFT_SPI_ioctl_enable(pika_dev* dev) {
cfg_MISO.dir = PIKA_HAL_GPIO_DIR_IN;
if (NULL != cfg->CS) {
pika_debug("CS[0x%p] config", cfg->CS);
pika_hal_ioctl(cfg->CS, PIKA_HAL_IOCTL_CONFIG, &cfg_CS);
}
pika_debug("SCK[0x%p] config", cfg->SCK);
pika_hal_ioctl(cfg->SCK, PIKA_HAL_IOCTL_CONFIG, &cfg_SCK);
pika_debug("MOSI[0x%p] config", cfg->MOSI);
pika_hal_ioctl(cfg->MOSI, PIKA_HAL_IOCTL_CONFIG, &cfg_MOSI);
if (NULL != cfg->MISO) {
pika_debug("MISO[0x%p] config", cfg->MISO);
pika_hal_ioctl(cfg->MISO, PIKA_HAL_IOCTL_CONFIG, &cfg_MISO);
}
if (NULL != cfg->CS) {
pika_debug("CS[0x%p] enable", cfg->CS);
pika_hal_ioctl(cfg->CS, PIKA_HAL_IOCTL_ENABLE);
}
pika_debug("SCK[0x%p] enable", cfg->SCK);
pika_hal_ioctl(cfg->SCK, PIKA_HAL_IOCTL_ENABLE);
pika_debug("MOSI[0x%p] enable", cfg->MOSI);
pika_hal_ioctl(cfg->MOSI, PIKA_HAL_IOCTL_ENABLE);
if (NULL != cfg->MISO) {
pika_debug("MISO[0x%p] enable", cfg->MISO);
pika_hal_ioctl(cfg->MISO, PIKA_HAL_IOCTL_ENABLE);
}
@ -109,41 +112,63 @@ static inline void _SPI_delay(void) {
sleep_us(1);
}
static inline int SPIv_WriteData(pika_hal_SOFT_SPI_config* cfg,
uint8_t Data,
static inline int SPIv_TransferByte(pika_hal_SOFT_SPI_config* cfg,
uint8_t tx,
uint8_t* rx,
int is_msb) {
unsigned char i = 0;
uint8_t received_data = 0; // Used to store the received data
if (is_msb) {
for (i = 0; i < 8; i++) {
if (Data & 0x80) {
if (tx & 0x80) {
_GPIO_write(cfg->MOSI, 1);
} else {
_GPIO_write(cfg->MOSI, 0);
}
_GPIO_write(cfg->SCK, 0);
_SPI_delay();
received_data <<=
1; // Shift received data left, preparing for the new bit
if (NULL != cfg->MISO) {
if (_GPIO_read(cfg->MISO)) { // Read data from the MISO line
received_data |= 0x01; // If MISO is high, set the lowest
// bit of the received data to 1
}
}
_GPIO_write(cfg->SCK, 1);
_SPI_delay();
Data <<= 1;
tx <<= 1;
}
} else {
for (i = 0; i < 8; i++) {
if (Data & 0x01) {
if (tx & 0x01) {
_GPIO_write(cfg->MOSI, 1);
} else {
_GPIO_write(cfg->MOSI, 0);
}
_GPIO_write(cfg->SCK, 0);
_SPI_delay();
received_data >>=
1; // Shift received data right, preparing for the new bit
if (NULL != cfg->MISO) {
if (_GPIO_read(cfg->MISO)) { // Read data from the MISO line
received_data |= 0x80; // If MISO is high, set the highest
// bit of the received data to 1
}
}
_GPIO_write(cfg->SCK, 1);
_SPI_delay();
Data >>= 1;
tx >>= 1;
}
}
*rx = received_data; // Store the received data into the variable pointed
// to by rx
return 0;
}
static inline int SPIv_ReadData(pika_hal_SOFT_SPI_config* cfg, int is_msb) {
static inline int SPIv_ReadByte(pika_hal_SOFT_SPI_config* cfg, int is_msb) {
unsigned char i = 0;
unsigned char Data = 0;
if (is_msb) {
@ -182,7 +207,9 @@ int pika_hal_platform_SOFT_SPI_write(pika_dev* dev, void* buf, size_t count) {
}
int is_msb = cfg->lsb_or_msb == PIKA_HAL_SPI_MSB ? 1 : 0;
for (int i = 0; i < count; i++) {
SPIv_WriteData(cfg, data[i], is_msb);
SPIv_TransferByte(
cfg, data[i],
&cfg->tranfer_rx_buffer[i % PIKA_HAL_SPI_RX_BUFFER_SIZE], is_msb);
}
if (NULL != cfg->CS) {
_GPIO_write(cfg->CS, 1);
@ -205,7 +232,7 @@ int pika_hal_platform_SOFT_SPI_read(pika_dev* dev, void* buf, size_t count) {
}
int is_msb = cfg->lsb_or_msb == PIKA_HAL_SPI_MSB ? 1 : 0;
for (int i = 0; i < count; i++) {
data[i] = SPIv_ReadData(cfg, is_msb);
data[i] = SPIv_ReadByte(cfg, is_msb);
}
if (NULL != cfg->CS) {
_GPIO_write(cfg->CS, 1);

View File

@ -159,6 +159,53 @@ int pika_hal_utils_SPI_config(pika_dev* dev, pika_hal_SPI_config* cfg) {
return ret;
}
int pika_hal_utils_SPI_transfer(pika_dev* dev,
uint8_t* txbuff,
uint8_t* rxbuff,
uint32_t size) {
// Modify parameter check logic: allow unidirectional transfer
if (dev == NULL || (txbuff == NULL && rxbuff == NULL)) {
return -1; // Parameter check failed
}
pika_hal_SPI_config* cfg = (pika_hal_SPI_config*)dev->ioctl_config;
uint32_t transferred = 0; // Amount of data transferred
uint32_t remaining = size; // Amount of data remaining
uint32_t chunkSize; // Amount of data for the current batch transfer
while (remaining > 0) {
chunkSize = remaining > PIKA_HAL_SPI_RX_BUFFER_SIZE
? PIKA_HAL_SPI_RX_BUFFER_SIZE
: remaining;
// Call SPI_write to transfer data only if txbuff is not NULL
if (txbuff != NULL) {
pika_hal_write(dev, &txbuff[transferred], chunkSize);
}
// Call hal_read instead of directly retrieving data from
// transfer_rx_buffer only if rxbuff is not NULL
if (rxbuff != NULL) {
if (txbuff == NULL) {
// Perform data reception only
pika_hal_read(dev, &rxbuff[transferred], chunkSize);
} else {
// Handle both data sending and receiving, assuming hal_write
// already includes reading logic
for (uint32_t i = 0; i < chunkSize; i++) {
rxbuff[transferred + i] =
cfg->tranfer_rx_buffer[i % PIKA_HAL_SPI_RX_BUFFER_SIZE];
}
}
}
transferred += chunkSize; // Update the amount of data transferred
remaining -= chunkSize; // Update the amount of data remaining
}
return 0; // Successfully completed the transfer
}
/* ADC utils */
int pika_hal_utils_ADC_config(pika_dev* dev, pika_hal_ADC_config* cfg) {
int ret = pika_hal_ioctl(dev, PIKA_HAL_IOCTL_CONFIG, cfg);

View File

@ -42,6 +42,10 @@ int pika_hal_utils_IIC_set_slave_addr(pika_dev* dev, uint32_t slave_addr);
/* SPI utils */
int pika_hal_utils_SPI_config(pika_dev* dev, pika_hal_SPI_config* cfg);
int pika_hal_utils_SPI_transfer(pika_dev* dev,
uint8_t* txbuff,
uint8_t* rxbuff,
uint32_t size);
/* ADC utils */
int pika_hal_utils_ADC_config(pika_dev* dev, pika_hal_ADC_config* cfg);

View File

@ -2,4 +2,4 @@
#define PIKA_VERSION_MINOR 13
#define PIKA_VERSION_MICRO 2
#define PIKA_EDIT_TIME "2024/02/10 00:40:58"
#define PIKA_EDIT_TIME "2024/02/11 21:43:11"