/** Release a SPI object * * TODO: spi_free is currently unimplemented * This will require reference counting at the C++ level to be safe * * Return the pins owned by the SPI object to their reset state * Disable the SPI peripheral * Disable the SPI clock * @param[in] obj The SPI object to deinitialize */ void spi_free(spi_t *obj) { struct spi_s *spiobj = SPI_S(obj); spi_disable(spiobj->spi); /* Disable and deinit SPI */ if (spiobj->spi == SPI0) { spi_i2s_deinit(SPI0); rcu_periph_clock_disable(RCU_SPI0); } if (spiobj->spi == SPI1) { spi_i2s_deinit(SPI1); rcu_periph_clock_disable(RCU_SPI1); } if (spiobj->spi == SPI2) { spi_i2s_deinit(SPI2); rcu_periph_clock_disable(RCU_SPI2); } /* Deinit GPIO mode of SPI pins */ pin_function(spiobj->pin_miso, MODE_IN_FLOATING); pin_function(spiobj->pin_mosi, MODE_IN_FLOATING); pin_function(spiobj->pin_sclk, MODE_IN_FLOATING); if (spiobj->spi_struct.nss != SPI_NSS_SOFT) { pin_function(spiobj->pin_ssel, MODE_IN_FLOATING); } }
/** Write a value to the SPI peripheral in slave mode * * Blocks until the SPI peripheral can be written to * @param[in] obj The SPI peripheral to write * @param[in] value The value to write */ void spi_slave_write(spi_t *obj, int value) { struct spi_s *spiobj = SPI_S(obj); /* wait the SPI transmit buffer is empty */ while (RESET == spi_i2s_flag_get(spiobj->spi, SPI_FLAG_TBE)); spi_i2s_data_transmit(spiobj->spi, value); }
/** Configure the SPI format * * Set the number of bits per frame, configure clock polarity and phase, shift order and master/slave mode. * The default bit order is MSB. * @param[in,out] obj The SPI object to configure * @param[in] bits The number of bits per frame * @param[in] mode The SPI mode (clock polarity, phase, and shift direction) * @param[in] slave Zero for master mode or non-zero for slave mode */ void spi_format(spi_t *obj, int bits, int mode, int slave) { struct spi_s *spiobj = SPI_S(obj); spiobj->spi_struct.frame_size = (bits == 16) ? SPI_FRAMESIZE_16BIT : SPI_FRAMESIZE_8BIT; /* Config polarity and phase of SPI */ switch (mode) { case 0: spiobj->spi_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; break; case 1: spiobj->spi_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE; break; case 2: spiobj->spi_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_1EDGE; break; default: spiobj->spi_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE; break; } if (spiobj->spi_struct.nss != SPI_NSS_SOFT) { if (slave) { pin_function(spiobj->pin_mosi, MODE_IN_FLOATING); pin_function(spiobj->pin_sclk, MODE_IN_FLOATING); pin_function(spiobj->pin_ssel, MODE_IN_FLOATING); spi_nss_output_disable(spiobj->spi); } } /* Select SPI as master or slave */ spiobj->spi_struct.device_mode = (slave) ? SPI_SLAVE : SPI_MASTER; dev_spi_struct_init(obj); }
/* * Only the frequency is managed in the family specific part * the rest of SPI management is common to all STM32 families */ int spi_get_clock_freq(spi_t *obj) { struct spi_s *spiobj = SPI_S(obj); int spi_hz = 0; /* Get source clock depending on SPI instance */ switch ((int)spiobj->spi) { case SPI_1: #if defined SPI4_BASE case SPI_4: #endif #if defined SPI5_BASE case SPI_5: #endif #if defined SPI6_BASE case SPI_6: #endif /* SPI_1, SPI_4, SPI_5 and SPI_6. Source CLK is PCKL2 */ spi_hz = HAL_RCC_GetPCLK2Freq(); break; case SPI_2: #if defined SPI3_BASE case SPI_3: #endif /* SPI_2 and SPI_3. Source CLK is PCKL1 */ spi_hz = HAL_RCC_GetPCLK1Freq(); break; default: error("CLK: SPI instance not set"); break; } return spi_hz; }
static inline int ssp_busy(spi_t *obj) { int status; struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_BSY) != RESET) ? 1 : 0); return status; }
/** Checks if the specified SPI peripheral is in use * * @param[in] obj The SPI peripheral to check * @return non-zero if the peripheral is currently transmitting */ int spi_busy(spi_t *obj) { int status; struct spi_s *spiobj = SPI_S(obj); /* check whether or not the SPI is busy */ status = ((spi_i2s_flag_get(spiobj->spi, SPI_FLAG_TRANS) != RESET) ? 1 : 0); return status; }
/** Initialize the SPI structure * * Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral * @param[out] obj The SPI object to initialize */ static void dev_spi_struct_init(spi_t *obj) { struct spi_s *spiobj = SPI_S(obj); spi_disable(spiobj->spi); spi_para_init(spiobj->spi, &obj->spi_struct); spi_enable(spiobj->spi); }
/** Check if a value is available to read * * @param[in] obj The SPI peripheral to check * @return non-zero if a value is available */ int spi_slave_receive(spi_t *obj) { int status; struct spi_s *spiobj = SPI_S(obj); /* check whether or not the SPI receive buffer is empty */ status = ((spi_i2s_flag_get(spiobj->spi, SPI_FLAG_RBNE) != RESET) ? 1 : 0); return status; }
static inline int ssp_writeable(spi_t *obj) { int status; struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); // Check if data is transmitted status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_TXE) != RESET) ? 1 : 0); return status; }
static inline int ssp_readable(spi_t *obj) { int status; struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); // Check if data is received status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_RXNE) != RESET) ? 1 : 0); return status; }
/** Initialize the SPI peripheral * * Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral * @param[out] obj The SPI object to initialize * @param[in] mosi The pin to use for MOSI * @param[in] miso The pin to use for MISO * @param[in] sclk The pin to use for SCLK * @param[in] ssel The pin to use for SSEL */ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { struct spi_s *spiobj = SPI_S(obj); SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK); SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL); /* return SPIName according to PinName */ SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel); spiobj->spi = (SPIName)pinmap_merge(spi_data, spi_cntl); MBED_ASSERT(spiobj->spi != (SPIName)NC); /* Set iqr type */ if (spiobj->spi == SPI0) { rcu_periph_clock_enable(RCU_SPI0); spiobj->spi_irq = SPI0_IRQn; } if (spiobj->spi == SPI1) { rcu_periph_clock_enable(RCU_SPI1); spiobj->spi_irq = SPI1_IRQn; } if (spiobj->spi == SPI2) { rcu_periph_clock_enable(RCU_SPI2); spiobj->spi_irq = SPI2_IRQn; } /* config GPIO mode of SPI pins */ pinmap_pinout(mosi, PinMap_SPI_MOSI); pinmap_pinout(miso, PinMap_SPI_MISO); pinmap_pinout(sclk, PinMap_SPI_SCLK); spiobj->pin_miso = miso; spiobj->pin_mosi = mosi; spiobj->pin_sclk = sclk; spiobj->pin_ssel = ssel; if (ssel != NC) { pinmap_pinout(ssel, PinMap_SPI_SSEL); spiobj->spi_struct.nss = SPI_NSS_HARD; spi_nss_output_enable(spiobj->spi); } else { spiobj->spi_struct.nss = SPI_NSS_SOFT; } spiobj->spi_struct.device_mode = SPI_MASTER; spiobj->spi_struct.prescale = SPI_PSC_256; spiobj->spi_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX; spiobj->spi_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; spiobj->spi_struct.frame_size = SPI_FRAMESIZE_8BIT; spiobj->spi_struct.endian = SPI_ENDIAN_MSB; dev_spi_struct_init(obj); }
/** Get a received value out of the SPI receive buffer in slave mode * * Blocks until a value is available * @param[in] obj The SPI peripheral to read * @return The value received */ int spi_slave_read(spi_t *obj) { int count = 0; struct spi_s *spiobj = SPI_S(obj); /* wait the SPI receive buffer is not empty */ while ((RESET == spi_i2s_flag_get(spiobj->spi, SPI_FLAG_RBNE)) && (count++ < 1000)); if (count >= 1000) { return -1; } else { return spi_i2s_data_receive(spiobj->spi); } }
// asynchronous API void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); // TODO: DMA usage is currently ignored (void) hint; // check which use-case we have bool use_tx = (tx != NULL && tx_length > 0); bool use_rx = (rx != NULL && rx_length > 0); bool is16bit = (handle->Init.DataSize == SPI_DATASIZE_16BIT); // don't do anything, if the buffers aren't valid if (!use_tx && !use_rx) return; // copy the buffers to the SPI object obj->tx_buff.buffer = (void *) tx; obj->tx_buff.length = tx_length; obj->tx_buff.pos = 0; obj->tx_buff.width = is16bit ? 16 : 8; obj->rx_buff.buffer = rx; obj->rx_buff.length = rx_length; obj->rx_buff.pos = 0; obj->rx_buff.width = obj->tx_buff.width; obj->spi.event = event; DEBUG_PRINTF("SPI: Transfer: %u, %u\n", tx_length, rx_length); // register the thunking handler IRQn_Type irq_n = spiobj->spiIRQ; NVIC_SetVector(irq_n, (uint32_t)handler); // enable the right hal transfer if (use_tx && use_rx) { // we cannot manage different rx / tx sizes, let's use smaller one size_t size = (tx_length < rx_length)? tx_length : rx_length; if(tx_length != rx_length) { DEBUG_PRINTF("SPI: Full duplex transfer only 1 size: %d\n", size); obj->tx_buff.length = size; obj->rx_buff.length = size; } spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TXRX, tx, rx, size); } else if (use_tx) { spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TX, tx, NULL, tx_length); } else if (use_rx) { spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_RX, NULL, rx, rx_length); } }
/// @returns the number of bytes transferred, or `0` if nothing transferred static int spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfer_type, const void *tx, void *rx, size_t length) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); bool is16bit = (handle->Init.DataSize == SPI_DATASIZE_16BIT); // the HAL expects number of transfers instead of number of bytes // so for 16 bit transfer width the count needs to be halved size_t words; DEBUG_PRINTF("SPI inst=0x%8X Start: %u, %u\r\n", (int)handle->Instance, transfer_type, length); obj->spi.transfer_type = transfer_type; if (is16bit) { words = length / 2; } else { words = length; } // enable the interrupt IRQn_Type irq_n = spiobj->spiIRQ; NVIC_DisableIRQ(irq_n); NVIC_ClearPendingIRQ(irq_n); NVIC_SetPriority(irq_n, 1); NVIC_EnableIRQ(irq_n); // enable the right hal transfer int rc = 0; switch(transfer_type) { case SPI_TRANSFER_TYPE_TXRX: rc = HAL_SPI_TransmitReceive_IT(handle, (uint8_t*)tx, (uint8_t*)rx, words); break; case SPI_TRANSFER_TYPE_TX: rc = HAL_SPI_Transmit_IT(handle, (uint8_t*)tx, words); break; case SPI_TRANSFER_TYPE_RX: // the receive function also "transmits" the receive buffer so in order // to guarantee that 0xff is on the line, we explicitly memset it here memset(rx, SPI_FILL_WORD, length); rc = HAL_SPI_Receive_IT(handle, (uint8_t*)rx, words); break; default: length = 0; } if (rc) { DEBUG_PRINTF("SPI: RC=%u\n", rc); length = 0; } return length; }
void init_spi(spi_t *obj) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); __HAL_SPI_DISABLE(handle); DEBUG_PRINTF("init_spi: instance=0x%8X\r\n", (int)handle->Instance); if (HAL_SPI_Init(handle) != HAL_OK) { error("Cannot initialize SPI"); } __HAL_SPI_ENABLE(handle); }
int spi_slave_read(spi_t *obj) { SPI_TypeDef *spi = SPI_INST(obj); struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); while (!ssp_readable(obj)); if (handle->Init.DataSize == SPI_DATASIZE_8BIT) { // Force 8-bit access to the data register uint8_t *p_spi_dr = 0; p_spi_dr = (uint8_t *) & (spi->DR); return (int)(*p_spi_dr); } else { return (int)spi->DR; } }
void spi_slave_write(spi_t *obj, int value) { SPI_TypeDef *spi = SPI_INST(obj); struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); while (!ssp_writeable(obj)); if (handle->Init.DataSize == SPI_DATASIZE_8BIT) { // Force 8-bit access to the data register uint8_t *p_spi_dr = 0; p_spi_dr = (uint8_t *) & (spi->DR); *p_spi_dr = (uint8_t)value; } else { // SPI_DATASIZE_16BIT spi->DR = (uint16_t)value; } }
uint8_t spi_active(spi_t *obj) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); HAL_SPI_StateTypeDef state = HAL_SPI_GetState(handle); switch(state) { case HAL_SPI_STATE_RESET: case HAL_SPI_STATE_READY: case HAL_SPI_STATE_ERROR: return 0; default: return 1; } }
void spi_abort_asynch(spi_t *obj) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); // disable interrupt IRQn_Type irq_n = spiobj->spiIRQ; NVIC_ClearPendingIRQ(irq_n); NVIC_DisableIRQ(irq_n); // clean-up __HAL_SPI_DISABLE(handle); HAL_SPI_DeInit(handle); HAL_SPI_Init(handle); __HAL_SPI_ENABLE(handle); }
/** Set the SPI baud rate * * Actual frequency may differ from the desired frequency due to available dividers and bus clock * Configures the SPI peripheral's baud rate * @param[in,out] obj The SPI object to configure * @param[in] hz The baud rate in Hz */ void spi_frequency(spi_t *obj, int hz) { struct spi_s *spiobj = SPI_S(obj); int spi_hz = 0; uint8_t prescaler_rank = 0; uint8_t last_index = (sizeof(baudrate_prescaler_table) / sizeof(baudrate_prescaler_table[0])) - 1; spi_hz = dev_spi_clock_source_frequency_get(obj) / 2; /* Config SPI prescaler according to input frequency*/ while ((spi_hz > hz) && (prescaler_rank < last_index)) { spi_hz = spi_hz / 2; prescaler_rank++; } spiobj->spi_struct.prescale = baudrate_prescaler_table[prescaler_rank]; dev_spi_struct_init(obj); }
int spi_master_write(spi_t *obj, int value) { uint16_t size, ret; int Rx = 0; struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); size = (handle->Init.DataSize == SPI_DATASIZE_16BIT) ? 2 : 1; /* Use 10ms timeout */ ret = HAL_SPI_TransmitReceive(handle,(uint8_t*)&value,(uint8_t*)&Rx,size,10); if(ret == HAL_OK) { return Rx; } else { DEBUG_PRINTF("SPI inst=0x%8X ERROR in write\r\n", (int)handle->Instance); return -1; } }
/** Write a byte out in master mode and receive a value * * @param[in] obj The SPI peripheral to use for sending * @param[in] value The value to send * @return Returns the value received during send */ int spi_master_write(spi_t *obj, int value) { int count = 0; struct spi_s *spiobj = SPI_S(obj); /* wait the SPI transmit buffer is empty */ while ((RESET == spi_i2s_flag_get(spiobj->spi, SPI_FLAG_TBE)) && (count++ < 1000)); if (count >= 1000) { return -1; } else { spi_i2s_data_transmit(spiobj->spi, value); } count = 0; /* wait the SPI receive buffer is not empty */ while ((RESET == spi_i2s_flag_get(spiobj->spi, SPI_FLAG_RBNE)) && (count++ < 1000)); if (count >= 1000) { return -1; } else { return spi_i2s_data_receive(spiobj->spi); } }
/* * Only the frequency is managed in the family specific part * the rest of SPI management is common to all STM32 families */ int spi_get_clock_freq(spi_t *obj) { struct spi_s *spiobj = SPI_S(obj); int spi_hz = 0; /* Get source clock depending on SPI instance */ switch ((int)spiobj->spi) { case SPI_1: /* SPI_1. Source CLK is PCKL2 */ spi_hz = HAL_RCC_GetPCLK2Freq(); break; #if defined(SPI2_BASE) case SPI_2: #endif case SPI_3: /* SPI_2, SPI_3. Source CLK is PCKL1 */ spi_hz = HAL_RCC_GetPCLK1Freq(); break; default: error("CLK: SPI instance not set"); break; } return spi_hz; }
void spi_frequency(spi_t *obj, int hz) { struct spi_s *spiobj = SPI_S(obj); int spi_hz = 0; uint8_t prescaler_rank = 0; SPI_HandleTypeDef *handle = &(spiobj->handle); /* Get the clock of the peripheral */ spi_hz = spi_get_clock_freq(obj); /* Define pre-scaler in order to get highest available frequency below requested frequency */ while ((spi_hz > hz) && (prescaler_rank < sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0]))){ spi_hz = spi_hz / 2; prescaler_rank++; } if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) { handle->Init.BaudRatePrescaler = baudrate_prescaler_table[prescaler_rank-1]; } else { error("Couldn't setup requested SPI frequency"); } init_spi(obj); }
void spi_format(spi_t *obj, int bits, int mode, int slave) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); DEBUG_PRINTF("spi_format, bits:%d, mode:%d, slave?:%d\r\n", bits, mode, slave); // Save new values handle->Init.DataSize = (bits == 16) ? SPI_DATASIZE_16BIT : SPI_DATASIZE_8BIT; switch (mode) { case 0: handle->Init.CLKPolarity = SPI_POLARITY_LOW; handle->Init.CLKPhase = SPI_PHASE_1EDGE; break; case 1: handle->Init.CLKPolarity = SPI_POLARITY_LOW; handle->Init.CLKPhase = SPI_PHASE_2EDGE; break; case 2: handle->Init.CLKPolarity = SPI_POLARITY_HIGH; handle->Init.CLKPhase = SPI_PHASE_1EDGE; break; default: handle->Init.CLKPolarity = SPI_POLARITY_HIGH; handle->Init.CLKPhase = SPI_PHASE_2EDGE; break; } if (handle->Init.NSS != SPI_NSS_SOFT) { handle->Init.NSS = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT; } handle->Init.Mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER; init_spi(obj); }
/** Get the frequency of SPI clock source * * Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral * @param[out] spi_freq The SPI clock source freguency * @param[in] obj The SPI object */ static int dev_spi_clock_source_frequency_get(spi_t *obj) { int spi_freq = 0; struct spi_s *spiobj = SPI_S(obj); switch ((int)spiobj->spi) { case SPI0: /* clock source is APB2 */ spi_freq = rcu_clock_freq_get(CK_APB2); break; case SPI1: /* clock source is APB1 */ spi_freq = rcu_clock_freq_get(CK_APB1); break; case SPI2: /* clock source is APB1 */ spi_freq = rcu_clock_freq_get(CK_APB1); break; default: error("SPI clock source frequency get error"); break; } return spi_freq; }
void spi_free(spi_t *obj) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); DEBUG_PRINTF("spi_free\r\n"); __HAL_SPI_DISABLE(handle); HAL_SPI_DeInit(handle); #if defined SPI1_BASE // Reset SPI and disable clock if (spiobj->spi == SPI_1) { __HAL_RCC_SPI1_FORCE_RESET(); __HAL_RCC_SPI1_RELEASE_RESET(); __HAL_RCC_SPI1_CLK_DISABLE(); } #endif #if defined SPI2_BASE if (spiobj->spi == SPI_2) { __HAL_RCC_SPI2_FORCE_RESET(); __HAL_RCC_SPI2_RELEASE_RESET(); __HAL_RCC_SPI2_CLK_DISABLE(); } #endif #if defined SPI3_BASE if (spiobj->spi == SPI_3) { __HAL_RCC_SPI3_FORCE_RESET(); __HAL_RCC_SPI3_RELEASE_RESET(); __HAL_RCC_SPI3_CLK_DISABLE(); } #endif #if defined SPI4_BASE if (spiobj->spi == SPI_4) { __HAL_RCC_SPI4_FORCE_RESET(); __HAL_RCC_SPI4_RELEASE_RESET(); __HAL_RCC_SPI4_CLK_DISABLE(); } #endif #if defined SPI5_BASE if (spiobj->spi == SPI_5) { __HAL_RCC_SPI5_FORCE_RESET(); __HAL_RCC_SPI5_RELEASE_RESET(); __HAL_RCC_SPI5_CLK_DISABLE(); } #endif #if defined SPI6_BASE if (spiobj->spi == SPI_6) { __HAL_RCC_SPI6_FORCE_RESET(); __HAL_RCC_SPI6_RELEASE_RESET(); __HAL_RCC_SPI6_CLK_DISABLE(); } #endif // Configure GPIOs pin_function(spiobj->pin_miso, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); pin_function(spiobj->pin_mosi, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); pin_function(spiobj->pin_sclk, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); if (handle->Init.NSS != SPI_NSS_SOFT) { pin_function(spiobj->pin_ssel, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); } }
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); // Determine the SPI to use SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK); SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL); SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel); spiobj->spi = (SPIName)pinmap_merge(spi_data, spi_cntl); MBED_ASSERT(spiobj->spi != (SPIName)NC); #if defined SPI1_BASE // Enable SPI clock if (spiobj->spi == SPI_1) { __HAL_RCC_SPI1_CLK_ENABLE(); spiobj->spiIRQ = SPI1_IRQn; } #endif #if defined SPI2_BASE if (spiobj->spi == SPI_2) { __HAL_RCC_SPI2_CLK_ENABLE(); spiobj->spiIRQ = SPI2_IRQn; } #endif #if defined SPI3_BASE if (spiobj->spi == SPI_3) { __HAL_RCC_SPI3_CLK_ENABLE(); spiobj->spiIRQ = SPI3_IRQn; } #endif #if defined SPI4_BASE if (spiobj->spi == SPI_4) { __HAL_RCC_SPI4_CLK_ENABLE(); spiobj->spiIRQ = SPI4_IRQn; } #endif #if defined SPI5_BASE if (spiobj->spi == SPI_5) { __HAL_RCC_SPI5_CLK_ENABLE(); spiobj->spiIRQ = SPI5_IRQn; } #endif #if defined SPI6_BASE if (spiobj->spi == SPI_6) { __HAL_RCC_SPI6_CLK_ENABLE(); spiobj->spiIRQ = SPI6_IRQn; } #endif // Configure the SPI pins pinmap_pinout(mosi, PinMap_SPI_MOSI); pinmap_pinout(miso, PinMap_SPI_MISO); pinmap_pinout(sclk, PinMap_SPI_SCLK); spiobj->pin_miso = miso; spiobj->pin_mosi = mosi; spiobj->pin_sclk = sclk; spiobj->pin_ssel = ssel; if (ssel != NC) { pinmap_pinout(ssel, PinMap_SPI_SSEL); } else { handle->Init.NSS = SPI_NSS_SOFT; } /* Fill default value */ handle->Instance = SPI_INST(obj); handle->Init.Mode = SPI_MODE_MASTER; handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; handle->Init.Direction = SPI_DIRECTION_2LINES; handle->Init.CLKPhase = SPI_PHASE_1EDGE; handle->Init.CLKPolarity = SPI_POLARITY_LOW; handle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; handle->Init.CRCPolynomial = 7; handle->Init.DataSize = SPI_DATASIZE_8BIT; handle->Init.FirstBit = SPI_FIRSTBIT_MSB; handle->Init.TIMode = SPI_TIMODE_DISABLED; init_spi(obj); }