17 #include "../../../hw-libs/misc/rtos.h" 19 #define SPI_INS_BAUDRATE 10000000UL 22 #define SPI_INS_BASE SPI0 23 #define SPI_INS_CHIP_SEL 2 24 #define SPI_spiTouINS_Handler SPI0_Handler 25 #define SPI_IRQn SPI0_IRQn 26 #define SPI_XDMAC_TX_CH_NUM 1 27 #define SPI_XDMAC_RX_CH_NUM 2 30 #define SPI_INS_CLK_POLARITY 1 31 #define SPI_INS_CLK_PHASE 0 34 #define SPI_DLYBS 0x10 37 #define SPI_DLYBCT 0x03 39 #define TX_BUFFER_SIZE 512 40 #define RX_BUFFER_SIZE 2048 //Needs to be a power of 2 (2^x) 41 #define RX_INT_BUFFER_SIZE 1024 //Needs to be a power of 2 (2^x) 44 #define READ_ADDITIONAL_SIZE 20 50 static volatile uint32_t rxfptr = 0, rxbptr = 0, rxintptr = 0;
51 static volatile uint8_t *txfptr = TxBuf;
54 volatile uint32_t lld_fptr;
55 volatile uint32_t lld_bptr;
58 #define DMA_LLD_COUNT 32 //Must be 2^x in size 59 #define DMA_LLD_MASK (DMA_LLD_COUNT - 1) 61 COMPILER_WORD_ALIGNED
volatile lld_view0 rx_lld;
66 #define TASK_SPI_TO_UINS_STACK_SIZE (512/sizeof(portSTACK_TYPE)) 67 #define TASK_SPI_TO_UINS_PRIORITY (configMAX_PRIORITIES - 2) // We want this to be the highest priority - Only timer task higher 68 #define TASK_SPI_TO_UINS_PERIOD_MS 1 78 if(lld_bptr != lld_fptr)
117 static volatile bool inDataPacket =
false;
119 uint32_t spi_statusReg;
164 static volatile bool inDataPacket =
false;
183 if (curDmaAddr < rxintptr)
184 bytesReady = RX_INT_BUFFER_SIZE - rxintptr + curDmaAddr;
186 bytesReady = curDmaAddr - rxintptr;
188 for(uint32_t i=0; i<bytesReady; i++)
193 RxBuf[rxfptr] = RxBufInternal[rxintptr];
196 if(0xFE == RxBufInternal[rxintptr])
198 inDataPacket =
false;
202 rxfptr = (rxfptr + 1) & (RX_BUFFER_SIZE - 1);
207 if(0xFF == RxBufInternal[rxintptr])
212 RxBuf[rxfptr] = RxBufInternal[rxintptr];
213 rxfptr = (rxfptr + 1) & (RX_BUFFER_SIZE - 1);
218 rxintptr = (rxintptr + 1) & (RX_INT_BUFFER_SIZE - 1);
254 cfg.
mbr_da = (uint32_t)RxBufInternal;
269 rx_lld.mbr_ta = (uint32_t)RxBufInternal;
270 rx_lld.mbr_nda = (uint32_t)&rx_lld;
292 cfg.
mbr_sa = (uint32_t)TxBuf;
343 lld[lld_fptr].mbr_ta = (uint32_t)TxBlank;
355 if(lld_bptr != lld_fptr)
387 if (txfptr < curDmaAddr)
388 return (
int)(curDmaAddr - txfptr);
390 return TX_BUFFER_SIZE - (int)(txfptr - curDmaAddr);
395 if (size <= 0)
return 0;
408 if (size > dmaFreeBytes || ((lld_fptr + 1) &
DMA_LLD_MASK) == lld_bptr )
417 if (size <= bytesToEnd)
424 lld[lld_fptr].mbr_ta = (uint32_t)txfptr;
436 int bytesWrapped = size - bytesToEnd;
437 uint32_t bufptr = lld_fptr;
448 lld[bufptr].mbr_ta = (uint32_t)txfptr;
460 lld[bufptr].mbr_ta = (uint32_t)TxBuf;
464 txfptr = TxBuf + bytesWrapped;
479 if(lld_bptr != lld_fptr)
510 int dataAvail = rxfptr - rxbptr;
512 return RX_BUFFER_SIZE + dataAvail;
522 int dataAvail = rxfptr - rxbptr;
527 size =
Min(size, RX_BUFFER_SIZE + dataAvail);
528 int bytesToEnd = RX_BUFFER_SIZE - rxbptr;
531 if(size <= bytesToEnd)
533 memcpy(buf, (
const uint8_t*)&RxBuf[rxbptr], size);
537 memcpy(buf, (
const uint8_t*)&RxBuf[rxbptr], bytesToEnd);
538 memcpy(&buf[bytesToEnd], (
const uint8_t*)RxBuf, size - bytesToEnd);
544 size =
Min(size, dataAvail);
547 memcpy(buf, (
const uint8_t*)&RxBuf[rxbptr], size);
551 rxbptr = (rxbptr + size) & (RX_BUFFER_SIZE - 1);
570 for(
int i=2; i<SIZE; i++)
577 int packet_count = 0;
590 int tx_len, rx_len, len;
595 len = 60 + rand() % 30;
596 for(tx_len = 1; tx_len < len; tx_len++)
598 tx_buf[tx_len] = tx_len + seed;
601 tx_buf[tx_len] = 0xFE;
602 rx_buf[tx_len++] = 0;
611 volatile uint32_t j=20000;
623 len =
sprintf(str,
"len %d %d %d\r\n", tx_len, rx_len, packet_count);
628 for(
int i=0;i<tx_len;i++)
630 if(rx_buf[i] != tx_buf[i])
632 len =
sprintf(str,
"byte %d %d ", tx_buf[i], rx_buf[i]);
656 len =
sprintf(str,
"Packets %d, failures %d, rate %.01f kB/s (each direction)\r\n", packet_count, failure, (
float)(total / seconds) / 1000.0);
static void PIO_DataReady_Handler(uint32_t id, uint32_t mask)
static void spi_set_master_mode(Spi *p_spi)
Set SPI to Master mode.
#define INS_DATA_RDY_PIN_ID
void spi_set_clock_phase(Spi *p_spi, uint32_t ul_pcs_ch, uint32_t ul_phase)
Set Data Capture Phase.
#define XDMAC_CC_DSYNC_MEM2PER
(XDMAC_CC) Memory to Peripheral transfer
static void spi_enable(Spi *p_spi)
Enable SPI.
#define MEMCPY_DCACHE_CLEAN(dst, src, size)
#define pdMS_TO_TICKS(xTimeInMs)
#define UNUSED(v)
Marking v as a unused parameter or value.
static void xdmac_channel_set_descriptor_control(Xdmac *xdmac, uint32_t channel_num, uint32_t config)
Set next descriptor's configuration for the relevant channel of given XDMA.
#define SPI_INS_CLK_PHASE
static void ioport_set_pin_level(ioport_pin_t pin, bool level)
Set an IOPORT pin to a specified logical value.
#define SPI_XDMAC_RX_CH_NUM
#define XDMAC_CC_TYPE_PER_TRAN
(XDMAC_CC) Synchronized mode (Peripheral to Memory or Memory to Peripheral Transfer).
bool udi_cdc_is_tx_ready(void)
This function checks if a new character sent is possible The type int is used to support scanf redire...
#define taskEXIT_CRITICAL()
__attribute__((optimize("O0")))
static void sendMoreData(int len)
#define SCB_CLEAN_DCACHE_BY_ADDR_32BYTE_ALIGNED(addr, size)
#define XDMAC_CC_SAM_FIXED_AM
(XDMAC_CC) The address remains unchanged.
#define XDMAC_CNDC_NDVIEW_NDV0
(XDMAC_CNDC) Next Descriptor View 0
#define XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED
(XDMAC_CNDC) Destination parameters are updated when the descriptor is retrieved. ...
int16_t spi_set_baudrate_div(Spi *p_spi, uint32_t ul_pcs_ch, uint8_t uc_baudrate_divider)
Set Serial Clock Baud Rate divider value (SCBR).
#define PIO_IT_HIGH_LEVEL
#define Min(a, b)
Takes the minimal value of a and b.
#define XDMAC
(XDMAC ) Base Address
static void spi_enable_interrupt(Spi *p_spi, uint32_t ul_sources)
Enable SPI interrupts.
static void xdmac_channel_software_flush_request(Xdmac *xdmac, uint32_t channel_num)
Set software flush request on the relevant channel.
size_t count(InputIterator first, InputIterator last, T const &item)
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
Set Interrupt Priority.
static void xdmac_channel_set_descriptor_addr(Xdmac *xdmac, uint32_t channel_num, uint32_t desc_addr, uint8_t ndaif)
Set next descriptor's address & interface for the relevant channel of given XDMA. ...
rtos_task_t task[UINS_RTOS_NUM_TASKS]
void spi_set_bits_per_transfer(Spi *p_spi, uint32_t ul_pcs_ch, uint32_t ul_bits)
Set number of bits per transfer.
#define spi_get_pcs(chip_sel_id)
Generate Peripheral Chip Select Value from Chip Select ID.
#define XDMAC_UBC_NDE_FETCH_EN
void spi_set_clock_polarity(Spi *p_spi, uint32_t ul_pcs_ch, uint32_t ul_polarity)
Set clock default state.
#define XDMAC_CC_MEMSET_NORMAL_MODE
(XDMAC_CC) Memset is not activated
static void spi_disable_interrupt(Spi *p_spi, uint32_t ul_sources)
Disable SPI interrupts.
#define SPI_spiTouINS_Handler
#define XDMAC_UBC_UBLEN(value)
static uint32_t xdmac_channel_get_interrupt_status(Xdmac *xdmac, uint32_t channel_num)
Get interrupt status for the relevant channel of given XDMA.
#define xTaskNotifyFromISR(xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken)
#define SPI_IMR_TDRE
(SPI_IMR) SPI Transmit Data Register Empty Interrupt Mask
#define XDMAC_CC_DAM_FIXED_AM
(XDMAC_CC) The address remains unchanged.
#define TASK_SPI_TO_UINS_PRIORITY
static bool ioport_get_pin_level(ioport_pin_t pin)
Get current value of an IOPORT pin, which has been configured as an input.
static void xdmac_channel_set_source_addr(Xdmac *xdmac, uint32_t channel_num, uint32_t src_addr)
Set source address for the relevant channel of given XDMA.
iram_size_t udi_cdc_write_buf(const void *buf, iram_size_t size)
Writes a RAM buffer on CDC line.
static uint32_t xdmac_channel_get_interrupt_mask(Xdmac *xdmac, uint32_t channel_num)
Get interrupt mask for the relevant channel of given XDMA.
#define XDMAC_CIE_BIE
(XDMAC_CIE) End of Block Interrupt Enable Bit
#define XDMAC_CC_DAM_INCREMENTED_AM
(XDMAC_CC) The addressing mode is incremented (the increment size is set to the data size)...
__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
Disable External Interrupt.
#define XDMAC_CC_SIF_AHB_IF1
(XDMAC_CC) The data is read through the system bus interface 1
static void spi_reset(Spi *p_spi)
Reset SPI and set it to Slave mode.
static void spiTouINS_task(void *pvParameters)
void test_spiTouINS(void)
#define XDMAC_CNDC_NDE_DSCR_FETCH_EN
(XDMAC_CNDC) Descriptor fetch is enabled
BaseType_t xTaskNotifyWait(uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait) PRIVILEGED_FUNCTION
#define INS_DATA_RDY_PIN_IDX
#define TASK_SPI_TO_UINS_PERIOD_MS
static uint32_t sysclk_get_peripheral_hz(void)
Retrieves the current rate in Hz of the peripheral clocks.
int spiTouINS_serWrite(const unsigned char *buf, int size)
static void xdmac_channel_set_microblock_control(Xdmac *xdmac, uint32_t channel_num, uint32_t ublen)
Set microblock length for the relevant channel of given XDMA.
#define TASK_SPI_TO_UINS_STACK_SIZE
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
Enable External Interrupt.
void spi_enable_clock(Spi *p_spi)
Enable SPI clock.
bool udi_cdc_is_rx_ready(void)
This function checks if a character has been received on the CDC line.
iram_size_t udi_cdc_read_no_polling(void *buf, iram_size_t size)
Non polling reads of a up to 'size' data from CDC line.
#define READ_ADDITIONAL_SIZE
#define INS_DATA_RDY_PIN_PIO
void XDMAC_spiTouINS_Handler(void)
void pio_enable_interrupt(Pio *p_pio, const uint32_t ul_mask)
Enable the given interrupt source. The PIO must be configured as an NVIC interrupt source as well...
static void xdmac_channel_disable_interrupt(Xdmac *xdmac, uint32_t channel_num, uint32_t mask)
Disable interrupt with mask on the relevant channel of given XDMA.
static void xdmac_enable_interrupt(Xdmac *xdmac, uint32_t channel_num)
Enables XDMAC global interrupt.
void spiTouINS_init(void)
#define portYIELD_FROM_ISR(x)
void pio_disable_interrupt(Pio *p_pio, const uint32_t ul_mask)
Disable a given interrupt source, with no added side effects.
#define SPI_CSR_BITS_8_BIT
(SPI_CSR[4]) 8 bits for transfer
#define XDMAC_UBC_NDEN_UPDATED
static void xdmac_channel_enable_interrupt(Xdmac *xdmac, uint32_t channel_num, uint32_t mask)
Enable interrupt with mask on the relevant channel of given XDMA.
void xdmac_configure_transfer(Xdmac *xdmac, uint32_t channel_num, xdmac_channel_config_t *cfg)
Configure DMA for a transfer.
#define XDMAC_CC_DIF_AHB_IF1
(XDMAC_CC) The data is written though the system bus interface 1
__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
Clear Pending Interrupt.
#define XDMAC_CC_CSIZE_CHK_1
(XDMAC_CC) 1 data transferred
static uint32_t getTxFree(void)
static void spi_disable_mode_fault_detect(Spi *p_spi)
Disable Mode Fault Detection.
void spi_set_peripheral_chip_select_value(Spi *p_spi, uint32_t ul_value)
Set Peripheral Chip Select (PCS) value.
#define XDMAC_CC_DSYNC_PER2MEM
(XDMAC_CC) Peripheral to Memory transfer
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
uint32_t pio_get_interrupt_status(const Pio *p_pio)
Read and clear PIO interrupt status.
Structure for storing parameters for DMA view0 that can be performed by the DMA Master transfer...
static void spi_write_single(Spi *p_spi, uint8_t data)
Write one byte to an SPI device.
#define SPI_XDMAC_TX_CH_NUM
#define taskENTER_CRITICAL()
void pio_handler_set_priority(Pio *p_pio, IRQn_Type ul_irqn, uint32_t ul_priority)
Initialize PIO interrupt management logic.
#define RX_INT_BUFFER_SIZE
#define XDMAC_CIS_BIS
(XDMAC_CIS) End of Block Interrupt Status Bit
void spi_set_transfer_delay(Spi *p_spi, uint32_t ul_pcs_ch, uint8_t uc_dlybs, uint8_t uc_dlybct)
Configure timing for SPI transfer.
#define XDMAC_CC_PERID(value)
#define RTC_SCCR_SECCLR
(RTC_SCCR) Second Clear
#define XDMAC_CC_SAM_INCREMENTED_AM
(XDMAC_CC) The addressing mode is incremented (the increment size is set to the data size)...
int spiTouINS_dataReady(void)
void vTaskDelay(const TickType_t xTicksToDelay) PRIVILEGED_FUNCTION
Autogenerated API include file for the Atmel Software Framework (ASF)
static void spi_disable(Spi *p_spi)
Disable SPI.
#define RTC_SR_SEC
(RTC_SR) Second Event
#define XDMAC_GS_ST0
(XDMAC_GS) XDMAC Channel 0 Status Bit
int spiTouINS_serRead(unsigned char *buf, int size)
#define SPI_INS_CLK_POLARITY
#define XDMAC_GE_EN0
(XDMAC_GE) XDMAC Channel 0 Enable Bit
#define SPI_SR_TXEMPTY
(SPI_SR) Transmission Registers Empty (cleared by writing SPI_TDR)
#define XDMAC_UBC_NVIEW_NDV0
#define XDMAC_CC_MBSIZE_SINGLE
(XDMAC_CC) The memory burst size is set to one.
#define RTC
(RTC ) Base Address
#define INS_DATA_RDY_PIN_MASK
int createTask(int index, pdTASK_CODE pxTaskCode, const char *const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, portTickType xTimeIncrement)
#define XDMAC_CC_DWIDTH_BYTE
(XDMAC_CC) The data size is set to 8 bits
#define SPI_IER_TDRE
(SPI_IER) SPI Transmit Data Register Empty Interrupt Enable
static void spi_set_lastxfer(Spi *p_spi)
Issue a LASTXFER command. The next transfer is the last transfer and after that CS is de-asserted...
uint32_t pio_handler_set(Pio *p_pio, uint32_t ul_id, uint32_t ul_mask, uint32_t ul_attr, void(*p_handler)(uint32_t, uint32_t))
Set an interrupt handler for the provided pins. The provided handler will be called with the triggeri...