• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "hal/spi_slave_hal.h"
16 #include "hal/spi_ll.h"
17 #include "soc/soc_caps.h"
18 
19 //This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
20 #if SOC_GDMA_SUPPORTED
21 #include "soc/gdma_struct.h"
22 #include "hal/gdma_ll.h"
23 
24 #define spi_dma_ll_rx_reset(dev, chan)                             gdma_ll_rx_reset_channel(&GDMA, chan)
25 #define spi_dma_ll_tx_reset(dev, chan)                             gdma_ll_tx_reset_channel(&GDMA, chan);
26 #define spi_dma_ll_rx_start(dev, chan, addr) do {\
27             gdma_ll_rx_set_desc_addr(&GDMA, chan, (uint32_t)addr);\
28             gdma_ll_rx_start(&GDMA, chan);\
29         } while (0)
30 #define spi_dma_ll_tx_start(dev, chan, addr) do {\
31             gdma_ll_tx_set_desc_addr(&GDMA, chan, (uint32_t)addr);\
32             gdma_ll_tx_start(&GDMA, chan);\
33         } while (0)
34 #endif
35 
spi_slave_hal_usr_is_done(spi_slave_hal_context_t * hal)36 bool spi_slave_hal_usr_is_done(spi_slave_hal_context_t* hal)
37 {
38     return spi_ll_usr_is_done(hal->hw);
39 }
40 
spi_slave_hal_user_start(const spi_slave_hal_context_t * hal)41 void spi_slave_hal_user_start(const spi_slave_hal_context_t *hal)
42 {
43     spi_ll_clear_int_stat(hal->hw); //clear int bit
44     spi_ll_slave_user_start(hal->hw);
45 }
46 
spi_slave_hal_prepare_data(const spi_slave_hal_context_t * hal)47 void spi_slave_hal_prepare_data(const spi_slave_hal_context_t *hal)
48 {
49     if (hal->use_dma) {
50 
51         //Fill DMA descriptors
52         if (hal->rx_buffer) {
53             lldesc_setup_link(hal->dmadesc_rx, hal->rx_buffer, ((hal->bitlen + 7) / 8), true);
54 
55             //reset dma inlink, this should be reset before spi related reset
56             spi_dma_ll_rx_reset(hal->dma_in, hal->rx_dma_chan);
57             spi_ll_dma_rx_fifo_reset(hal->dma_in);
58             spi_ll_slave_reset(hal->hw);
59             spi_ll_infifo_full_clr(hal->hw);
60 
61             spi_ll_dma_rx_enable(hal->hw, 1);
62             spi_dma_ll_rx_start(hal->dma_in, hal->rx_dma_chan, &hal->dmadesc_rx[0]);
63         }
64         if (hal->tx_buffer) {
65             lldesc_setup_link(hal->dmadesc_tx, hal->tx_buffer, (hal->bitlen + 7) / 8, false);
66             //reset dma outlink, this should be reset before spi related reset
67             spi_dma_ll_tx_reset(hal->dma_out, hal->tx_dma_chan);
68             spi_ll_dma_tx_fifo_reset(hal->dma_out);
69             spi_ll_slave_reset(hal->hw);
70             spi_ll_outfifo_empty_clr(hal->hw);
71 
72             spi_ll_dma_tx_enable(hal->hw, 1);
73             spi_dma_ll_tx_start(hal->dma_out, hal->tx_dma_chan, (&hal->dmadesc_tx[0]));
74         }
75     } else {
76         //No DMA. Turn off SPI and copy data to transmit buffers.
77         if (hal->tx_buffer) {
78             spi_ll_slave_reset(hal->hw);
79             spi_ll_write_buffer(hal->hw, hal->tx_buffer, hal->bitlen);
80         }
81 
82         spi_ll_cpu_tx_fifo_reset(hal->hw);
83     }
84 
85     spi_ll_slave_set_rx_bitlen(hal->hw, hal->bitlen);
86     spi_ll_slave_set_tx_bitlen(hal->hw, hal->bitlen);
87 
88     spi_ll_enable_mosi(hal->hw, (hal->tx_buffer == NULL) ? 0 : 1);
89     spi_ll_enable_miso(hal->hw, (hal->rx_buffer == NULL) ? 0 : 1);
90 }
91 
spi_slave_hal_store_result(spi_slave_hal_context_t * hal)92 void spi_slave_hal_store_result(spi_slave_hal_context_t *hal)
93 {
94     //when data of cur_trans->length are all sent, the slv_rdata_bit
95     //will be the length sent-1 (i.e. cur_trans->length-1 ), otherwise
96     //the length sent.
97     hal->rcv_bitlen = spi_ll_slave_get_rcv_bitlen(hal->hw);
98     if (hal->rcv_bitlen == hal->bitlen - 1) {
99         hal->rcv_bitlen++;
100     }
101     if (!hal->use_dma && hal->rx_buffer) {
102         //Copy result out
103         spi_ll_read_buffer(hal->hw, hal->rx_buffer, hal->bitlen);
104     }
105 }
106 
spi_slave_hal_get_rcv_bitlen(spi_slave_hal_context_t * hal)107 uint32_t spi_slave_hal_get_rcv_bitlen(spi_slave_hal_context_t *hal)
108 {
109     return hal->rcv_bitlen;
110 }
111 
spi_slave_hal_dma_need_reset(const spi_slave_hal_context_t * hal)112 bool spi_slave_hal_dma_need_reset(const spi_slave_hal_context_t *hal)
113 {
114     bool ret;
115     ret = false;
116     if (hal->use_dma && hal->rx_buffer) {
117         int i;
118         //In case CS goes high too soon, the transfer is aborted while the DMA channel still thinks it's going. This
119         //leads to issues later on, so in that case we need to reset the channel. The state can be detected because
120         //the DMA system doesn't give back the offending descriptor; the owner is still set to DMA.
121         for (i = 0; hal->dmadesc_rx[i].eof == 0 && hal->dmadesc_rx[i].owner == 0; i++) {}
122         if (hal->dmadesc_rx[i].owner) {
123             ret = true;
124         }
125     }
126     return ret;
127 }
128