Compare commits

...

1 Commits

2 changed files with 147 additions and 288 deletions

View File

@ -15,8 +15,8 @@
#ifndef _DRIVER_SPI_H
#define _DRIVER_SPI_H
#include <stdint.h>
#include <stddef.h>
#include <stdint.h>
#include "dmac.h"
#ifdef __cplusplus
@ -140,12 +140,11 @@ typedef enum _spi_transfer_mode
SPI_TMOD_EEROM
} spi_transfer_mode_t;
typedef enum _spi_transfer_width
{
SPI_TRANS_CHAR = 0x1,
SPI_TRANS_CHAR = 0x1,
SPI_TRANS_SHORT = 0x2,
SPI_TRANS_INT = 0x4,
SPI_TRANS_INT = 0x4,
} spi_transfer_width_t;
typedef enum _spi_chip_select
@ -157,23 +156,29 @@ typedef enum _spi_chip_select
SPI_CHIP_SELECT_MAX,
} spi_chip_select_t;
typedef enum
#define SPI_SLAVE_BUFFER_NUMBER_MAX 128
#define SPI_SLAVE_BUFFER_WRITE 0
#define SPI_SLAVE_BUFFER_READ 1
typedef union
{
WRITE_CONFIG,
READ_CONFIG,
WRITE_DATA_BYTE,
READ_DATA_BYTE,
WRITE_DATA_BLOCK,
READ_DATA_BLOCK,
} spi_slave_command_e;
uint32_t u32[2];
uint8_t u8[8];
struct
{
uint64_t rw:1;
uint64_t index:7;
uint64_t offset:24;
uint64_t length:24;
uint64_t cks_err:8;
} command __attribute__((packed, aligned(8)));
} spi_slave_command_t;
typedef struct
{
uint8_t cmd;
uint8_t err;
uint32_t addr;
uint32_t len;
} spi_slave_command_t;
uint32_t *address;
uint32_t length;
} spi_slave_buffer_desc_t;
typedef enum
{
@ -189,14 +194,10 @@ typedef struct _spi_slave_instance
uint8_t int_pin;
uint8_t ready_pin;
dmac_channel_number_t dmac_channel;
uint8_t dfs;
uint8_t slv_oe;
uint8_t work_mode;
size_t data_bit_length;
volatile spi_slave_status_e status;
volatile spi_slave_command_t command;
volatile uint8_t *config_ptr;
uint32_t config_len;
spi_slave_status_e status;
uint8_t config_len;
spi_slave_buffer_desc_t *config_ptr;
spi_slave_command_t command;
spi_slave_receive_callback_t callback;
} spi_slave_instance_t;
@ -447,9 +448,9 @@ uint32_t spi_set_clk_rate(spi_device_num_t spi_num, uint32_t spi_clk);
*
*/
void spi_dup_send_receive_data_dma(dmac_channel_number_t dma_send_channel_num,
dmac_channel_number_t dma_receive_channel_num,
spi_device_num_t spi_num, spi_chip_select_t chip_select,
const uint8_t *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len);
dmac_channel_number_t dma_receive_channel_num,
spi_device_num_t spi_num, spi_chip_select_t chip_select,
const uint8_t *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len);
/**
* @brief Set spi slave configuration
@ -457,14 +458,13 @@ void spi_dup_send_receive_data_dma(dmac_channel_number_t dma_send_channel_num,
* @param[in] int_pin SPI master starts sending data interrupt.
* @param[in] ready_pin SPI slave ready.
* @param[in] dmac_channel Dmac channel number for block.
* @param[in] data_bit_length Spi data bit length
* @param[in] data SPI slave device data buffer.
* @param[in] len The length of SPI slave device data buffer.
* @param[in] data SPI slave buffer desc.
* @param[in] len The number of SPI slave buffer desc.
* @param[in] callback Callback of spi slave.
*
* @return Void
*/
void spi_slave_config(uint8_t int_pin, uint8_t ready_pin, dmac_channel_number_t dmac_channel, size_t data_bit_length, uint8_t *data, uint32_t len, spi_slave_receive_callback_t callback);
void spi_slave_config(uint8_t int_pin, uint8_t ready_pin, dmac_channel_number_t dmac_channel, spi_slave_buffer_desc_t *data, uint8_t len, spi_slave_receive_callback_t callback);
/**
* @brief Spi handle transfer data operations

View File

@ -660,29 +660,36 @@ void spi_receive_data_normal_dma(dmac_channel_number_t dma_send_channel_num,
{
configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2);
if(cmd_len == 0)
spi_set_tmod(spi_num, SPI_TMOD_RECV);
else
if(cmd_len && spi_get_frame_format(spi_num) == SPI_FF_STANDARD)
spi_set_tmod(spi_num, SPI_TMOD_EEROM);
else
spi_set_tmod(spi_num, SPI_TMOD_RECV);
volatile spi_t *spi_handle = spi[spi_num];
spi_handle->ctrlr1 = (uint32_t)(rx_len - 1);
spi_handle->dmacr = 0x3;
spi_handle->ssienr = 0x01;
if(cmd_len)
sysctl_dma_select((sysctl_dma_channel_t)dma_send_channel_num, SYSCTL_DMA_SELECT_SSI0_TX_REQ + spi_num * 2);
sysctl_dma_select((sysctl_dma_channel_t)dma_receive_channel_num, SYSCTL_DMA_SELECT_SSI0_RX_REQ + spi_num * 2);
dmac_set_single_mode(dma_receive_channel_num, (void *)(&spi_handle->dr[0]), rx_buff, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, rx_len);
if(cmd_len)
if(cmd_len && dma_send_channel_num < DMAC_CHANNEL_MAX)
{
sysctl_dma_select((sysctl_dma_channel_t)dma_send_channel_num, SYSCTL_DMA_SELECT_SSI0_TX_REQ + spi_num * 2);
dmac_set_single_mode(dma_send_channel_num, cmd_buff, (void *)(&spi_handle->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, cmd_len);
if(cmd_len == 0 && spi_get_frame_format(spi_num) == SPI_FF_STANDARD)
spi[spi_num]->dr[0] = 0xffffffff;
}
else
{
dma_send_channel_num = DMAC_CHANNEL_MAX;
if(cmd_len == 0)
spi[spi_num]->dr[0] = 0xffffffff;
uint32_t *cmd = (uint32_t *)cmd_buff;
while(cmd_len--)
spi[spi_num]->dr[0] = *cmd++;
}
spi_handle->ser = 1U << chip_select;
if(cmd_len)
if(dma_send_channel_num < DMAC_CHANNEL_MAX)
dmac_wait_done(dma_send_channel_num);
dmac_wait_done(dma_receive_channel_num);
@ -1037,28 +1044,22 @@ void spi_fill_data_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_n
spi_handle->ssienr = 0x00;
}
static int spi_slave_irq(void *ctx)
static int spi_slave_dma_irq(void *ctx)
{
volatile spi_t *spi_handle = spi[2];
spi_handle->imr = 0x00;
*(volatile uint32_t *)((uintptr_t)spi_handle->icr);
if (g_instance.status == IDLE)
g_instance.status = COMMAND;
spi_handle->ssienr = 0x00;
spi_handle->dmacr = 0x00;
dmac->channel[g_instance.dmac_channel].intsignal_en = 0x00;
return 0;
}
static void spi_slave_idle_mode(void)
{
volatile spi_t *spi_handle = spi[2];
uint32_t data_width = g_instance.data_bit_length / 8;
g_instance.status = IDLE;
spi_handle->ssienr = 0x00;
spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x1 << g_instance.slv_oe) | ((g_instance.data_bit_length - 1) << g_instance.dfs);
spi_handle->rxftlr = 0x08 / data_width - 1;
spi_handle->ctrlr0 = 0x001F0600;
spi_handle->dmacr = 0x00;
spi_handle->imr = 0x10;
spi_handle->ssienr = 0x01;
gpiohs_set_pin(g_instance.ready_pin, GPIO_PV_HIGH);
}
@ -1066,287 +1067,145 @@ static void spi_slave_idle_mode(void)
static void spi_slave_command_mode(void)
{
volatile spi_t *spi_handle = spi[2];
uint8_t cmd_data[8], sum = 0;
spi_slave_command_t command;
uint8_t checksum = 0;
spi_transfer_width_t frame_width = spi_get_frame_size(g_instance.data_bit_length - 1);
uint32_t data_width = g_instance.data_bit_length / 8;
spi_device_num_t spi_num = SPI_DEVICE_2;
switch(frame_width)
{
case SPI_TRANS_INT:
for (uint32_t i = 0; i < 8 / 4; i++)
((uint32_t *)cmd_data)[i] = spi_handle->dr[0];
break;
case SPI_TRANS_SHORT:
for (uint32_t i = 0; i < 8 / 2; i++)
((uint16_t *)cmd_data)[i] = spi_handle->dr[0];
break;
default:
for (uint32_t i = 0; i < 8; i++)
cmd_data[i] = spi_handle->dr[0];
break;
}
command.u32[0] = spi_handle->dr[0];
command.u32[1] = spi_handle->dr[0];
for (uint32_t i = 0; i < 7; i++)
{
sum += cmd_data[i];
}
if (cmd_data[7] != sum)
for(int i = 0; i < 7; i++)
checksum += command.u8[i];
if((command.command.cks_err != checksum) || (command.command.index >= g_instance.config_len) ||
((command.command.offset + command.command.length) >= g_instance.config_ptr[command.command.index].length))
{
spi_slave_idle_mode();
return;
}
g_instance.command.cmd = cmd_data[0];
g_instance.command.addr = cmd_data[1] | (cmd_data[2] << 8) | (cmd_data[3] << 16) | (cmd_data[4] << 24);
g_instance.command.len = cmd_data[5] | (cmd_data[6] << 8);
if (g_instance.command.len == 0)
g_instance.command.len = 65536;
if ((g_instance.command.cmd < WRITE_DATA_BLOCK) && (g_instance.command.len > 8))
{
spi_slave_idle_mode();
return;
}
g_instance.status = TRANSFER;
spi_handle->ssienr = 0x00;
if (g_instance.command.cmd == WRITE_CONFIG)
dmac->channel[g_instance.dmac_channel].block_ts = command.command.length;
dmac->channel[g_instance.dmac_channel].intstatus_en = 0xFFFFFFFF;
dmac->channel[g_instance.dmac_channel].intclear = 0xFFFFFFFF;
if(command.command.rw == SPI_SLAVE_BUFFER_WRITE)
{
spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x1 << g_instance.slv_oe) | ((g_instance.data_bit_length - 1) << g_instance.dfs);
spi[2]->rxftlr = g_instance.command.len / data_width - 1;
spi_handle->imr = 0x00;
spi_handle->ssienr = 0x01;
}
else if (g_instance.command.cmd == READ_CONFIG)
{
spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x0 << g_instance.slv_oe) | ((g_instance.data_bit_length - 1) << g_instance.dfs);
spi_set_tmod(2, SPI_TMOD_TRANS);
spi_handle->txftlr = 0x00;
spi_handle->imr = 0x00;
spi_handle->ssienr = 0x01;
switch(frame_width)
{
case SPI_TRANS_INT:
for (uint32_t i = 0; i < g_instance.command.len / 4; i++)
{
spi_handle->dr[0] = ((uint32_t *)&g_instance.config_ptr[g_instance.command.addr])[i];
}
break;
case SPI_TRANS_SHORT:
for (uint32_t i = 0; i < g_instance.command.len / 2; i++)
{
spi_handle->dr[0] = ((uint16_t *)&g_instance.config_ptr[g_instance.command.addr])[i];
}
break;
default:
for (uint32_t i = 0; i < g_instance.command.len; i++)
{
spi_handle->dr[0] = ((uint8_t *)&g_instance.config_ptr[g_instance.command.addr])[i];
}
break;
}
}
else if (g_instance.command.cmd == WRITE_DATA_BYTE)
{
spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x1 << g_instance.slv_oe) | ((g_instance.data_bit_length - 1) << g_instance.dfs);
spi[2]->rxftlr = g_instance.command.len / data_width - 1;
spi_handle->imr = 0x00;
spi_handle->ssienr = 0x01;
}
else if (g_instance.command.cmd == READ_DATA_BYTE)
{
spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x0 << g_instance.slv_oe) | ((g_instance.data_bit_length - 1) << g_instance.dfs);
spi_set_tmod(2, SPI_TMOD_TRANS);
spi_handle->txftlr = 0x00;
spi_handle->imr = 0x00;
spi_handle->ssienr = 0x01;
switch(frame_width)
{
case SPI_TRANS_INT:
for (uint32_t i = 0; i < g_instance.command.len / 4; i++)
{
spi_handle->dr[0] = ((uint32_t *)(uintptr_t)g_instance.command.addr)[i];
}
break;
case SPI_TRANS_SHORT:
for (uint32_t i = 0; i < g_instance.command.len / 2; i++)
{
spi_handle->dr[0] = ((uint16_t *)(uintptr_t)g_instance.command.addr)[i];
}
break;
default:
for (uint32_t i = 0; i < g_instance.command.len; i++)
{
spi_handle->dr[0] = ((uint8_t *)(uintptr_t)g_instance.command.addr)[i];
}
break;
}
}
else if (g_instance.command.cmd == WRITE_DATA_BLOCK)
{
spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x1 << g_instance.slv_oe) | ((32 - 1) << g_instance.dfs);
sysctl_dma_select(g_instance.dmac_channel, SYSCTL_DMA_SELECT_SSI2_RX_REQ);
dmac->channel[g_instance.dmac_channel].sar = (uint64_t)(&spi_handle->dr[0]);
dmac->channel[g_instance.dmac_channel].dar = (uint64_t)(g_instance.config_ptr[command.command.index].address + command.command.offset);
dmac->channel[g_instance.dmac_channel].ctl = (((uint64_t)1 << 47) | ((uint64_t)3 << 48) | ((uint64_t)1 << 38) | ((uint64_t)3 << 39) | ((uint64_t)1 << 18) | ((uint64_t)1 << 14) | ((uint64_t)2 << 11) | ((uint64_t)2 << 8) | ((uint64_t)1 << 4));
dmac->channel[g_instance.dmac_channel].cfg = (((uint64_t)1 << 49) | ((uint64_t)g_instance.dmac_channel << 39) | ((uint64_t)2 << 32));
dmac->channel[g_instance.dmac_channel].intsignal_en = 0x02;
plic_set_priority(IRQN_DMA0_INTERRUPT + g_instance.dmac_channel, 7);
plic_irq_register(IRQN_DMA0_INTERRUPT + g_instance.dmac_channel, spi_slave_dma_irq, &g_instance);
plic_irq_enable(IRQN_DMA0_INTERRUPT + g_instance.dmac_channel);
spi_handle->ctrlr0 = 0x001F0600;
spi_handle->dmacr = 0x01;
spi_handle->imr = 0x00;
spi_handle->ssienr = 0x01;
sysctl_dma_select(g_instance.dmac_channel, SYSCTL_DMA_SELECT_SSI0_RX_REQ + spi_num * 2);
dmac_set_single_mode(g_instance.dmac_channel, (void *)(&spi_handle->dr[0]), (void *)((uintptr_t)g_instance.command.addr & 0xFFFFFFF0), DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, g_instance.command.len * 4);
}
else if (g_instance.command.cmd == READ_DATA_BLOCK)
{
spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x0 << g_instance.slv_oe) | ((32 - 1) << g_instance.dfs);
spi_set_tmod(2, SPI_TMOD_TRANS);
spi_handle->dmacr = 0x02;
spi_handle->imr = 0x00;
spi_handle->ssienr = 0x01;
sysctl_dma_select(g_instance.dmac_channel, SYSCTL_DMA_SELECT_SSI0_TX_REQ + spi_num * 2);
dmac_set_single_mode(g_instance.dmac_channel, (void *)((uintptr_t)g_instance.command.addr & 0xFFFFFFF0), (void *)(&spi_handle->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, g_instance.command.len * 4);
}
else
{
spi_slave_idle_mode();
return;
sysctl_dma_select(g_instance.dmac_channel, SYSCTL_DMA_SELECT_SSI2_TX_REQ);
dmac->channel[g_instance.dmac_channel].sar = (uint64_t)(g_instance.config_ptr[command.command.index].address + command.command.offset);
dmac->channel[g_instance.dmac_channel].dar = (uint64_t)(&spi_handle->dr[0]);
dmac->channel[g_instance.dmac_channel].ctl = (((uint64_t)1 << 47) | ((uint64_t)3 << 48) | ((uint64_t)1 << 38) | ((uint64_t)3 << 39) | ((uint64_t)1 << 18) | ((uint64_t)1 << 14) | ((uint64_t)2 << 11) | ((uint64_t)2 << 8) | ((uint64_t)1 << 6));
dmac->channel[g_instance.dmac_channel].cfg = (((uint64_t)1 << 49) | ((uint64_t)g_instance.dmac_channel << 44) | ((uint64_t)1 << 32));
dmac->channel[g_instance.dmac_channel].intsignal_en = 0x00;
spi_handle->ctrlr0 = 0x001F0100;
spi_handle->dmacr = 0x02;
}
dmac->chen = 0x0101 << g_instance.dmac_channel;
spi_handle->ssienr = 0x01;
g_instance.command = command;
g_instance.status = TRANSFER;
gpiohs_set_pin(g_instance.ready_pin, GPIO_PV_LOW);
}
static void spi_slave_transfer_mode(void)
{
spi_transfer_width_t frame_width = spi_get_frame_size(g_instance.data_bit_length - 1);
uint32_t command_len = 0;
switch(frame_width)
{
case SPI_TRANS_INT:
command_len = g_instance.command.len / 4;
break;
case SPI_TRANS_SHORT:
command_len = g_instance.command.len / 2;
break;
default:
command_len = g_instance.command.len;
break;
}
volatile spi_t *spi_handle = spi[2];
g_instance.command.err = 0;
if (g_instance.command.cmd == WRITE_CONFIG || g_instance.command.cmd == WRITE_DATA_BYTE)
spi_slave_command_t command;
uint32_t intstatus = dmac->channel[g_instance.dmac_channel].intstatus;
command = g_instance.command;
g_instance.command.command.cks_err = 0;
if(command.command.rw == SPI_SLAVE_BUFFER_WRITE)
{
if (spi_handle->rxflr < command_len - 1)
g_instance.command.err = 1;
}
else if (g_instance.command.cmd == READ_CONFIG || g_instance.command.cmd == READ_DATA_BYTE)
{
if (spi_handle->txflr != 0)
g_instance.command.err = 2;
} else if (g_instance.command.cmd == WRITE_DATA_BLOCK || g_instance.command.cmd == READ_DATA_BLOCK)
{
if (dmac->channel[g_instance.dmac_channel].intstatus != 0x02)
g_instance.command.err = 3;
uint32_t length;
length = (uint32_t)command.command.length + 1;
if(intstatus & 0xFFFFFFE0)
{
g_instance.command.command.cks_err = 3;
}
else if((intstatus & 0x02) == 0)
{
if(length > (((uint32_t)(dmac->channel[g_instance.dmac_channel].dar) - (uint32_t)(g_instance.config_ptr[command.command.index].address + command.command.offset)) / 4 + spi_handle->rxflr))
{
g_instance.command.command.cks_err = 1;
}
else if(length & 0x3)
{
length &= 0x3;
uint32_t *data = (uint32_t *)(dmac->channel[g_instance.dmac_channel].dar);
while(length--)
*data++ = spi_handle->dr[0];
}
}
}
else
{
spi_slave_idle_mode();
return;
}
if (g_instance.command.err == 0)
{
if (g_instance.command.cmd == WRITE_CONFIG)
if(intstatus & 0xFFFFFFE0)
{
switch(frame_width)
{
case SPI_TRANS_INT:
for (uint32_t i = 0; i < command_len; i++)
{
((uint32_t *)&g_instance.config_ptr[g_instance.command.addr])[i] = spi_handle->dr[0];
}
break;
case SPI_TRANS_SHORT:
for (uint32_t i = 0; i < command_len; i++)
{
((uint16_t *)&g_instance.config_ptr[g_instance.command.addr])[i] = spi_handle->dr[0];
}
break;
default:
for (uint32_t i = 0; i < command_len; i++)
{
((uint8_t *)&g_instance.config_ptr[g_instance.command.addr])[i] = spi_handle->dr[0];
}
break;
}
g_instance.command.command.cks_err = 3;
}
else if (g_instance.command.cmd == WRITE_DATA_BYTE)
else if((intstatus & 0x02) == 0)
{
switch(frame_width)
{
case SPI_TRANS_INT:
for (uint32_t i = 0; i < command_len; i++)
{
((uint32_t *)(uintptr_t)g_instance.command.addr)[i] = spi_handle->dr[0];
}
break;
case SPI_TRANS_SHORT:
for (uint32_t i = 0; i < command_len; i++)
{
((uint16_t *)(uintptr_t)g_instance.command.addr)[i] = spi_handle->dr[0];
}
break;
default:
for (uint32_t i = 0; i < command_len; i++)
{
((uint8_t *)(uintptr_t)g_instance.command.addr)[i] = spi_handle->dr[0];
}
break;
}
g_instance.command.command.cks_err = 2;
}
}
spi_handle->ssienr = 0x00;
dmac->chen = 0x0100 << g_instance.dmac_channel;
while(dmac->chen & (1 << g_instance.dmac_channel));
dmac->channel[g_instance.dmac_channel].intsignal_en = 0x00;
plic_irq_disable(IRQN_DMA0_INTERRUPT + g_instance.dmac_channel);
if(g_instance.callback != NULL)
{
g_instance.callback((void *)&g_instance.command);
}
spi_slave_idle_mode();
}
static void spi_slave_cs_irq(void)
{
if (g_instance.status == IDLE)
volatile spi_t *spi_handle = spi[2];
if(g_instance.status == IDLE && spi_handle->rxflr == 2)
g_instance.status = COMMAND;
if(g_instance.status == IDLE)
spi_slave_idle_mode();
else if (g_instance.status == COMMAND)
else if(g_instance.status == COMMAND)
spi_slave_command_mode();
else if (g_instance.status == TRANSFER)
else if(g_instance.status == TRANSFER)
spi_slave_transfer_mode();
}
void spi_slave_config(uint8_t int_pin, uint8_t ready_pin, dmac_channel_number_t dmac_channel, size_t data_bit_length, uint8_t *data, uint32_t len, spi_slave_receive_callback_t callback)
void spi_slave_config(uint8_t int_pin, uint8_t ready_pin, dmac_channel_number_t dmac_channel, spi_slave_buffer_desc_t *data, uint8_t len, spi_slave_receive_callback_t callback)
{
g_instance.status = IDLE;
g_instance.config_ptr = data;
g_instance.config_len = len;
g_instance.work_mode = 6;
g_instance.slv_oe = 10;
g_instance.dfs = 16;
g_instance.data_bit_length = data_bit_length;
g_instance.config_len = len > SPI_SLAVE_BUFFER_NUMBER_MAX ? SPI_SLAVE_BUFFER_NUMBER_MAX : len;
g_instance.ready_pin = ready_pin;
g_instance.int_pin = int_pin;
g_instance.callback = callback;
g_instance.dmac_channel = dmac_channel;
sysctl_reset(SYSCTL_RESET_SPI2);
sysctl_clock_enable(SYSCTL_CLOCK_SPI2);
sysctl_clock_set_threshold(SYSCTL_THRESHOLD_SPI2, 9);
sysctl_clock_set_threshold(SYSCTL_THRESHOLD_SPI2, 0);
uint32_t data_width = data_bit_length / 8;
volatile spi_t *spi_handle = spi[2];
spi_handle->ssienr = 0x00;
spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x1 << g_instance.slv_oe) | ((data_bit_length - 1) << g_instance.dfs);
spi_handle->ctrlr0 = 0x001F0600;
spi_handle->dmatdlr = 0x04;
spi_handle->dmardlr = 0x03;
spi_handle->dmacr = 0x00;
spi_handle->txftlr = 0x00;
spi_handle->rxftlr = 0x08 / data_width - 1;
spi_handle->imr = 0x10;
spi_handle->rxftlr = 0x07;
spi_handle->imr = 0x00;
spi_handle->ssienr = 0x01;
gpiohs_set_drive_mode(g_instance.ready_pin, GPIO_DM_OUTPUT);
@ -1355,10 +1214,6 @@ void spi_slave_config(uint8_t int_pin, uint8_t ready_pin, dmac_channel_number_t
gpiohs_set_drive_mode(g_instance.int_pin, GPIO_DM_INPUT_PULL_UP);
gpiohs_set_pin_edge(g_instance.int_pin, GPIO_PE_RISING);
gpiohs_set_irq(g_instance.int_pin, 3, spi_slave_cs_irq);
plic_set_priority(IRQN_SPI_SLAVE_INTERRUPT, 4);
plic_irq_enable(IRQN_SPI_SLAVE_INTERRUPT);
plic_irq_register(IRQN_SPI_SLAVE_INTERRUPT, spi_slave_irq, NULL);
}
void spi_handle_data_dma(spi_device_num_t spi_num, spi_chip_select_t chip_select, spi_data_t data, plic_interrupt_t *cb)
@ -1411,7 +1266,7 @@ void spi_handle_data_dma(spi_device_num_t spi_num, spi_chip_select_t chip_select
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, data.rx_len);
spi_handle->ser = 1U << chip_select;
if(!cb)
dmac_wait_idle(data.rx_channel);
dmac_wait_done(data.rx_channel);
break;
case SPI_TMOD_TRANS:
spi_set_tmod(spi_num, SPI_TMOD_TRANS);
@ -1433,8 +1288,8 @@ void spi_handle_data_dma(spi_device_num_t spi_num, spi_chip_select_t chip_select
spi_handle->ser = 1U << chip_select;
if(!cb)
{
dmac_wait_idle(data.tx_channel);
while ((spi_handle->sr & 0x05) != 0x04)
dmac_wait_done(data.tx_channel);
while((spi_handle->sr & 0x05) != 0x04)
;
}
break;
@ -1462,7 +1317,11 @@ void spi_handle_data_dma(spi_device_num_t spi_num, spi_chip_select_t chip_select
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, data.rx_len);
spi_handle->ser = 1U << chip_select;
if(!cb)
dmac_wait_idle(data.rx_channel);
{
dmac_wait_done(data.tx_channel);
dmac_wait_done(data.rx_channel);
}
break;
case SPI_TMOD_TRANS_RECV:
spi_set_tmod(spi_num, SPI_TMOD_TRANS_RECV);
@ -1498,8 +1357,8 @@ void spi_handle_data_dma(spi_device_num_t spi_num, spi_chip_select_t chip_select
spi_handle->ser = 1U << chip_select;
if(!cb)
{
dmac_wait_idle(data.tx_channel);
dmac_wait_idle(data.rx_channel);
dmac_wait_done(data.tx_channel);
dmac_wait_done(data.rx_channel);
}
break;
}