| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
-
- #include "board.h"
- #define TDC_SPI_CR2_BSC ((0<<6) | /* RXNEIE, RX not empty interrupt 0:off; 1:on; */ \
- (0<<5) | /* TXEIE, TX empty interrupt 0:off; 1:on; */ \
- (0<<4) | /* HDMATX, hard DMA TX 0:off; 1:on; */ \
- (0<<3) | /* HDMARX, hard DMA RX 0:off; 1:on; */ \
- (0<<2) | /* INT_EN, SPI interrupt 0:off; 1:on; */ \
- (3<<0)) /* 2 RSV bits */
- #define TDC_DMA_CONFA_BSC ((0u<<29) | /* ST, 0:no soft start DMA; 1:soft start DMA */ \
- (0x42u<<22) | /* TRI_SEL, 0x40:SPI0 RX; 0x42:SPI1 RX */ \
- (0u<<16)) /* BC, one trigger require 0:one; 1:two; ... 15:sixteen data(8/16/32 bits per data) */
- uint8_t tdc_spi_rbuf[5];
- // 4-wire SPI (2.5V)
- // fclk <= 15M
- // Pulse width >= 30 ns
- // CPOL = 0 (SCK is low when idle)
- // CPHA = 1 (capture data at falling edge of SCK)
- // assert SSN at least 40ns before SCLK rising
- // deassert SSN at least 40ns after SCLK falling
- // MSB first
- void tdc_spi_init(void)
- {
- // SPI GPIO Configuration
- // PC02 : SPI1_MISO
- GpioInit(PC02_SPI1_MISO, GPIO_DIG_IN_NONEUP_PULLDOWN);
- PeriClk_MutEnable(PeriClk_Spi1);
- M0P_SPI1->CR = (0<<7) | // SPR2
- (0<<6) | // SPEN, 0:off; 1:on;
- (1<<4) | // MSTR, 0:slave; 1:master;
- (0<<3) | // CPOL, when idle 0:SCK is low; 1:SCK is high;
- (1<<2) | // CPHA, 0:1st; 1:2nd; SCK edge sample data
- (0<<0); // [SPR1:SPR0], 0:PCLK/2; 1:PCLK/4;
- M0P_SPI1->CR2 = TDC_SPI_CR2_BSC;
- M0P_SPI1->SSN = 1;
- M0P_SPI1->CR_f.SPEN = 1;
- PeriClk_MutDisable(PeriClk_Spi1);
- // SPI GPIO Configuration
- // PD00 : SPI1_CS
- // PD01 : SPI1_SCK
- // PC03 : SPI1_MOSI
- GpioInit(PD00_SPI1_CS, GPIO_DIG_OUT_STRN_PUSH_NONEUP_NONEDOWN);
- GpioInit(PD01_SPI1_SCK, GPIO_DIG_OUT_STRN_PUSH_NONEUP_NONEDOWN);
- GpioInit(PC03_SPI1_MOSI, GPIO_DIG_OUT_STRN_PUSH_NONEUP_NONEDOWN);
- DMA_ReqClkOn();
- M0P_DMAC->CONF = (1u<<31) | // EN, 0:DMAC off; 1:DMAC on;
- (0u<<28) | // PRIO, 0:priority of CH0 higher than CH1; 1:round-robin between CH0 and CH1;
- (0u<<24); // HALT, 0:not halt; others:halt all CH;
- M0P_DMAC->CONFB0 = (0u<<28) | // MODE, 0:Block; 1:Burst(non interruptible between TC+1 Trigger);
- (0u<<26) | // WIDTH, 0:8 bits; 1:16 bits; 2:32 bits;
- (1u<<25) | // FS, source address 0:inc; 1:fixed;
- (0u<<24) | // FD, destination address 0:inc; 1:fixed;
- (0u<<20) | // ERR_IE, interrupt 0:off; 1:on; when DMA error
- (0u<<19) | // FIS_IE, interrupt 0:off; 1:on; after DMA done
- (0u<<0); // MSK, 0:clear ENS 1:keep ENS; after DMA done
- M0P_DMAC->SRCADR0 = (uint32_t)&(M0P_SPI1->DATA);
- M0P_DMAC->DSTADR0 = (uint32_t)&(tdc_spi_rbuf[0]);
- DMA_ReqClkOff();
- }
- void spi1_wr_byte(uint8_t byte)
- {
- while(M0P_SPI1->STAT_f.TXE==0x0u){
- // loop wait until tx buffer is empty
- }
- M0P_SPI1->DATA = byte;
- }
- uint8_t spi1_rd_byte(void)
- {
- M0P_SPI1->DATA = 0x00u; // write any data
- while(M0P_SPI1->STAT_f.TXE==0x0u){
- // loop wait until tx buffer is empty
- }
- while(M0P_SPI1->STAT_f.BUSY){ // more reliable than RXNE
- // loop wait until not busy
- }
- return(M0P_SPI1->DATA);
- }
- void spi1_wait_busy(void)
- {
- while(M0P_SPI1->STAT_f.BUSY){ // more reliable than RXNE
- // loop wait until not busy
- }
- }
- void tdc_spi_wr_d32(uint8_t code, uint32_t data)
- {
- uint8_t i;
- // assert CSN
- M0P_SPI1->SSN = 0; // 0:SPI_CS low; 1:SPI_CS high
- M0P_SPI1->DATA = code;
- for(i=0;i<4;i++){
- while(M0P_SPI1->STAT_f.TXE==0x0u){
- // loop wait until tx buffer is empty
- }
- M0P_SPI1->DATA = data>>24; // MSB first
- data = data<<8;
- }
- while(M0P_SPI1->STAT_f.TXE==0x0u){
- // loop wait until tx buffer is empty
- }
- while(M0P_SPI1->STAT_f.BUSY){
- // loop wait until not busy
- }
- // deassert CSN and clear RXN(hardwareE)
- M0P_SPI1->SSN = 1; // 0:SPI_CS low; 1:SPI_CS high
- // M0P_SPI1->ICLR = 0x0; // clr RX flag(rising of SSN clear rx flag automatically)
- }
- void tdc_spi_wr_code(uint8_t code)
- {
- // assert CSN
- M0P_SPI1->SSN = 0; // 0:SPI_CS low; 1:SPI_CS high
- M0P_SPI1->DATA = code;
- while(M0P_SPI1->STAT_f.TXE==0x0u){
- // loop wait until tx buffer is empty
- }
- while(M0P_SPI1->STAT_f.BUSY){
- // loop wait until not busy
- }
- // deassert CSN and clear RXNE(hardware)
- M0P_SPI1->SSN = 1; // 0:SPI_CS low; 1:SPI_CS high
- // M0P_SPI1->ICLR = 0x0; // clr RX flag(rising of SSN clear rx flag automatically)
- }
- uint32_t tdc_spi_rd_d32(uint8_t code)
- {
- uint8_t i;
- uint32_t data;
- // assert CSN
- M0P_SPI1->SSN = 0; // 0:SPI_CS low; 1:SPI_CS high
- // enable DMAR of SPI
- M0P_SPI1->CR2 = TDC_SPI_CR2_BSC |
- (1<<3); // HDMARX, hard DMA RX 0:off; 1:on;
- // reload DSTADR because INC
- M0P_DMAC->DSTADR0 = (uint32_t)&(tdc_spi_rbuf[0]);
- // enable DMA channel
- M0P_DMAC->CONFA0 = TDC_DMA_CONFA_BSC |
- (1u<<31) | /* ENS, 0:CHx off; 1:CHx on; */
- ((5-1)<<0); /* TC = Len - 1, close DAM after (TC+1)*(BC+1) */
- M0P_SPI1->DATA = code;
- for(i=0;i<4;i++){
- while(M0P_SPI1->STAT_f.TXE==0x0u){
- // loop wait until tx buffer is empty
- }
- M0P_SPI1->DATA = 0x00;
- // __asm volatile("nop"); // adding "NOP" maybe decrease checking TXFE rounds
- // __asm volatile("nop");
- // __asm volatile("nop");
- }
- while(M0P_DMAC->CONFA0 & (0x1u<<31)){
- // wait until DMA ch0 full done
- }
- // disable DMAR of SPI
- M0P_SPI1->CR2 = TDC_SPI_CR2_BSC;
- data = tdc_spi_rbuf[1];
- data = data<<8;
- data |= tdc_spi_rbuf[2];
- data = data<<8;
- data |= tdc_spi_rbuf[3];
- data = data<<8;
- data |= tdc_spi_rbuf[4];
- // deassert CSN
- M0P_SPI1->SSN = 1; // 0:SPI_CS low; 1:SPI_CS high
- return(data);
- }
- uint16_t tdc_spi_rd_d16(uint8_t code)
- {
- uint8_t i;
- uint16_t data;
- // assert CSN
- M0P_SPI1->SSN = 0; // 0:SPI_CS low; 1:SPI_CS high
- // enable DMAR of SPI
- M0P_SPI1->CR2 = TDC_SPI_CR2_BSC |
- (1<<3); // HDMARX, hard DMA RX 0:off; 1:on;
- // reload DSTADR because INC
- M0P_DMAC->DSTADR0 = (uint32_t)&(tdc_spi_rbuf[0]);
- // enable DMA channel
- M0P_DMAC->CONFA0 = TDC_DMA_CONFA_BSC |
- (1u<<31) | /* ENS, 0:CHx off; 1:CHx on; */
- ((3-1)<<0); /* TC = Len - 1, close DAM after (TC+1)*(BC+1) */
- M0P_SPI1->DATA = code; // more faster, if send one byte before start DMA enable
- for(i=0;i<2;i++){
- while(M0P_SPI1->STAT_f.TXE==0x0u){
- // loop wait until tx buffer is empty
- }
- M0P_SPI1->DATA = 0x00;
- // __asm volatile("nop"); // adding "NOP" maybe decrease checking TXFE rounds
- // __asm volatile("nop");
- // __asm volatile("nop");
- }
- while(M0P_DMAC->CONFA0 & (0x1u<<31)){
- // wait until DMA ch0 full done
- }
- // disable DMAR of SPI
- M0P_SPI1->CR2 = TDC_SPI_CR2_BSC;
- data = tdc_spi_rbuf[1];
- data = data<<8;
- data |= tdc_spi_rbuf[2];
- // deassert CSN
- M0P_SPI1->SSN = 1; // 0:SPI_CS low; 1:SPI_CS high
- return(data);
- }
- //uint16_t tdc_spi_rd_d16(uint8_t code)
- //{
- // uint16_t data;
- //
- // // assert CSN
- // M0P_SPI1->SSN = 0; // 0:SPI_CS low; 1:SPI_CS high
- //
- // M0P_SPI1->DATA = code; // more faster, if send one byte before start DMA enable
- //
- // while(M0P_SPI1->STAT_f.TXE==0x0u){
- // // loop wait until tx buffer is empty
- // }
- // M0P_SPI1->DATA = 0x00;
- //
- // while(M0P_SPI1->STAT_f.TXE==0x0u){
- // // loop wait until tx buffer is empty
- // }
- // while(M0P_SPI1->STAT_f.BUSY){
- // // loop wait until not busy
- // }
- // data = M0P_SPI1->DATA;
- //
- // M0P_SPI1->DATA = 0x00;
- //
- // while(M0P_SPI1->STAT_f.TXE==0x0u){
- // // loop wait until tx buffer is empty
- // }
- // while(M0P_SPI1->STAT_f.BUSY){
- // // loop wait until not busy
- // }
- // data <<= 8;
- // data |= M0P_SPI1->DATA & 0xFF;
- //
- // // deassert CSN
- // M0P_SPI1->SSN = 1; // 0:SPI_CS low; 1:SPI_CS high
- //
- // return(data);
- //}
- uint8_t tdc_spi_rd_d8(uint8_t code)
- {
- uint8_t data;
- // assert CSN
- M0P_SPI1->SSN = 0; // 0:SPI_CS low; 1:SPI_CS high
- M0P_SPI1->DATA = code; // more faster, if send one byte before start DMA enable
- while(M0P_SPI1->STAT_f.TXE==0x0u){
- // loop wait until tx buffer is empty
- }
- M0P_SPI1->DATA = 0x00;
- while(M0P_SPI1->STAT_f.TXE==0x0u){
- // loop wait until tx buffer is empty
- }
- while(M0P_SPI1->STAT_f.BUSY){
- // loop wait until not busy
- }
- data = M0P_SPI1->DATA;
- // deassert CSN
- M0P_SPI1->SSN = 1; // 0:SPI_CS low; 1:SPI_CS high
- return(data);
- }
|