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