From f7cd9b461ca33845339f4a11f49bdc142696827a Mon Sep 17 00:00:00 2001 From: Dominik Sliwa Date: Tue, 28 Jun 2016 09:51:29 +0200 Subject: Apalis_TK1_K20: SPI Communication, ADC, TSC, GPIO Support for Communication between TK1 SoC and K20 MCU This patch includes ADC, TSC and GPIO functionality. Signed-off-by: Dominik Sliwa --- source/com_task.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 source/com_task.c (limited to 'source/com_task.c') diff --git a/source/com_task.c b/source/com_task.c new file mode 100644 index 0000000..348c3e1 --- /dev/null +++ b/source/com_task.c @@ -0,0 +1,205 @@ + +#include "com_task.h" +#include "gpio_ext.h" +#include "adc_task.h" + +/* Put FW version at known address in binary. Make it 32-bit to have room for the future*/ +const uint32_t __attribute__((section(".FwVersion"))) fw_version = APALIS_TK1_K20_FW_VER; + +#define MAX_TRANSFER_SIZE 32U +static dspi_slave_handle_t spi_handle; +static uint8_t slaveRxData[MAX_TRANSFER_SIZE] = {0U}; +static uint8_t slaveTxData[MAX_TRANSFER_SIZE] = {0U}; + +void generate_irq(uint8_t irq) { + gen_regs.irq = gen_regs.irq | BIT(irq); + /* Toggle INT1 pin */ + GPIO_TogglePinsOutput(GPIOA, 1u << 16u); +} + +void clear_irq_flag(uint8_t irq) { + gen_regs.irq = ~irq & gen_regs.irq; +} + +uint8_t get_control_reg() +{ + return gen_regs.control; + +} + +void set_control_reg(uint8_t value) +{ + gen_regs.control = value; +} + +uint8_t get_status_reg() +{ + return gen_regs.status; + +} + +void set_status_reg(uint8_t value) +{ + gen_regs.status = value; +} + +uint8_t get_mask_reg() +{ + return gen_regs.irq_mask; + +} + +void set_mask_reg(uint8_t value) +{ + gen_regs.irq_mask = value; +} + +uint8_t get_irq_reg() +{ + return gen_regs.irq; + +} + +void set_irq_reg(uint8_t value) +{ + /* Clear IRQ flag on 1 */ + clear_irq_flag(value); + +} + +int inline general_registers(uint8_t *rx_buf, uint8_t * tx_buf) { + + if (rx_buf[0] == APALIS_TK1_K20_READ_INST) { + switch (rx_buf[1]) { + case APALIS_TK1_K20_STAREG: + tx_buf[0] = get_status_reg(); + return 1; + case APALIS_TK1_K20_REVREG: + tx_buf[0] = APALIS_TK1_K20_FW_VER; + return 1; + case APALIS_TK1_K20_IRQREG: + tx_buf[0] = get_irq_reg(); + return 1; + case APALIS_TK1_K20_CTRREG: + tx_buf[0] = get_control_reg(); + return 1; + case APALIS_TK1_K20_MSQREG: + tx_buf[0] = get_mask_reg(); + return 1; + default: + return -ENOENT; + } + } else if (rx_buf[0] == APALIS_TK1_K20_WRITE_INST) { + switch (rx_buf[1]) { + case APALIS_TK1_K20_STAREG: + set_status_reg(rx_buf[2]); + return 0; + case APALIS_TK1_K20_REVREG: + return -ENOENT; + case APALIS_TK1_K20_IRQREG: + set_irq_reg(rx_buf[2]); + return 0; + case APALIS_TK1_K20_CTRREG: + set_control_reg(rx_buf[2]); + return 0; + case APALIS_TK1_K20_MSQREG: + set_mask_reg(rx_buf[2]); + return 0; + default: + return -ENOENT; + } + } + + + return -ENOENT; +} + +static void SPI_callback(SPI_Type *base, dspi_slave_handle_t *handle, status_t status, void *userData) +{ + callback_message_t * cb = (callback_message_t*) userData; + BaseType_t reschedule = pdFALSE; + + if (status == kStatus_Success) + { + xSemaphoreGiveFromISR(cb->sem, &reschedule); + } + + if (status == kStatus_DSPI_Error) + { + __NOP(); + } + portYIELD_FROM_ISR(reschedule); +} + +static void SPI_init() { + dspi_slave_config_t slaveConfig; + /* Slave config */ + slaveConfig.whichCtar = kDSPI_Ctar0; + slaveConfig.ctarConfig.bitsPerFrame = 8; + slaveConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + slaveConfig.ctarConfig.cpha = kDSPI_ClockPhaseSecondEdge; + slaveConfig.enableContinuousSCK = true; + slaveConfig.enableRxFifoOverWrite = false; + slaveConfig.enableModifiedTimingFormat = false; + slaveConfig.samplePoint = kDSPI_SckToSin0Clock; + + DSPI_SlaveInit(SPI2, &slaveConfig); + DSPI_SlaveTransferCreateHandle(SPI2, &spi_handle, SPI_callback, spi_handle.userData); + + /* Set dspi slave interrupt priority higher. */ + NVIC_SetPriority(SPI2_IRQn, 5U); + GPIO_ClearPinsOutput(GPIOA, 1u << 29u); /* INT2 active */ + PRINTF("SPI init done \r\n"); + +} + +void spi_task(void *pvParameters) { + callback_message_t cb_msg; + dspi_transfer_t slaveXfer; + int ret; + + cb_msg.sem = xSemaphoreCreateBinary(); + spi_handle.userData = &cb_msg; + SPI_init(); + GPIO_SetPinsOutput(GPIOA, 1u << 29u); /* INT2 idle */ + + while(1){ + slaveXfer.txData = slaveTxData; + slaveXfer.rxData = slaveRxData; + slaveXfer.dataSize = 3; + slaveXfer.configFlags = kDSPI_SlaveCtar0; + /* Wait for instructions from SoC */ + DSPI_SlaveTransferNonBlocking(SPI2, &spi_handle, &slaveXfer); + xSemaphoreTake(cb_msg.sem, portMAX_DELAY); + if (slaveRxData[1] <= 0x05) { + ret = general_registers(slaveRxData, &slaveTxData[1]); +#ifdef BOARD_USES_ADC + } else if ((slaveRxData[1] >= APALIS_TK1_K20_ADCREG) && (slaveRxData[1] <= APALIS_TK1_K20_ADC_CH3H)) { + ret = adc_registers(slaveRxData, &slaveTxData[1]); + + } else if ((slaveRxData[1] >= APALIS_TK1_K20_TSCREG) && (slaveRxData[1] <= APALIS_TK1_K20_TSC_YPH)) { + ret = tsc_registers(slaveRxData, &slaveTxData[1]); +#endif + } else if ((slaveRxData[1] >= APALIS_TK1_K20_GPIOREG) && (slaveRxData[1] <= APALIS_TK1_K20_GPIO_STA)) { + ret = gpio_registers(slaveRxData, &slaveTxData[1]); + + } else { + /* Register not defined */ + ret = -EINVAL; + } + + if (ret < 0) { + slaveTxData[0] = TK1_K20_INVAL; + slaveTxData[1] = TK1_K20_INVAL; + } else { + slaveTxData[0] = TK1_K20_SENTINEL; + } + + if (slaveRxData[0] == APALIS_TK1_K20_READ_INST || slaveRxData[0] == APALIS_TK1_K20_BULK_READ_INST) + { + slaveXfer.dataSize = (ret >= 0) ? (ret + 1):2; /* Extra byte is for sentinel */ + DSPI_SlaveTransferNonBlocking(SPI2, &spi_handle, &slaveXfer); + xSemaphoreTake(cb_msg.sem, portMAX_DELAY); + } + } +} -- cgit v1.2.3