/** * Blocking call to send a value on the SPI. Returns the value received from the * SPI slave. * * MASTER: Sends the value and returns the received value from the slave. * SLAVE: Invalid API. Returns 0xFFFF * * @param spi_num Spi interface to use * @param val Value to send * * @return uint16_t Value received on SPI interface from slave. Returns 0xFFFF * if called when the SPI is configured to be a slave */ uint16_t hal_spi_tx_val(int spi_num, uint16_t val) { int rc; struct stm32_hal_spi *spi; uint16_t retval; int len; int sr; STM32_HAL_SPI_RESOLVE(spi_num, spi); if (spi->slave) { retval = -1; goto err; } if (spi->handle.Init.DataSize == SPI_DATASIZE_8BIT) { len = sizeof(uint8_t); } else { len = sizeof(uint16_t); } __HAL_DISABLE_INTERRUPTS(sr); spi_stat.tx++; rc = HAL_SPI_TransmitReceive(&spi->handle,(uint8_t *)&val, (uint8_t *)&retval, len, STM32_HAL_SPI_TIMEOUT); __HAL_ENABLE_INTERRUPTS(sr); if (rc != HAL_OK) { retval = 0xFFFF; } err: return retval; }
int hal_spi_txrx_noblock(int spi_num, void *txbuf, void *rxbuf, int len) { struct stm32_hal_spi *spi; int rc; int sr; STM32_HAL_SPI_RESOLVE(spi_num, spi); spi_stat.tx++; rc = -1; __HAL_DISABLE_INTERRUPTS(sr); if (!spi->slave) { rc = HAL_SPI_TransmitReceive_IT_Custom(&spi->handle, txbuf, rxbuf, len); } else { /* * Slave: if selected, start transmitting new data. * If not selected, queue it for transmission. */ spi->handle.State = HAL_SPI_STATE_READY; if (spi->selected) { rc = HAL_SPI_TransmitReceive_IT_Custom(&spi->handle, txbuf, rxbuf, len); } else { rc = HAL_SPI_Slave_Queue_TransmitReceive(&spi->handle, txbuf, rxbuf, len); } if (rc == 0) { spi->tx_in_prog = 1; } } __HAL_ENABLE_INTERRUPTS(sr); err: return (rc); }
/** * Blocking interface to send a buffer and store the received values from the * slave. The transmit and receive buffers are either arrays of 8-bit (uint8_t) * values or 16-bit values depending on whether the spi is configured for 8 bit * data or more than 8 bits per value. The 'cnt' parameter is the number of * 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an * array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise * txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values). * * NOTE: these buffers are in the native endian-ness of the platform. * * MASTER: master sends all the values in the buffer and stores the * stores the values in the receive buffer if rxbuf is not NULL. * The txbuf parameter cannot be NULL. * SLAVE: cannot be called for a slave; returns -1 * * @param spi_num SPI interface to use * @param txbuf Pointer to buffer where values to transmit are stored. * @param rxbuf Pointer to buffer to store values received from peer. * @param cnt Number of 8-bit or 16-bit values to be transferred. * * @return int 0 on success, non-zero error code on failure. */ int hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int len) { int rc; struct stm32_hal_spi *spi; int sr; rc = -1; if (!len) { goto err; } STM32_HAL_SPI_RESOLVE(spi_num, spi); if (spi->slave) { goto err; } __HAL_DISABLE_INTERRUPTS(sr); spi_stat.tx++; __HAL_SPI_ENABLE(&spi->handle); rc = HAL_SPI_TransmitReceive(&spi->handle, (uint8_t *)txbuf, (uint8_t *)rxbuf, len, STM32_HAL_SPI_TIMEOUT); __HAL_ENABLE_INTERRUPTS(sr); if (rc != HAL_OK) { rc = -1; goto err; } rc = 0; err: return rc; }
static int nrf52k_flash_erase_sector(uint32_t sector_address) { int sr; int rc = -1; if (nrf52k_flash_wait_ready()) { return -1; } __HAL_DISABLE_INTERRUPTS(sr); NRF_NVMC->CONFIG |= NVMC_CONFIG_WEN_Een; /* Enable erase OP */ if (nrf52k_flash_wait_ready()) { goto out; } NRF_NVMC->ERASEPAGE = sector_address; if (nrf52k_flash_wait_ready()) { goto out; } rc = 0; out: NRF_NVMC->CONFIG &= ~NVMC_CONFIG_WEN_Een; /* Disable erase OP */ __HAL_ENABLE_INTERRUPTS(sr); return rc; }
/** * gpio irq disable * * * @param pin */ void gpio_irq_disable(int pin) { uint32_t ctx; uint32_t mask; mask = GPIO_MASK(pin); __HAL_DISABLE_INTERRUPTS(ctx); EXTI->IMR &= ~mask; __HAL_ENABLE_INTERRUPTS(ctx); }
/** * gpio irq enable * * Enable the irq on the specified pin * * @param pin */ void hal_gpio_irq_enable(int pin) { uint32_t ctx; uint32_t mask; mask = HAL_GPIO_PIN(pin); __HAL_DISABLE_INTERRUPTS(ctx); EXTI->IMR |= mask; __HAL_ENABLE_INTERRUPTS(ctx); }
void hal_uart_start_tx(int port) { struct hal_uart *u; int sr; u = &uarts[port]; __HAL_DISABLE_INTERRUPTS(sr); u->u_regs->CR1 &= ~USART_CR1_TCIE; u->u_regs->CR1 |= USART_CR1_TXEIE; u->u_tx_end = 0; __HAL_ENABLE_INTERRUPTS(sr); }
/** * Sets the txrx callback (executed at interrupt context) when the * buffer is transferred by the master or the slave using the non-blocking API. * Cannot be called when the spi is enabled. This callback will also be called * when chip select is de-asserted on the slave. * * NOTE: This callback is only used for the non-blocking interface and must * be called prior to using the non-blocking API. * * @param spi_num SPI interface on which to set callback * @param txrx Callback function * @param arg Argument to be passed to callback function * * @return int 0 on success, non-zero error code on failure. */ int hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg) { struct stm32_hal_spi *spi; int rc = 0; int sr; STM32_HAL_SPI_RESOLVE(spi_num, spi); __HAL_DISABLE_INTERRUPTS(sr); spi->txrx_cb_func = txrx_cb; spi->txrx_cb_arg = arg; __HAL_ENABLE_INTERRUPTS(sr); err: return rc; }
void os_bsp_systick_init(uint32_t os_ticks_per_sec, int prio) { uint32_t ctx; uint32_t mask; uint32_t pre_scaler; /* Turn on the LFCLK */ NRF_CLOCK->XTALFREQ = CLOCK_XTALFREQ_XTALFREQ_16MHz; NRF_CLOCK->TASKS_LFCLKSTOP = 1; NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; NRF_CLOCK->LFCLKSRC = CLOCK_LFCLKSRC_SRC_Xtal; NRF_CLOCK->TASKS_LFCLKSTART = 1; /* Wait here till started! */ mask = CLOCK_LFCLKSTAT_STATE_Msk | CLOCK_LFCLKSTAT_SRC_Xtal; while (1) { if (NRF_CLOCK->EVENTS_LFCLKSTARTED) { if ((NRF_CLOCK->LFCLKSTAT & mask) == mask) { break; } } } /* Is this exact frequency obtainable? */ pre_scaler = (32768 / os_ticks_per_sec) - 1; /* disable interrupts */ __HAL_DISABLE_INTERRUPTS(ctx); NRF_RTC0->TASKS_STOP = 1; NRF_RTC0->EVENTS_TICK = 0; NRF_RTC0->PRESCALER = pre_scaler; NRF_RTC0->INTENCLR = 0xffffffff; NRF_RTC0->TASKS_CLEAR = 1; /* Set isr in vector table and enable interrupt */ NVIC_SetPriority(RTC0_IRQn, prio); NVIC_SetVector(RTC0_IRQn, (uint32_t)rtc0_timer_handler); NVIC_EnableIRQ(RTC0_IRQn); NRF_RTC0->INTENSET = RTC_INTENSET_TICK_Msk; NRF_RTC0->TASKS_START = 1; __HAL_ENABLE_INTERRUPTS(ctx); }
void hal_uart_start_rx(int port) { struct hal_uart *u; int sr; int rc; u = &uarts[port]; if (u->u_rx_stall) { __HAL_DISABLE_INTERRUPTS(sr); rc = u->u_rx_func(u->u_func_arg, u->u_rx_data); if (rc == 0) { u->u_rx_stall = 0; u->u_regs->CR1 |= USART_CR1_RXNEIE; } __HAL_ENABLE_INTERRUPTS(sr); } }
int hal_spi_abort(int spi_num) { int rc; struct stm32_hal_spi *spi; int sr; rc = 0; STM32_HAL_SPI_RESOLVE(spi_num, spi); if (spi->slave) { goto err; } __HAL_DISABLE_INTERRUPTS(sr); spi->handle.State = HAL_SPI_STATE_READY; __HAL_SPI_DISABLE_IT(&spi->handle, SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR); spi->handle.Instance->CR1 &= ~SPI_CR1_SPE; __HAL_ENABLE_INTERRUPTS(sr); err: return rc; }
uint64_t cputime_get64(void) { uint32_t ctx; uint32_t high; uint32_t low; uint64_t cpu_time; __HAL_DISABLE_INTERRUPTS(ctx); high = g_cputime.cputime_high; low = cputime_get32(); if (CPUTIMER->EVENTS_COMPARE[CPUTIMER_CC_OVERFLOW]) { ++high; low = cputime_get32(); } __HAL_ENABLE_INTERRUPTS(ctx); cpu_time = ((uint64_t)high << 32) | low; return cpu_time; }
/** * Sets the default value transferred by the slave. Not valid for master * * @param spi_num SPI interface to use * * @return int 0 on success, non-zero error code on failure. */ int hal_spi_slave_set_def_tx_val(int spi_num, uint16_t val) { struct stm32_hal_spi *spi; int rc; int sr; int i; STM32_HAL_SPI_RESOLVE(spi_num, spi); if (spi->slave) { rc = 0; __HAL_DISABLE_INTERRUPTS(sr); if (spi->handle.Init.DataSize == SPI_DATASIZE_8BIT) { for (i = 0; i < 4; i++) { ((uint8_t *)spi->def_char)[i] = val; } } else { for (i = 0; i < 2; i++) { ((uint16_t *)spi->def_char)[i] = val; } } if (!spi->tx_in_prog) { /* * Replaces the current default char in tx buffer register. */ spi->handle.State = HAL_SPI_STATE_READY; rc = HAL_SPI_QueueTransmit(&spi->handle, spi->def_char, 2); assert(rc == 0); } __HAL_ENABLE_INTERRUPTS(sr); } else { rc = -1; } err: return rc; }
void os_tick_init(uint32_t os_ticks_per_sec, int prio) { uint32_t ctx; uint32_t prescaler_reg; /* Make os ticks per sec divides evenly into frequency */ timer_ticks_per_ostick = MKW41Z_LPTMR_FREQ / os_ticks_per_sec; assert((timer_ticks_per_ostick * os_ticks_per_sec) == MKW41Z_LPTMR_FREQ); /* disable interrupts */ __HAL_DISABLE_INTERRUPTS(ctx); /* Enable access to LPTMR module. LPTMR is bit 0 */ SIM->SCGC5 |= 1; /* Make sure timer is disabled */ LPTMR0->CSR = 0; /* Set isr in vector table and enable interrupt */ NVIC_SetPriority(LPTMR0_IRQn, prio); NVIC_SetVector(LPTMR0_IRQn, (uint32_t)mkw41z_os_tick_handler); NVIC_EnableIRQ(LPTMR0_IRQn); /* Set prescaler register. Bypass prescalar and use LPO (clock 1) */ prescaler_reg = LPTMR_PSR_PBYP_MASK | 1; LPTMR0->PSR = prescaler_reg; /* Write output compare while disabled */ LPTMR0->CMR = timer_ticks_per_ostick - 1; /* Enable the timer: note you cannot alter bits 5 to 1 (inclusive) */ LPTMR0->CSR = LPTMR_CSR_TIE_MASK | LPTMR_CSR_TEN_MASK; __HAL_ENABLE_INTERRUPTS(ctx); }
/* * Flash write is done by writing 4 bytes at a time at a word boundary. */ static int nrf52k_flash_write(uint32_t address, const void *src, uint32_t num_bytes) { int sr; int rc = -1; uint32_t val; int cnt; uint32_t tmp; if (nrf52k_flash_wait_ready()) { return -1; } __HAL_DISABLE_INTERRUPTS(sr); NRF_NVMC->CONFIG |= NVMC_CONFIG_WEN_Wen; /* Enable erase OP */ tmp = address & 0x3; if (tmp) { if (nrf52k_flash_wait_ready()) { goto out; } /* * Starts at a non-word boundary. Read 4 bytes which were there * before, update with new data, and write back. */ val = *(uint32_t *)(address & ~0x3); cnt = 4 - tmp; if (cnt > num_bytes) { cnt = num_bytes; } memcpy((uint8_t *)&val + tmp, src, cnt); *(uint32_t *)(address & ~0x3) = val; address += cnt; num_bytes -= cnt; src += cnt; } while (num_bytes >= sizeof(uint32_t)) { /* * Write data 4 bytes at a time. */ if (nrf52k_flash_wait_ready()) { goto out; } *(uint32_t *)address = *(uint32_t *)src; address += sizeof(uint32_t); src += sizeof(uint32_t); num_bytes -= sizeof(uint32_t); } if (num_bytes) { /* * Deal with the trailing bytes. */ val = *(uint32_t *)address; memcpy(&val, src, num_bytes); if (nrf52k_flash_wait_ready()) { goto out; } *(uint32_t *)address = val; } rc = 0; if (nrf52k_flash_wait_ready()) { goto out; } out: NRF_NVMC->CONFIG &= ~NVMC_CONFIG_WEN_Wen; __HAL_ENABLE_INTERRUPTS(sr); return rc; }
/** * cputime init * * Initialize the cputime module. This must be called after os_init is called * and before any other timer API are used. This should be called only once * and should be called before the hardware timer is used. * * @param clock_freq The desired cputime frequency, in hertz (Hz). * * @return int 0 on success; -1 on error. */ int cputime_hw_init(uint32_t clock_freq) { uint32_t ctx; uint32_t max_freq; uint32_t pre_scaler; #if defined(HAL_CPUTIME_1MHZ) if (clock_freq != 1000000) { return -1; } #endif /* Clock frequency must be at least 1 MHz */ if (clock_freq < 1000000U) { return -1; } /* Check if clock frequency exceeds max. range */ max_freq = NRF51_MAX_TIMER_FREQ; if (clock_freq > max_freq) { return -1; } /* Is this exact frequency obtainable? */ pre_scaler = max_freq / clock_freq; if ((pre_scaler * clock_freq) != max_freq) { return -1; } /* * Pre-scaler is 4 bits and is a 2^n, so the only possible values that * work are 1, 2, 4, 8 and 16, which gives a valid pre-scaler of 0, 1, 2, * 3 or 4. */ switch (pre_scaler) { case 1: pre_scaler = 0; break; case 2: pre_scaler = 1; break; case 4: pre_scaler = 2; break; case 8: pre_scaler = 3; break; case 16: pre_scaler = 4; break; default: pre_scaler = 0xFFFFFFFF; break; } if (pre_scaler == 0xFFFFFFFF) { return -1; } /* disable interrupts */ __HAL_DISABLE_INTERRUPTS(ctx); /* Set the clock frequency */ g_cputime.ticks_per_usec = clock_freq / 1000000U; /* XXX: no way to halt the timer in debug mode that I can see */ /* Stop the timer first */ CPUTIMER->TASKS_STOP = 1; /* Put the timer in timer mode using 32 bits. */ CPUTIMER->MODE = TIMER_MODE_MODE_Timer; CPUTIMER->BITMODE = TIMER_BITMODE_BITMODE_32Bit; /* Set the pre-scaler*/ CPUTIMER->PRESCALER = pre_scaler; /* Start the timer */ CPUTIMER->TASKS_START = 1; /* Use an output compare to generate an overflow */ #ifdef HAL_CPUTIME_USE_OVERFLOW CPUTIMER->CC[CPUTIMER_CC_OVERFLOW] = 0; CPUTIMER->EVENTS_COMPARE[CPUTIMER_CC_OVERFLOW] = 0; CPUTIMER->INTENSET = CPUTIMER_INT_MASK(CPUTIMER_CC_OVERFLOW); #endif /* Set isr in vector table and enable interrupt */ NVIC_SetVector(CPUTIMER_IRQ, (uint32_t)cputime_isr); NVIC_EnableIRQ(CPUTIMER_IRQ); __HAL_ENABLE_INTERRUPTS(ctx); return 0; }
int hal_spi_config(int spi_num, struct hal_spi_settings *settings) { struct stm32_hal_spi *spi; struct stm32_hal_spi_cfg *cfg; SPI_InitTypeDef *init; GPIO_InitTypeDef gpio; uint32_t gpio_speed; IRQn_Type irq; uint32_t prescaler; int rc; int sr; __HAL_DISABLE_INTERRUPTS(sr); STM32_HAL_SPI_RESOLVE(spi_num, spi); init = &spi->handle.Init; cfg = spi->cfg; if (!spi->slave) { spi->handle.Init.NSS = SPI_NSS_HARD_OUTPUT; spi->handle.Init.Mode = SPI_MODE_MASTER; } else { spi->handle.Init.NSS = SPI_NSS_SOFT; spi->handle.Init.Mode = SPI_MODE_SLAVE; } gpio.Mode = GPIO_MODE_AF_PP; gpio.Pull = GPIO_NOPULL; /* TODO: also VERY_HIGH for STM32L1x */ if (settings->baudrate <= 2000) { gpio_speed = GPIO_SPEED_FREQ_LOW; } else if (settings->baudrate <= 12500) { gpio_speed = GPIO_SPEED_FREQ_MEDIUM; } else { gpio_speed = GPIO_SPEED_FREQ_HIGH; } /* Enable the clocks for this SPI */ switch (spi_num) { #if SPI_0_ENABLED case 0: __HAL_RCC_SPI1_CLK_ENABLE(); #if !defined(STM32F1) gpio.Alternate = GPIO_AF5_SPI1; #endif spi->handle.Instance = SPI1; break; #endif #if SPI_1_ENABLED case 1: __HAL_RCC_SPI2_CLK_ENABLE(); #if !defined(STM32F1) gpio.Alternate = GPIO_AF5_SPI2; #endif spi->handle.Instance = SPI2; break; #endif #if SPI_2_ENABLED case 2: __HAL_RCC_SPI3_CLK_ENABLE(); #if !defined(STM32F1) gpio.Alternate = GPIO_AF6_SPI3; #endif spi->handle.Instance = SPI3; break; #endif #if SPI_3_ENABLED case 3: __HAL_RCC_SPI4_CLK_ENABLE(); #if !defined(STM32F1) gpio.Alternate = GPIO_AF5_SPI4; #endif spi->handle.Instance = SPI4; break; #endif #if SPI_4_ENABLED case 4: __HAL_RCC_SPI5_CLK_ENABLE(); #if !defined(STM32F1) gpio.Alternate = GPIO_AF5_SPI5; #endif spi->handle.Instance = SPI5; break; #endif #if SPI_5_ENABLED case 5: __HAL_RCC_SPI6_CLK_ENABLE(); #if !defined(STM32F1) gpio.Alternate = GPIO_AF5_SPI6; #endif spi->handle.Instance = SPI6; break; #endif default: assert(0); rc = -1; goto err; } if (!spi->slave) { if (settings->data_mode == HAL_SPI_MODE2 || settings->data_mode == HAL_SPI_MODE3) { gpio.Pull = GPIO_PULLUP; } else { gpio.Pull = GPIO_PULLDOWN; } } /* NOTE: Errata ES0125: STM32L100x6/8/B, STM32L151x6/8/B and * STM32L152x6/8/B ultra-low-power device limitations. * * 2.6.6 - Corrupted last bit of data and or CRC, received in Master * mode with delayed SCK feedback * * This driver is always using very high speed for SCK on STM32L1x */ #if defined(STM32L152xC) if (!spi->slave) { gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH; } else { gpio.Speed = gpio_speed; } #else gpio.Speed = gpio_speed; #endif rc = hal_gpio_init_stm(cfg->sck_pin, &gpio); if (rc != 0) { goto err; } #if defined(STM32L152xC) if (!spi->slave) { gpio.Speed = gpio_speed; } #endif if (!spi->slave) { gpio.Pull = GPIO_NOPULL; } else { gpio.Mode = GPIO_MODE_AF_OD; } rc = hal_gpio_init_stm(cfg->mosi_pin, &gpio); if (rc != 0) { goto err; } if (!spi->slave) { gpio.Mode = GPIO_MODE_AF_OD; } else { gpio.Mode = GPIO_MODE_AF_PP; } rc = hal_gpio_init_stm(cfg->miso_pin, &gpio); if (rc != 0) { goto err; } switch (settings->data_mode) { case HAL_SPI_MODE0: init->CLKPolarity = SPI_POLARITY_LOW; init->CLKPhase = SPI_PHASE_1EDGE; break; case HAL_SPI_MODE1: init->CLKPolarity = SPI_POLARITY_LOW; init->CLKPhase = SPI_PHASE_2EDGE; break; case HAL_SPI_MODE2: init->CLKPolarity = SPI_POLARITY_HIGH; init->CLKPhase = SPI_PHASE_1EDGE; break; case HAL_SPI_MODE3: init->CLKPolarity = SPI_POLARITY_HIGH; init->CLKPhase = SPI_PHASE_2EDGE; break; default: rc = -1; goto err; } switch (settings->data_order) { case HAL_SPI_MSB_FIRST: init->FirstBit = SPI_FIRSTBIT_MSB; break; case HAL_SPI_LSB_FIRST: init->FirstBit = SPI_FIRSTBIT_LSB; break; default: rc = -1; goto err; } switch (settings->word_size) { case HAL_SPI_WORD_SIZE_8BIT: init->DataSize = SPI_DATASIZE_8BIT; break; case HAL_SPI_WORD_SIZE_9BIT: init->DataSize = SPI_DATASIZE_16BIT; break; default: rc = -1; goto err; } rc = stm32_spi_resolve_prescaler(spi_num, settings->baudrate * 1000, &prescaler); if (rc != 0) { goto err; } init->BaudRatePrescaler = prescaler; /* Add default values */ init->Direction = SPI_DIRECTION_2LINES; init->TIMode = SPI_TIMODE_DISABLE; init->CRCCalculation = SPI_CRCCALCULATION_DISABLE; init->CRCPolynomial = 1; #ifdef SPI_NSS_PULSE_DISABLE init->NSSPMode = SPI_NSS_PULSE_DISABLE; #endif irq = stm32_resolve_spi_irq(&spi->handle); NVIC_SetPriority(irq, cfg->irq_prio); NVIC_SetVector(irq, stm32_resolve_spi_irq_handler(&spi->handle)); NVIC_EnableIRQ(irq); /* Init, Enable */ rc = HAL_SPI_Init(&spi->handle); if (rc != 0) { goto err; } if (spi->slave) { hal_spi_slave_set_def_tx_val(spi_num, 0); rc = hal_gpio_irq_init(cfg->ss_pin, spi_ss_isr, spi, HAL_GPIO_TRIG_BOTH, HAL_GPIO_PULL_UP); spi_ss_isr(spi); } __HAL_ENABLE_INTERRUPTS(sr); return (0); err: __HAL_ENABLE_INTERRUPTS(sr); return (rc); }