/** * \ingroup freertos_uart_peripheral_control_group * \brief Initiate a completely asynchronous multi-byte write operation on a * UART peripheral. * * freertos_uart_write_packet_async() is an ASF specific FreeRTOS driver * function. It configures the UART peripheral DMA controller (PDC) to * transmit data on the UART port, then returns. * freertos_uart_write_packet_async() does not wait for the transmission to * complete before returning. * * The FreeRTOS UART driver is initialized using a call to * freertos_uart_serial_init(). The freertos_driver_parameters.options_flags * parameter passed into the initialization function defines the driver behavior. * freertos_uart_write_packet_async() can only be used if the * freertos_driver_parameters.options_flags parameter passed to the initialization * function had the WAIT_TX_COMPLETE bit clear. * * freertos_uart_write_packet_async() is an advanced function and readers are * recommended to also reference the application note and examples that * accompany the FreeRTOS ASF drivers. freertos_uart_write_packet() is a * version that does not exit until the PDC transfer is complete, but still * allows other RTOS tasks to execute while the transmission is in progress. * * The FreeRTOS ASF driver both installs and handles the UART PDC interrupts. * Users do not need to concern themselves with interrupt handling, and must * not install their own interrupt handler. * * \param p_uart The handle to the UART peripheral returned by the * freertos_uart_serial_init() call used to initialise the peripheral. * \param data A pointer to the data to be transmitted. * \param len The number of bytes to transmit. * \param block_time_ticks The FreeRTOS ASF UART driver is initialized using * a call to freertos_uart_serial_init(). The * freertos_driver_parameters.options_flags parameter passed to the * initialization function defines the driver behavior. If * freertos_driver_parameters.options_flags had the USE_TX_ACCESS_MUTEX bit * set, then the driver will only write to the UART peripheral if it has * first gained exclusive access to it. block_time_ticks specifies the * maximum amount of time the driver will wait to get exclusive access * before aborting the write operation. Other tasks will execute during any * waiting time. block_time_ticks is specified in RTOS tick periods. To * specify a block time in milliseconds, divide the milliseconds value by * portTICK_RATE_MS, and pass the result in block_time_ticks. * portTICK_RATE_MS is defined by FreeRTOS. * \param notification_semaphore The RTOS task that calls the transmit * function exits the transmit function as soon as the transmission starts. * The data being transmitted by the PDC must not be modified until after * the transmission has completed. The PDC interrupt (handled internally by * the FreeRTOS ASF driver) 'gives' the semaphore when the PDC transfer * completes. The notification_semaphore therefore provides a mechanism for * the calling task to know when the PDC has finished accessing the data. * The calling task can call standard FreeRTOS functions to block on the * semaphore until the PDC interrupt occurs. Other RTOS tasks will execute * while the the calling task is in the Blocked state. The semaphore must * be created using the FreeRTOS vSemaphoreCreateBinary() API function * before it is used as a parameter. * * \return ERR_INVALID_ARG is returned if an input parameter is invalid. * ERR_TIMEOUT is returned if block_time_ticks passed before exclusive * access to the UART peripheral could be obtained. STATUS_OK is returned * if the PDC was successfully configured to perform the UART write * operation. */ status_code_t freertos_uart_write_packet_async(freertos_uart_if p_uart, const uint8_t *data, size_t len, portTickType block_time_ticks, xSemaphoreHandle notification_semaphore) { status_code_t return_value; portBASE_TYPE uart_index; Uart *uart_base; uart_base = (Uart *) p_uart; uart_index = get_pdc_peripheral_details(all_uart_definitions, MAX_UARTS, (void *) uart_base); /* Don't do anything unless a valid UART pointer was used. */ if (uart_index < MAX_UARTS) { return_value = freertos_obtain_peripheral_access_mutex( &(tx_dma_control[uart_index]), &block_time_ticks); if (return_value == STATUS_OK) { freertos_start_pdc_tx(&(tx_dma_control[uart_index]), data, len, all_uart_definitions[uart_index].pdc_base_address, notification_semaphore); /* Catch the end of transmission so the access mutex can be returned, and the task notified (if it supplied a notification semaphore). The interrupt can be enabled here because the ENDTX signal from the PDC to the UART will have been de-asserted when the next transfer was configured. */ uart_enable_interrupt(uart_base, UART_IER_ENDTX); return_value = freertos_optionally_wait_transfer_completion( &(tx_dma_control[uart_index]), notification_semaphore, block_time_ticks); } } else { return_value = ERR_INVALID_ARG; } return return_value; }
/** * \ingroup freertos_spi_peripheral_control_group * \brief Initiate a completely asynchronous multi-byte read operation on an SPI * peripheral. * * freertos_spi_read_packet_async() is an ASF specific FreeRTOS driver function. * It configures the SPI peripheral DMA controller (PDC) to read data from the * SPI port, then returns. freertos_spi_read_packet_async() does not wait for * the reception to complete before returning. * * The FreeRTOS ASF SPI driver is initialized using a call to * freertos_spi_master_init(). The freertos_driver_parameters.options_flags * parameter passed into the initialization function defines the driver behavior. * freertos_spi_read_packet_async() can only be used if the * freertos_driver_parameters.options_flags parameter passed to the initialization * function had the WAIT_RX_COMPLETE bit clear. * * freertos_spi_read_packet_async() is an advanced function and readers are * recommended to also reference the application note and examples that * accompany the FreeRTOS ASF drivers. freertos_spi_read_packet() is a version * that does not exit until the PDC transfer is complete, but still allows other * RTOS tasks to execute while the transmission is in progress. * * The FreeRTOS ASF driver both installs and handles the SPI PDC interrupts. * Users do not need to concern themselves with interrupt handling, and must * not install their own interrupt handler. * * \param p_spi The handle to the SPI port returned by the * freertos_spi_master_init() call used to initialise the port. * \param data A pointer to the buffer into which received data is to be * written. * \param len The number of bytes to receive. * \param block_time_ticks The FreeRTOS ASF SPI driver is initialized using a * call to freertos_spi_master_init(). The * freertos_driver_parameters.options_flags parameter passed to the * initialization function defines the driver behavior. If * freertos_driver_parameters.options_flags had the USE_RX_ACCESS_MUTEX bit * set, then the driver will only read from the SPI peripheral if it has * first gained exclusive access to it. block_time_ticks specifies the * maximum amount of time the driver will wait to get exclusive access * before aborting the read operation. Other tasks will execute during any * waiting time. block_time_ticks is specified in RTOS tick periods. To * specify a block time in milliseconds, divide the milliseconds value by * portTICK_RATE_MS, and pass the result in block_time_ticks. * portTICK_RATE_MS is defined by FreeRTOS. * \param notification_semaphore The RTOS task that calls the receive * function exits the receive function as soon as the reception starts. * The data being received by the PDC cannot normally be processed until * after the reception has completed. The PDC interrupt (handled internally * by the FreeRTOS ASF driver) 'gives' the semaphore when the PDC transfer * completes. The notification_semaphore therefore provides a mechanism for * the calling task to know when the PDC has read the requested number of * bytes. The calling task can call standard FreeRTOS functions to block on * the semaphore until the PDC interrupt occurs. Other RTOS tasks will * execute while the the calling task is in the Blocked state. The * semaphore must be created using the FreeRTOS vSemaphoreCreateBinary() API * function before it is used as a parameter. * * \return ERR_INVALID_ARG is returned if an input parameter is invalid. * ERR_TIMEOUT is returned if block_time_ticks passed before exclusive * access to the SPI peripheral could be obtained. STATUS_OK is returned if * the PDC was successfully configured to perform the SPI read operation. */ status_code_t freertos_spi_read_packet_async(freertos_spi_if p_spi, uint8_t *data, uint32_t len, portTickType block_time_ticks, xSemaphoreHandle notification_semaphore) { status_code_t return_value; pdc_packet_t pdc_tx_packet; portBASE_TYPE spi_index; Spi *spi_base; volatile uint16_t junk_value; spi_base = (Spi *) p_spi; spi_index = get_pdc_peripheral_details(all_spi_definitions, MAX_SPIS, (void *) spi_base); /* Don't do anything unless a valid SPI pointer was used. */ if (spi_index < MAX_SPIS) { /* Because the peripheral is half duplex, there is only one access mutex and the rx uses the tx mutex. */ return_value = freertos_obtain_peripheral_access_mutex( &(tx_dma_control[spi_index]), &block_time_ticks); if (return_value == STATUS_OK) { /* Data must be sent for data to be received. Set the receive buffer to all 0xffs so it can also be used as the send buffer. */ memset((void *)data, 0xff, (size_t)len); /* Ensure Rx is already empty. */ while(spi_is_rx_full(all_spi_definitions[spi_index].peripheral_base_address) != 0) { junk_value = ((Spi*) all_spi_definitions[spi_index].peripheral_base_address)->SPI_RDR; (void) junk_value; } /* Start the PDC reception, although nothing is received until the SPI is also transmitting. */ freertos_start_pdc_rx(&(rx_dma_control[spi_index]), data, len, all_spi_definitions[spi_index].pdc_base_address, notification_semaphore); /* Start the transmit so data is also received. */ pdc_tx_packet.ul_addr = (uint32_t)data; pdc_tx_packet.ul_size = (uint32_t)len; pdc_disable_transfer( all_spi_definitions[spi_index].pdc_base_address, PERIPH_PTCR_TXTDIS); pdc_tx_init( all_spi_definitions[spi_index].pdc_base_address, &pdc_tx_packet, NULL); pdc_enable_transfer( all_spi_definitions[spi_index].pdc_base_address, PERIPH_PTCR_TXTEN); /* Catch the end of reception so the access mutex can be returned, and the task notified (if it supplied a notification semaphore). The interrupt can be enabled here because the ENDRX signal from the PDC to the peripheral will have been de-asserted when the next transfer was configured. */ spi_enable_interrupt(spi_base, SPI_IER_ENDRX); return_value = freertos_optionally_wait_transfer_completion( &(rx_dma_control[spi_index]), notification_semaphore, block_time_ticks); } } else { return_value = ERR_INVALID_ARG; } return return_value; }
/** * \ingroup freertos_twi_peripheral_control_group * \brief Initiate a completely asynchronous multi-byte read operation on an TWI * peripheral. * * freertos_twi_read_packet_async() is an ASF specific FreeRTOS driver function. * It configures the TWI peripheral DMA controller (PDC) to read data from the * TWI port, then returns. freertos_twi_read_packet_async() does not wait for * the reception to complete before returning. * * The FreeRTOS ASF TWI driver is initialized using a call to * freertos_twi_master_init(). The freertos_driver_parameters.options_flags * parameter passed into the initialization function defines the driver behavior. * freertos_twi_read_packet_async() can only be used if the * freertos_driver_parameters.options_flags parameter passed to the initialization * function had the WAIT_RX_COMPLETE bit clear. The function can also only be used * if the length of the packet is more that two. If less, it will block until the * transfer is done. * * freertos_twi_read_packet_async() is an advanced function and readers are * recommended to also reference the application note and examples that * accompany the FreeRTOS ASF drivers. freertos_twi_read_packet() is a version * that does not exit until the PDC transfer is complete, but still allows other * RTOS tasks to execute while the transmission is in progress. * * The FreeRTOS ASF driver both installs and handles the TWI PDC interrupts. * Users do not need to concern themselves with interrupt handling, and must * not install their own interrupt handler. * * \param p_twi The handle to the TWI port returned by the * freertos_twi_master_init() call used to initialise the port. * \param p_packet Structure that defines the TWI transfer parameters, such * as the I2C chip being addressed, the destination for the data being read, * and the number of bytes to read. twi_packet_t is a standard ASF type (it * is not FreeRTOS specific). * \param block_time_ticks The FreeRTOS ASF TWI driver is initialized using a * call to freertos_twi_master_init(). The * freertos_driver_parameters.options_flags parameter passed to the * initialization function defines the driver behavior. If * freertos_driver_parameters.options_flags had the USE_RX_ACCESS_MUTEX bit * set, then the driver will only read from the TWI peripheral if it has * first gained exclusive access to it. block_time_ticks specifies the * maximum amount of time the driver will wait to get exclusive access * before aborting the read operation. Other tasks will execute during any * waiting time. block_time_ticks is specified in RTOS tick periods. To * specify a block time in milliseconds, divide the milliseconds value by * portTICK_RATE_MS, and pass the result in block_time_ticks. * portTICK_RATE_MS is defined by FreeRTOS. * \param notification_semaphore The RTOS task that calls the receive * function exits the receive function as soon as the reception starts. * The data being received by the PDC cannot normally be processed until * after the reception has completed. The PDC interrupt (handled internally * by the FreeRTOS ASF driver) 'gives' the semaphore when the PDC transfer * completes. The notification_semaphore therefore provides a mechanism for * the calling task to know when the PDC has read the requested number of * bytes. The calling task can call standard FreeRTOS functions to block on * the semaphore until the PDC interrupt occurs. Other RTOS tasks will * execute while the the calling task is in the Blocked state. The * semaphore must be created using the FreeRTOS vSemaphoreCreateBinary() API * function before it is used as a parameter. * * \return ERR_INVALID_ARG is returned if an input parameter is invalid. * ERR_TIMEOUT is returned if block_time_ticks passed before exclusive * access to the TWI peripheral could be obtained. STATUS_OK is returned if * the PDC was successfully configured to perform the TWI read operation. */ status_code_t freertos_twi_read_packet_async(freertos_twi_if p_twi, twi_packet_t *p_packet, portTickType block_time_ticks, xSemaphoreHandle notification_semaphore) { status_code_t return_value; portBASE_TYPE twi_index; Twi *twi_base; uint32_t internal_address = 0; twi_base = (Twi *) p_twi; twi_index = get_pdc_peripheral_details(all_twi_definitions, MAX_TWIS, (void *) twi_base); /* Don't do anything unless a valid TWI pointer was used. */ if ((twi_index < MAX_TWIS) && (p_packet->length > 0)) { /* Because the peripheral is half duplex, there is only one access mutex and the rx uses the tx mutex. */ return_value = freertos_obtain_peripheral_access_mutex( &(tx_dma_control[twi_index]), &block_time_ticks); if (return_value == STATUS_OK) { /* Ensure Rx is already empty. */ twi_read_byte(twi_base); /* Set read mode and slave address. */ twi_base->TWI_MMR = 0; twi_base->TWI_MMR = TWI_MMR_MREAD | TWI_MMR_DADR( p_packet->chip) | ((p_packet->addr_length << TWI_MMR_IADRSZ_Pos) & TWI_MMR_IADRSZ_Msk); /* Set internal address if any. */ if (p_packet->addr_length) { internal_address = p_packet->addr [0]; if (p_packet->addr_length > 1) { internal_address <<= 8; internal_address |= p_packet->addr[1]; } if (p_packet->addr_length > 2) { internal_address <<= 8; internal_address |= p_packet->addr[2]; } } twi_base->TWI_IADR = internal_address; if (p_packet->length <= 2) { /* Do not handle errors for short packets in interrupt handler */ twi_disable_interrupt( all_twi_definitions[twi_index].peripheral_base_address, IER_ERROR_INTERRUPTS); /* Cannot use PDC transfer, use normal transfer */ uint8_t stop_sent = 0; uint32_t cnt = p_packet->length; uint32_t status; uint8_t *buffer = p_packet->buffer; uint32_t timeout_counter = 0; /* Start the transfer. */ if (cnt == 1) { twi_base->TWI_CR = TWI_CR_START | TWI_CR_STOP; stop_sent = 1; } else { twi_base->TWI_CR = TWI_CR_START; } while (cnt > 0) { status = twi_base->TWI_SR; if (status & TWI_SR_NACK) { /* Re-enable interrupts */ twi_enable_interrupt( all_twi_definitions[twi_index].peripheral_base_address, IER_ERROR_INTERRUPTS); /* Release semaphore */ xSemaphoreGive(tx_dma_control[twi_index].peripheral_access_mutex); return ERR_BUSY; } /* Last byte ? */ if (cnt == 1 && !stop_sent) { twi_base->TWI_CR = TWI_CR_STOP; stop_sent = 1; } if (!(status & TWI_SR_RXRDY)) { if (++timeout_counter >= TWI_TIMEOUT_COUNTER) { return_value = ERR_TIMEOUT; break; } continue; } *buffer++ = twi_base->TWI_RHR; cnt--; timeout_counter = 0; } timeout_counter = 0; /* Wait for stop to be sent */ while (!(twi_base->TWI_SR & TWI_SR_TXCOMP)) { /* Check timeout condition. */ if (++timeout_counter >= TWI_TIMEOUT_COUNTER) { return_value = ERR_TIMEOUT; break; } } /* Re-enable interrupts */ twi_enable_interrupt( all_twi_definitions[twi_index].peripheral_base_address, IER_ERROR_INTERRUPTS); /* Release semaphores */ xSemaphoreGive(tx_dma_control[twi_index].peripheral_access_mutex); if (return_value != ERR_TIMEOUT) { if (rx_dma_control[twi_index].transaction_complete_notification_semaphore != NULL) { xSemaphoreGive(rx_dma_control[twi_index].transaction_complete_notification_semaphore); } } } else { /* Start the PDC reception. */ twis[twi_index].buffer = p_packet->buffer; twis[twi_index].length = p_packet->length; freertos_start_pdc_rx(&(rx_dma_control[twi_index]), p_packet->buffer, (p_packet->length)-2, all_twi_definitions[twi_index].pdc_base_address, notification_semaphore); /* Start the transfer. */ twi_base->TWI_CR = TWI_CR_START; /* Catch the end of reception so the access mutex can be returned, and the task notified (if it supplied a notification semaphore). The interrupt can be enabled here because the ENDRX signal from the PDC to the peripheral will have been de-asserted when the next transfer was configured. */ twi_enable_interrupt(twi_base, TWI_IER_ENDRX); return_value = freertos_optionally_wait_transfer_completion( &(rx_dma_control[twi_index]), notification_semaphore, block_time_ticks); } } } else { return_value = ERR_INVALID_ARG; } return return_value; }
/** * \ingroup freertos_twi_peripheral_control_group * \brief Initiate a completely asynchronous multi-byte write operation on a TWI * peripheral. * * freertos_twi_write_packet_async() is an ASF specific FreeRTOS driver function. * It configures the TWI peripheral DMA controller (PDC) to transmit data on the * TWI port, then returns. freertos_twi_write_packet_async() does not wait for * the transmission to complete before returning. * * The FreeRTOS TWI driver is initialized using a call to * freertos_twi_master_init(). The freertos_driver_parameters.options_flags * parameter passed into the initialization function defines the driver behavior. * freertos_twi_write_packet_async() can only be used if the * freertos_driver_parameters.options_flags parameter passed to the initialization * function had the WAIT_TX_COMPLETE bit clear. It can also only be used if packet * length is more than 1. * * freertos_twi_write_packet_async() is an advanced function and readers are * recommended to also reference the application note and examples that * accompany the FreeRTOS ASF drivers. freertos_twi_write_packet() is a version * that does not exit until the PDC transfer is complete, but still allows other * RTOS tasks to execute while the transmission is in progress. * * The FreeRTOS ASF driver both installs and handles the TWI PDC interrupts. * Users do not need to concern themselves with interrupt handling, and must * not install their own interrupt handler. * * \param p_twi The handle to the TWI peripheral returned by the * freertos_twi_master_init() call used to initialise the peripheral. * \param p_packet Structure that defines the TWI transfer parameters, such * as the I2C chip being addressed, the source data location, and the number * of bytes to transmit. twi_packet_t is a standard ASF type (it is not * FreeRTOS specific). * \param block_time_ticks The FreeRTOS ASF TWI driver is initialized using a * call to freertos_twi_master_init(). The * freertos_driver_parameters.options_flags parameter passed to the * initialization function defines the driver behavior. If * freertos_driver_parameters.options_flags had the USE_TX_ACCESS_MUTEX bit * set, then the driver will only write to the TWI peripheral if it has * first gained exclusive access to it. block_time_ticks specifies the * maximum amount of time the driver will wait to get exclusive access * before aborting the write operation. Other tasks will execute during any * waiting time. block_time_ticks is specified in RTOS tick periods. To * specify a block time in milliseconds, divide the milliseconds value by * portTICK_RATE_MS, and pass the result in block_time_ticks. * portTICK_RATE_MS is defined by FreeRTOS. * \param notification_semaphore The RTOS task that calls the transmit * function exits the transmit function as soon as the transmission starts. * The data being transmitted by the PDC must not be modified until after * the transmission has completed. The PDC interrupt (handled internally by * the FreeRTOS ASF driver) 'gives' the semaphore when the PDC transfer * completes. The notification_semaphore therefore provides a mechanism for * the calling task to know when the PDC has finished accessing the data. * The calling task can call standard FreeRTOS functions to block on the * semaphore until the PDC interrupt occurs. Other RTOS tasks will execute * while the the calling task is in the Blocked state. The semaphore must * be created using the FreeRTOS vSemaphoreCreateBinary() API function * before it is used as a parameter. * * \return ERR_INVALID_ARG is returned if an input parameter is invalid. * ERR_TIMEOUT is returned if block_time_ticks passed before exclusive * access to the TWI peripheral could be obtained. STATUS_OK is returned if * the PDC was successfully configured to perform the TWI write operation. */ status_code_t freertos_twi_write_packet_async(freertos_twi_if p_twi, twi_packet_t *p_packet, portTickType block_time_ticks, xSemaphoreHandle notification_semaphore) { status_code_t return_value; portBASE_TYPE twi_index; Twi *twi_base; uint32_t internal_address = 0; twi_base = (Twi *) p_twi; twi_index = get_pdc_peripheral_details(all_twi_definitions, MAX_TWIS, (void *) twi_base); /* Don't do anything unless a valid TWI pointer was used. */ if ((twi_index < MAX_TWIS) && (p_packet->length > 0)) { return_value = freertos_obtain_peripheral_access_mutex( &(tx_dma_control[twi_index]), &block_time_ticks); if (return_value == STATUS_OK) { /* Set write mode and slave address. */ twi_base->TWI_MMR = 0; twi_base->TWI_MMR = TWI_MMR_DADR(p_packet->chip) | ((p_packet->addr_length << TWI_MMR_IADRSZ_Pos) & TWI_MMR_IADRSZ_Msk); /* Set internal address if any. */ if (p_packet->addr_length > 0) { internal_address = p_packet->addr[0]; if (p_packet->addr_length > 1) { internal_address <<= 8; internal_address |= p_packet->addr[1]; } if (p_packet->addr_length > 2) { internal_address <<= 8; internal_address |= p_packet->addr[2]; } } twi_base->TWI_IADR = internal_address; if (p_packet->length == 1) { uint32_t status; uint32_t timeout_counter = 0; /* Do not handle errors for short packets in interrupt handler */ twi_disable_interrupt( all_twi_definitions[twi_index].peripheral_base_address, IER_ERROR_INTERRUPTS); /* Send start condition */ twi_base->TWI_THR = *((uint8_t*)(p_packet->buffer)); while (1) { status = twi_base->TWI_SR; if (status & TWI_SR_NACK) { /* Re-enable interrupts */ twi_enable_interrupt( all_twi_definitions[twi_index].peripheral_base_address, IER_ERROR_INTERRUPTS); /* Release semaphore */ xSemaphoreGive(tx_dma_control[twi_index].peripheral_access_mutex); return ERR_BUSY; } if (status & TWI_SR_TXRDY) { break; } /* Check timeout condition. */ if (++timeout_counter >= TWI_TIMEOUT_COUNTER) { return_value = ERR_TIMEOUT; break; } } twi_base->TWI_CR = TWI_CR_STOP; /* Wait for TX complete */ while (!(twi_base->TWI_SR & TWI_SR_TXCOMP)) { /* Check timeout condition. */ if (++timeout_counter >= TWI_TIMEOUT_COUNTER) { return_value = ERR_TIMEOUT; break; } } /* Re-enable interrupts */ twi_enable_interrupt( all_twi_definitions[twi_index].peripheral_base_address, IER_ERROR_INTERRUPTS); /* Release semaphores */ xSemaphoreGive(tx_dma_control[twi_index].peripheral_access_mutex); if (return_value != ERR_TIMEOUT) { if (tx_dma_control[twi_index].transaction_complete_notification_semaphore != NULL) { xSemaphoreGive(tx_dma_control[twi_index].transaction_complete_notification_semaphore); } } } else { twis[twi_index].buffer = p_packet->buffer; twis[twi_index].length = p_packet->length; freertos_start_pdc_tx(&(tx_dma_control[twi_index]), p_packet->buffer, p_packet->length - 1, all_twi_definitions[twi_index].pdc_base_address, notification_semaphore); /* Catch the end of transmission so the access mutex can be returned, and the task notified (if it supplied a notification semaphore). The interrupt can be enabled here because the ENDTX signal from the PDC to the peripheral will have been de-asserted when the next transfer was configured. */ twi_enable_interrupt(twi_base, TWI_IER_ENDTX); return_value = freertos_optionally_wait_transfer_completion( &(tx_dma_control[twi_index]), notification_semaphore, block_time_ticks); } } } else { return_value = ERR_INVALID_ARG; } return return_value; }