Example #1
0
/*
 * For internal use only.
 * A common TWIHS interrupt handler that is called for all TWIHS peripherals.
 */
static void local_twihs_handler(const portBASE_TYPE twihs_index)
{
	portBASE_TYPE higher_priority_task_woken = pdFALSE;
	uint32_t twihs_status;
	Twihs *twihs_port;

	twihs_port = all_twihs_definitions[twihs_index].peripheral_base_address;

	twihs_status = twihs_get_interrupt_status(twihs_port);
	twihs_status &= twihs_get_interrupt_mask(twihs_port);

	/* Has the PDC completed a transmission? */
	if ((twihs_status & TWIHS_SR_ENDTX) != 0UL) {
		/* Disable PDC */
		pdc_disable_transfer(all_twihs_definitions[twihs_index].pdc_base_address, PERIPH_PTCR_TXTDIS);
		twihs_disable_interrupt(twihs_port, TWIHS_IDR_ENDTX);

		uint8_t status;
		uint32_t timeout_counter = 0;

		/* Wait for TX ready flag */
		while (1) {
			status = twihs_port->TWIHS_SR;
			if (status & TWIHS_SR_TXRDY) {
				break;
			}
			/* Check timeout condition. */
			if (++timeout_counter >= TWIHS_TIMEOUT_COUNTER) {
				status = ERR_TIMEOUT;
				break;
			}
		}
		/* Complete the transfer - stop and last byte */
		twihs_port->TWIHS_CR = TWIHS_CR_STOP;
		twihs_port->TWIHS_THR = twihss[twihs_index].buffer[twihss[twihs_index].length-1];

		/* Wait for TX complete flag */
		while (1) {
			status = twihs_port->TWIHS_SR;
			if (status & TWIHS_SR_TXCOMP) {
				break;
			}
			/* Check timeout condition. */
			if (++timeout_counter >= TWIHS_TIMEOUT_COUNTER) {
				status = ERR_TIMEOUT;
				break;
			}
		}


		/* If the driver is supporting multi-threading, then return the access
		mutex. */
		if (tx_dma_control[twihs_index].peripheral_access_mutex != NULL) {
			xSemaphoreGiveFromISR(
					tx_dma_control[twihs_index].peripheral_access_mutex,
					&higher_priority_task_woken);
		}

		/* if the sending task supplied a notification semaphore, then
		notify the task that the transmission has completed. */
		if (!(timeout_counter >= TWIHS_TIMEOUT_COUNTER)) {
			if (tx_dma_control[twihs_index]. transaction_complete_notification_semaphore != NULL) {
				xSemaphoreGiveFromISR(
						tx_dma_control[twihs_index].transaction_complete_notification_semaphore,
						&higher_priority_task_woken);
			}
		}
	}

	/* Has the PDC completed a reception? */
	if ((twihs_status & TWIHS_SR_ENDRX) != 0UL) {
		uint32_t timeout_counter = 0;
		uint32_t status;
		/* Must handle the two last bytes */
		/* Disable PDC */
		pdc_disable_transfer(all_twihs_definitions[twihs_index].pdc_base_address, PERIPH_PTCR_RXTDIS);

		twihs_disable_interrupt(twihs_port, TWIHS_IDR_ENDRX);

		/* Wait for RX ready flag */
		while (1) {
			status = twihs_port->TWIHS_SR;
			if (status & TWIHS_SR_RXRDY) {
				break;
			}
			/* Check timeout condition. */
			if (++timeout_counter >= TWIHS_TIMEOUT_COUNTER) {
				break;
			}
		}
		/* Complete the transfer. */
		twihs_port->TWIHS_CR = TWIHS_CR_STOP;
		/* Read second last data */
		twihss[twihs_index].buffer[(twihss[twihs_index].length)-2] = twihs_port->TWIHS_RHR;

		/* Wait for RX ready flag */
		while (1) {
			status = twihs_port->TWIHS_SR;
			if (status & TWIHS_SR_RXRDY) {
				break;
			}
			/* Check timeout condition. */
			if (++timeout_counter >= TWIHS_TIMEOUT_COUNTER) {
				break;
			}
		}

		if (!(timeout_counter >= TWIHS_TIMEOUT_COUNTER)) {
			/* Read last data */
			twihss[twihs_index].buffer[(twihss[twihs_index].length)-1] = twihs_port->TWIHS_RHR;
			timeout_counter = 0;
			/* Wait for TX complete flag before releasing semaphore */
			while (1) {
				status = twihs_port->TWIHS_SR;
				if (status & TWIHS_SR_TXCOMP) {
					break;
				}
				/* Check timeout condition. */
				if (++timeout_counter >= TWIHS_TIMEOUT_COUNTER) {
					status = ERR_TIMEOUT;
					break;
				}
			}
		}

		/* If the driver is supporting multi-threading, then return the access
		mutex.  NOTE: As the peripheral is half duplex there is only one
		access mutex, and the reception uses the tx access muted. */
		if (tx_dma_control[twihs_index].peripheral_access_mutex != NULL) {
			xSemaphoreGiveFromISR(
					tx_dma_control[twihs_index].peripheral_access_mutex,
					&higher_priority_task_woken);
		}

		/* if the receiving task supplied a notification semaphore, then
		notify the task that the transmission has completed. */
		if  (!(timeout_counter >= TWIHS_TIMEOUT_COUNTER)) {
			if (rx_dma_control[twihs_index].transaction_complete_notification_semaphore != NULL) {
				xSemaphoreGiveFromISR(
						rx_dma_control[twihs_index].transaction_complete_notification_semaphore,
						&higher_priority_task_woken);
			}
		}
	}

	if ((twihs_status & SR_ERROR_INTERRUPTS) != 0) {
		/* An error occurred in either a transmission or reception.  Abort.
		Stop the transmission, disable interrupts used by the peripheral, and
		ensure the peripheral access mutex is made available to tasks.  As this
		peripheral is half duplex, only the Tx peripheral access mutex exits.*/

		/* Stop the PDC */
		pdc_disable_transfer(all_twihs_definitions[twihs_index].pdc_base_address, PERIPH_PTCR_TXTDIS | PERIPH_PTCR_RXTDIS);

		if (!(twihs_status & TWIHS_SR_NACK)) {
			/* Do not send stop if NACK received. Handled by hardware */
			twihs_port->TWIHS_CR = TWIHS_CR_STOP;
		}
		twihs_disable_interrupt(twihs_port, TWIHS_IDR_ENDTX);
		twihs_disable_interrupt(twihs_port, TWIHS_IDR_ENDRX);

		if (tx_dma_control[twihs_index].peripheral_access_mutex != NULL) {
			xSemaphoreGiveFromISR(
					tx_dma_control[twihs_index].peripheral_access_mutex,
					&higher_priority_task_woken);
		}
	}

	/* If giving a semaphore caused a task to unblock, and the unblocked task
	has a priority equal to or higher than the currently running task (the task
	this ISR interrupted), then higher_priority_task_woken will have
	automatically been set to pdTRUE within the semaphore function.
	portEND_SWITCHING_ISR() will then ensure that this ISR returns directly to
	the higher priority unblocked task. */
	portEND_SWITCHING_ISR(higher_priority_task_woken);
}
Example #2
0
void BOARD_TWIHS_Handler(void)
{
	uint32_t status;

	status = twihs_get_interrupt_status(BOARD_BASE_TWIHS_SLAVE);

	if (((status & TWIHS_SR_SVACC) == TWIHS_SR_SVACC)
			&& (emulate_driver.uc_acquire_address == 0)) {
		twihs_disable_interrupt(BOARD_BASE_TWIHS_SLAVE, TWIHS_IDR_SVACC);
		twihs_enable_interrupt(BOARD_BASE_TWIHS_SLAVE,
				TWIHS_IER_RXRDY | TWIHS_IER_GACC |
				TWIHS_IER_NACK | TWIHS_IER_EOSACC | TWIHS_IER_SCL_WS);
		emulate_driver.uc_acquire_address++;
		emulate_driver.us_page_address = 0;
		emulate_driver.us_offset_memory = 0;
	}

	if ((status & TWIHS_SR_GACC) == TWIHS_SR_GACC) {
		puts("General Call Treatment\n\r");
		puts("not treated");
	}

	if (((status & TWIHS_SR_SVACC) == TWIHS_SR_SVACC) &&
			((status & TWIHS_SR_GACC) == 0) &&
			((status & TWIHS_SR_RXRDY) == TWIHS_SR_RXRDY)) {

		if (emulate_driver.uc_acquire_address == 1) {
			/* Acquire MSB address */
			emulate_driver.us_page_address =
					(twihs_read_byte(BOARD_BASE_TWIHS_SLAVE) & 0xFF) << 8;
			emulate_driver.uc_acquire_address++;
		} else {
			if (emulate_driver.uc_acquire_address == 2) {
				/* Acquire LSB address */
				emulate_driver.us_page_address |=
						(twihs_read_byte(BOARD_BASE_TWIHS_SLAVE) & 0xFF);
				emulate_driver.uc_acquire_address++;
			} else {
				/* Read one byte of data from master to slave device */
				emulate_driver.uc_memory[emulate_driver.us_page_address +
						emulate_driver.us_offset_memory] =
						(twihs_read_byte(BOARD_BASE_TWIHS_SLAVE) & 0xFF);
				emulate_driver.us_offset_memory++;
			}
		}
	} else {
		if (((status & TWIHS_SR_TXRDY) == TWIHS_SR_TXRDY)
				&& ((status & TWIHS_SR_TXCOMP) == TWIHS_SR_TXCOMP)
				&& ((status & TWIHS_SR_EOSACC) == TWIHS_SR_EOSACC)) {
			/* End of transfer, end of slave access */
			emulate_driver.us_offset_memory = 0;
			emulate_driver.uc_acquire_address = 0;
			emulate_driver.us_page_address = 0;
			twihs_enable_interrupt(BOARD_BASE_TWIHS_SLAVE, TWIHS_SR_SVACC);
			twihs_disable_interrupt(BOARD_BASE_TWIHS_SLAVE,
					TWIHS_IDR_RXRDY | TWIHS_IDR_GACC |
					TWIHS_IDR_NACK | TWIHS_IDR_EOSACC | TWIHS_IDR_SCL_WS);
		} else {
			if (((status & TWIHS_SR_SVACC) == TWIHS_SR_SVACC)
					&& ((status & TWIHS_SR_GACC) == 0)
					&& (emulate_driver.uc_acquire_address == 3)
					&& ((status & TWIHS_SR_SVREAD) == TWIHS_SR_SVREAD)
					&& ((status & TWIHS_SR_NACK) == 0)) {
				/* Write one byte of data from slave to master device */
				twihs_write_byte(BOARD_BASE_TWIHS_SLAVE,
						emulate_driver.uc_memory[emulate_driver.us_page_address
						+ emulate_driver.us_offset_memory]);
				emulate_driver.us_offset_memory++;
			}
		}
	}
}