| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #include <string.h> |
| #include <errno.h> |
| #include <assert.h> |
| #include <os/mynewt.h> |
| #include <mcu/da1469x_pd.h> |
| #include <mcu/da1469x_hal.h> |
| #include <hal/hal_spi.h> |
| #include <mcu/mcu.h> |
| |
| /* The maximum number of SPI interfaces we will allow */ |
| #define DA1469X_HAL_SPI_MAX (2) |
| |
| #if MYNEWT_VAL(SPI_0_MASTER) || MYNEWT_VAL(SPI_1_MASTER) |
| #define SPI_MASTER_CODE 1 |
| #else |
| #define SPI_MASTER_CODE 0 |
| #endif |
| #if MYNEWT_VAL(SPI_0_SLAVE) || MYNEWT_VAL(SPI_1_SLAVE) |
| #defien SPI_SLAVE_CODE 1 |
| #else |
| #define SPI_SLAVE_CODE 0 |
| #endif |
| |
| #if SPI_MASTER_CODE || SPI_SLAVE_CODE |
| |
| struct da1469x_hal_spi_controller { |
| SPI_Type *regs; |
| uint8_t spi_num; |
| uint8_t spi_clk_func; |
| uint8_t spi_do_func; |
| uint8_t spi_di_func; |
| uint8_t spi_ss_func; |
| uint8_t irq_num; |
| void (* irq_handler)(void); |
| }; |
| |
| struct da1469x_hal_spi { |
| uint8_t spi_type; |
| struct hal_spi_settings spi_cfg; /* Slave and master */ |
| |
| /* SPI controller data */ |
| const struct da1469x_hal_spi_controller *hw; |
| |
| const uint8_t *txbuf; /* Pointer to TX buffer */ |
| uint8_t *rxbuf; /* Pointer to RX buffer */ |
| |
| uint16_t len; /* Length of buffer(s) */ |
| uint16_t txlen; /* Number of bytes sent so far */ |
| uint16_t rxlen; /* Number of bytes received so far */ |
| |
| /* Callback and arguments */ |
| hal_spi_txrx_cb txrx_cb_func; |
| void *txrx_cb_arg; |
| }; |
| |
| void SPI_Handler(void); |
| void SPI2_Handler(void); |
| |
| #if MYNEWT_VAL(SPI_0_MASTER) || MYNEWT_VAL(SPI_0_SLAVE) |
| static const struct da1469x_hal_spi_controller hal_spi0_controller = { |
| .regs = (SPI_Type *)SPI, |
| .spi_num = 0, |
| .spi_clk_func = MCU_GPIO_FUNC_SPI_CLK, |
| .spi_do_func = MCU_GPIO_FUNC_SPI_DO, |
| .spi_di_func = MCU_GPIO_FUNC_SPI_DI, |
| .spi_ss_func = MCU_GPIO_FUNC_SPI_EN, |
| .irq_num = SPI_IRQn, |
| .irq_handler = SPI_Handler, |
| }; |
| struct da1469x_hal_spi hal_spi0 = { |
| .hw = &hal_spi0_controller, |
| }; |
| #endif |
| #if MYNEWT_VAL(SPI_1_MASTER) || MYNEWT_VAL(SPI_1_SLAVE) |
| static const struct da1469x_hal_spi_controller hal_spi1_controller = { |
| .regs = (SPI_Type *)SPI2, |
| .spi_num = 1, |
| .spi_clk_func = MCU_GPIO_FUNC_SPI2_CLK, |
| .spi_do_func = MCU_GPIO_FUNC_SPI2_DO, |
| .spi_di_func = MCU_GPIO_FUNC_SPI2_DI, |
| .spi_ss_func = MCU_GPIO_FUNC_SPI2_EN, |
| .irq_num = SPI2_IRQn, |
| .irq_handler = SPI2_Handler, |
| }; |
| struct da1469x_hal_spi hal_spi1 = { |
| .hw = &hal_spi1_controller, |
| }; |
| #endif |
| |
| static struct da1469x_hal_spi *da1469x_hal_spis[DA1469X_HAL_SPI_MAX] = { |
| #if MYNEWT_VAL(SPI_0_MASTER) || MYNEWT_VAL(SPI_0_SLAVE) |
| &hal_spi0, |
| #else |
| NULL, |
| #endif |
| #if MYNEWT_VAL(SPI_1_MASTER) || MYNEWT_VAL(SPI_1_SLAVE) |
| &hal_spi1 |
| #else |
| NULL |
| #endif |
| }; |
| |
| static struct da1469x_hal_spi * |
| hal_spi_resolve(int spi_num) |
| { |
| if (spi_num >= DA1469X_HAL_SPI_MAX) { |
| return NULL; |
| } |
| |
| return da1469x_hal_spis[spi_num]; |
| } |
| |
| static bool |
| da1469x_hal_spi_do_transfer(struct da1469x_hal_spi *spi) |
| { |
| SPI_Type *regs = spi->hw->regs; |
| uint32_t ctrl_reg; |
| |
| while (spi->rxlen < spi->len || spi->txlen < spi->len) { |
| ctrl_reg = regs->SPI_CTRL_REG; |
| if (0 == (ctrl_reg & SPI_SPI_CTRL_REG_SPI_RX_FIFO_EMPTY_Msk)) { |
| if (spi->rxlen < spi->len) { |
| spi->rxbuf[spi->rxlen++] = (uint8_t)regs->SPI_RX_TX_REG; |
| } |
| } else if (0 != (ctrl_reg & SPI_SPI_CTRL_REG_SPI_TXH_Msk)) { |
| if (spi->txlen < spi->len) { |
| regs->SPI_RX_TX_REG = spi->txbuf[spi->txlen++]; |
| } |
| } else { |
| /* Transfer not finished yet, but there is nothing more to send |
| * or TX FIFO is full for now */ |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| static void |
| da1469x_hal_spi_irq_handler(struct da1469x_hal_spi *spi) |
| { |
| SPI_Type *regs = spi->hw->regs; |
| |
| if (!da1469x_hal_spi_do_transfer(spi)) { |
| if (spi->txlen >= spi->len) { |
| /* No need for interrupt from TX fifo */ |
| regs->SPI_CTRL_REG &= ~SPI_SPI_CTRL_REG_SPI_TX_FIFO_NOTFULL_MASK_Msk; |
| } |
| regs->SPI_CLEAR_INT_REG = 1; |
| } else { |
| regs->SPI_CTRL_REG &= ~(SPI_SPI_CTRL_REG_SPI_TX_FIFO_NOTFULL_MASK_Msk | |
| SPI_SPI_CTRL_REG_SPI_MINT_Msk); |
| if (spi->txrx_cb_func) { |
| spi->txrx_cb_func(spi->txrx_cb_arg, spi->len); |
| } |
| } |
| } |
| |
| #if MYNEWT_VAL(SPI_0_MASTER) || MYNEWT_VAL(SPI_0_SLAVE) |
| void |
| SPI_Handler(void) |
| { |
| da1469x_hal_spi_irq_handler(&hal_spi0); |
| } |
| #endif |
| |
| #if MYNEWT_VAL(SPI_1_MASTER) || MYNEWT_VAL(SPI_1_SLAVE) |
| void |
| SPI2_Handler(void) |
| { |
| da1469x_hal_spi_irq_handler(&hal_spi1); |
| } |
| #endif |
| |
| static int |
| hal_spi_init_master(const struct da1469x_hal_spi *spi, |
| const struct da1469x_hal_spi_cfg *cfg) |
| { |
| int irq_num = spi->hw->irq_num; |
| |
| /* Configure pins */ |
| mcu_gpio_set_pin_function(cfg->pin_sck, MCU_GPIO_MODE_OUTPUT, |
| spi->hw->spi_clk_func); |
| if (cfg->pin_do >= 0) { |
| mcu_gpio_set_pin_function(cfg->pin_do, MCU_GPIO_MODE_OUTPUT, |
| spi->hw->spi_do_func); |
| } |
| if (cfg->pin_di >= 0) { |
| mcu_gpio_set_pin_function(cfg->pin_di, MCU_GPIO_MODE_INPUT, |
| spi->hw->spi_di_func); |
| } |
| |
| spi->hw->regs->SPI_CLEAR_INT_REG = 0; |
| spi->hw->regs->SPI_CTRL_REG = 0; |
| |
| if (spi->hw->spi_num == 0 && MYNEWT_VAL(SPI_0_MASTER)) { |
| CRG_COM->RESET_CLK_COM_REG = CRG_COM_RESET_CLK_COM_REG_SPI_CLK_SEL_Msk; |
| CRG_COM->SET_CLK_COM_REG = CRG_COM_RESET_CLK_COM_REG_SPI_ENABLE_Msk; |
| } else if (spi->hw->spi_num == 1 && MYNEWT_VAL(SPI_1_MASTER)) { |
| CRG_COM->RESET_CLK_COM_REG = CRG_COM_RESET_CLK_COM_REG_SPI2_CLK_SEL_Msk; |
| CRG_COM->SET_CLK_COM_REG = CRG_COM_RESET_CLK_COM_REG_SPI2_ENABLE_Msk; |
| } |
| |
| NVIC_SetVector(irq_num, (uint32_t)spi->hw->irq_handler); |
| NVIC_SetPriority(irq_num, (1 << __NVIC_PRIO_BITS) - 1); |
| NVIC_ClearPendingIRQ(irq_num); |
| NVIC_EnableIRQ(irq_num); |
| |
| return 0; |
| } |
| |
| static int |
| hal_spi_init_slave(const struct da1469x_hal_spi *spi, |
| const struct da1469x_hal_spi_cfg *cfg) |
| { |
| return -1; |
| } |
| |
| int |
| hal_spi_init(int spi_num, void *cfg, uint8_t spi_type) |
| { |
| int rc; |
| struct da1469x_hal_spi *spi; |
| |
| if (cfg == NULL) { |
| return SYS_EINVAL; |
| } |
| |
| spi = hal_spi_resolve(spi_num); |
| if (!spi) { |
| return SYS_EINVAL; |
| } |
| |
| if ((spi_type != HAL_SPI_TYPE_MASTER) && (spi_type != HAL_SPI_TYPE_SLAVE)) { |
| return SYS_EINVAL; |
| } |
| |
| da1469x_pd_acquire(MCU_PD_DOMAIN_COM); |
| |
| spi->spi_type = spi_type; |
| |
| rc = hal_spi_disable(spi_num); |
| if (rc) { |
| return rc; |
| } |
| |
| if (spi_type == HAL_SPI_TYPE_MASTER && SPI_MASTER_CODE) { |
| rc = hal_spi_init_master(spi, (struct da1469x_hal_spi_cfg *)cfg); |
| } else if (SPI_SLAVE_CODE) { |
| rc = hal_spi_init_slave(spi, (struct da1469x_hal_spi_cfg *)cfg); |
| } else { |
| rc = SYS_EINVAL; |
| } |
| |
| return rc; |
| } |
| |
| int |
| hal_spi_config(int spi_num, struct hal_spi_settings *settings) |
| { |
| SPI_Type *regs; |
| uint32_t ctrl_reg; |
| struct da1469x_hal_spi *spi; |
| |
| if (settings == NULL) { |
| return SYS_EINVAL; |
| } |
| |
| spi = hal_spi_resolve(spi_num); |
| if (!spi) { |
| return SYS_EINVAL; |
| } |
| regs = spi->hw->regs; |
| |
| regs->SPI_CTRL_REG &= ~SPI_SPI_CTRL_REG_SPI_ON_Msk; |
| regs->SPI_CTRL_REG |= SPI_SPI_CTRL_REG_SPI_RST_Msk; |
| |
| /* Preserve some register fields only */ |
| ctrl_reg = regs->SPI_CTRL_REG & (SPI_SPI_CTRL_REG_SPI_TX_FIFO_NOTFULL_MASK_Msk | |
| SPI_SPI_CTRL_REG_SPI_DMA_TXREQ_MODE_Msk | |
| SPI_SPI_CTRL_REG_SPI_PRIORITY_Msk | |
| SPI_SPI_CTRL_REG_SPI_EN_CTRL_Msk | |
| SPI_SPI_CTRL_REG_SPI_SMN_Msk | |
| SPI_SPI_CTRL_REG_SPI_DO_Msk | |
| SPI_SPI_CTRL_REG_SPI_RST_Msk); |
| |
| assert(settings->data_order == HAL_SPI_MSB_FIRST); |
| |
| switch (settings->baudrate) { |
| case 16000: |
| ctrl_reg |= (2U << SPI_SPI_CTRL_REG_SPI_CLK_Pos); |
| break; |
| case 8000: |
| ctrl_reg |= (1U << SPI_SPI_CTRL_REG_SPI_CLK_Pos); |
| break; |
| case 4000: |
| ctrl_reg |= (0U << SPI_SPI_CTRL_REG_SPI_CLK_Pos); |
| break; |
| default: |
| /* Slowest possibly clock, divider 14, 2.28MHz */ |
| ctrl_reg |= (3U << SPI_SPI_CTRL_REG_SPI_CLK_Pos); |
| break; |
| } |
| |
| switch (settings->data_mode) { |
| case HAL_SPI_MODE0: |
| /* Bits already zeroed */ |
| break; |
| case HAL_SPI_MODE1: |
| ctrl_reg |= (1U << SPI_SPI_CTRL_REG_SPI_PHA_Pos); |
| break; |
| case HAL_SPI_MODE2: |
| ctrl_reg |= (1U << SPI_SPI_CTRL_REG_SPI_POL_Pos); |
| break; |
| case HAL_SPI_MODE3: |
| ctrl_reg |= (1U << SPI_SPI_CTRL_REG_SPI_PHA_Pos) | |
| (1U << SPI_SPI_CTRL_REG_SPI_POL_Pos); |
| break; |
| default: |
| assert(0); |
| break; |
| } |
| if (settings->word_size == HAL_SPI_WORD_SIZE_9BIT) { |
| ctrl_reg |= (1U << SPI_SPI_CTRL_REG_SPI_WORD_Pos); |
| } |
| regs->SPI_CTRL_REG = ctrl_reg; |
| /* At this point interrupt is cleared, FIFO is enabled, controller is disabled */ |
| |
| return 0; |
| } |
| |
| int |
| hal_spi_enable(int spi_num) |
| { |
| SPI_Type *regs; |
| struct da1469x_hal_spi *spi; |
| |
| spi = hal_spi_resolve(spi_num); |
| if (!spi) { |
| return SYS_EINVAL; |
| } |
| regs = spi->hw->regs; |
| |
| if (regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_BUSY_Msk) { |
| return SYS_EBUSY; |
| } |
| |
| regs->SPI_CTRL_REG |= SPI_SPI_CTRL_REG_SPI_ON_Msk; |
| regs->SPI_CTRL_REG &= ~SPI_SPI_CTRL_REG_SPI_RST_Msk; |
| |
| return 0; |
| } |
| |
| int |
| hal_spi_disable(int spi_num) |
| { |
| SPI_Type *regs; |
| struct da1469x_hal_spi *spi; |
| |
| spi = hal_spi_resolve(spi_num); |
| if (!spi) { |
| return SYS_EINVAL; |
| } |
| regs = spi->hw->regs; |
| |
| while (regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_BUSY_Msk) { |
| } |
| |
| regs->SPI_CTRL_REG &= ~(SPI_SPI_CTRL_REG_SPI_ON_Msk | |
| SPI_SPI_CTRL_REG_SPI_INT_BIT_Msk); |
| regs->SPI_CTRL_REG |= SPI_SPI_CTRL_REG_SPI_RST_Msk; |
| |
| return 0; |
| } |
| |
| uint16_t |
| hal_spi_tx_val(int spi_num, uint16_t val) |
| { |
| SPI_Type *regs; |
| struct da1469x_hal_spi *spi; |
| uint16_t dummy; |
| uint32_t ctrl_reg; |
| bool nine_bits = false; |
| |
| spi = hal_spi_resolve(spi_num); |
| if (!spi || spi->spi_type == HAL_SPI_TYPE_SLAVE) { |
| return 0xFFFF; |
| } |
| regs = spi->hw->regs; |
| |
| /* Get rid of old data if any */ |
| while (!(regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_TX_FIFO_EMPTY_Msk)) { |
| } |
| |
| while (!(regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_RX_FIFO_EMPTY_Msk)) { |
| dummy = regs->SPI_RX_TX_REG; |
| (void)dummy; |
| } |
| |
| ctrl_reg = regs->SPI_CTRL_REG; |
| /* 9-bit word */ |
| nine_bits = (ctrl_reg & SPI_SPI_CTRL_REG_SPI_WORD_Msk) == |
| (3U << SPI_SPI_CTRL_REG_SPI_WORD_Pos); |
| if (nine_bits) { |
| ctrl_reg &= ~SPI_SPI_CTRL_REG_SPI_9BIT_VAL_Msk; |
| ctrl_reg |= (val << (SPI_SPI_CTRL_REG_SPI_9BIT_VAL_Pos - 8) ) & |
| SPI_SPI_CTRL_REG_SPI_9BIT_VAL_Msk; |
| } |
| regs->SPI_RX_TX_REG = (uint8_t)val; |
| while (regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_RX_FIFO_EMPTY_Msk) { |
| } |
| |
| ctrl_reg = regs->SPI_CTRL_REG; |
| val = (uint8_t)regs->SPI_RX_TX_REG; |
| if (nine_bits) { |
| val |= (ctrl_reg & SPI_SPI_CTRL_REG_SPI_9BIT_VAL_Msk) >> |
| (SPI_SPI_CTRL_REG_SPI_9BIT_VAL_Pos - 8); |
| } |
| |
| return val; |
| } |
| |
| int |
| hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg) |
| { |
| SPI_Type *regs; |
| struct da1469x_hal_spi *spi; |
| int rc = 0; |
| |
| spi = hal_spi_resolve(spi_num); |
| if (!spi) { |
| rc = SYS_EINVAL; |
| goto err; |
| } |
| regs = spi->hw->regs; |
| |
| |
| if ((regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_ON_Msk) != 0) { |
| rc = SYS_EINVAL; |
| } else { |
| spi->txrx_cb_func = txrx_cb; |
| spi->txrx_cb_arg = arg; |
| } |
| |
| err: |
| return rc; |
| } |
| |
| int |
| hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int len) |
| { |
| SPI_Type *regs; |
| struct da1469x_hal_spi *spi; |
| int rc = 0; |
| const uint8_t *tx; |
| uint8_t *rx; |
| int rxlen = 0; |
| uint8_t val; |
| |
| spi = hal_spi_resolve(spi_num); |
| if (spi == NULL || txbuf == NULL || spi->spi_type != HAL_SPI_TYPE_MASTER) { |
| rc = SYS_EINVAL; |
| goto err; |
| } |
| regs = spi->hw->regs; |
| tx = txbuf; |
| rx = rxbuf; |
| |
| /* Flush RX FIFO */ |
| while (!(regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_RX_FIFO_EMPTY_Msk)) { |
| val = (uint8_t)regs->SPI_RX_TX_REG; |
| } |
| |
| rxlen = len; |
| |
| while (len) { |
| if (0 == (regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_TXH_Msk)) { |
| regs->SPI_RX_TX_REG = *tx++; |
| len--; |
| } |
| if (0 == (regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_RX_FIFO_EMPTY_Msk)) { |
| val = (uint8_t)regs->SPI_RX_TX_REG; |
| if (rx) { |
| *rx++ = val; |
| } |
| rxlen--; |
| } |
| } |
| while (rxlen) { |
| if (0 == (regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_RX_FIFO_EMPTY_Msk)) { |
| val = (uint8_t)regs->SPI_RX_TX_REG; |
| if (rx) { |
| *rx++ = val; |
| } |
| rxlen--; |
| } |
| } |
| err: |
| return rc; |
| } |
| |
| int |
| hal_spi_txrx_noblock(int spi_num, void *txbuf, void *rxbuf, int len) |
| { |
| SPI_Type *regs; |
| struct da1469x_hal_spi *spi; |
| uint32_t ctrl_reg; |
| int rc = 0; |
| |
| spi = hal_spi_resolve(spi_num); |
| if (spi == NULL) { |
| rc = SYS_EINVAL; |
| goto err; |
| } |
| if (SPI_MASTER_CODE && txbuf == NULL && spi->spi_type != HAL_SPI_TYPE_MASTER) { |
| rc = SYS_EINVAL; |
| goto err; |
| } else if (SPI_SLAVE_CODE && txbuf == NULL && rxbuf == NULL && |
| spi->spi_type == HAL_SPI_TYPE_SLAVE) { |
| rc = SYS_EINVAL; |
| goto err; |
| } |
| regs = spi->hw->regs; |
| spi->txbuf = txbuf; |
| spi->rxbuf = rxbuf; |
| spi->len = (uint16_t)len; |
| spi->txlen = 0; |
| spi->rxlen = 0; |
| |
| if (da1469x_hal_spi_do_transfer(spi)) { |
| if (spi->txrx_cb_func) { |
| spi->txrx_cb_func(spi->txrx_cb_arg, spi->len); |
| } |
| } else { |
| ctrl_reg = regs->SPI_CTRL_REG | SPI_SPI_CTRL_REG_SPI_MINT_Msk; |
| if (spi->txlen < spi->len) { |
| ctrl_reg |= SPI_SPI_CTRL_REG_SPI_TX_FIFO_NOTFULL_MASK_Msk; |
| } |
| regs->SPI_CTRL_REG = ctrl_reg; |
| } |
| err: |
| return rc; |
| } |
| |
| int |
| hal_spi_slave_set_def_tx_val(int spi_num, uint16_t val) |
| { |
| return 0; |
| } |
| |
| int |
| hal_spi_abort(int spi_num) |
| { |
| SPI_Type *regs; |
| struct da1469x_hal_spi *spi; |
| int rc = 0; |
| |
| spi = hal_spi_resolve(spi_num); |
| if (spi == NULL) { |
| rc = SYS_EINVAL; |
| goto err; |
| } |
| regs = spi->hw->regs; |
| regs->SPI_CTRL_REG &= ~(SPI_SPI_CTRL_REG_SPI_MINT_Msk | |
| SPI_SPI_CTRL_REG_SPI_TX_FIFO_NOTFULL_MASK_Msk); |
| |
| spi->len = 0; |
| spi->txlen = 0; |
| spi->rxlen = 0; |
| |
| err: |
| return rc; |
| } |
| |
| int |
| hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type, |
| const struct hal_spi_hw_settings *cfg) |
| { |
| struct da1469x_hal_spi_cfg hal_cfg; |
| |
| hal_cfg.pin_sck = (uint8_t)cfg->pin_sck; |
| if (spi_type == HAL_SPI_TYPE_MASTER) { |
| hal_cfg.pin_do = (uint8_t)cfg->pin_mosi; |
| hal_cfg.pin_di = (uint8_t)cfg->pin_miso; |
| } else { |
| hal_cfg.pin_di = (uint8_t)cfg->pin_mosi; |
| hal_cfg.pin_do = (uint8_t)cfg->pin_miso; |
| } |
| hal_cfg.pin_ss = (uint8_t)cfg->pin_ss; |
| |
| return hal_spi_init(spi_num, &hal_cfg, spi_type); |
| } |
| |
| #endif |