コード例 #1
0
xNetworkBufferDescriptor_t *pxNetworkBufferGetFromISR( size_t xRequestedSizeBytes )
{
    xNetworkBufferDescriptor_t *pxReturn = NULL;
    UBaseType_t uxSavedInterruptStatus;

    /*_RB_ The current implementation only has a single size memory block, so
    the requested size parameter is not used (yet). */
    ( void ) xRequestedSizeBytes;

    /* If there is a semaphore available then there is a buffer available, but,
    as this is called from an interrupt, only take a buffer if there are at
    least ipINTERRUPT_BUFFER_GET_THRESHOLD buffers remaining.  This prevents,
    to a certain degree at least, a rapidly executing interrupt exhausting
    buffer and in so doing preventing tasks from continuing. */
    if( uxQueueMessagesWaitingFromISR( ( xQueueHandle ) xNetworkBufferSemaphore ) > ipINTERRUPT_BUFFER_GET_THRESHOLD ) {
        if( xSemaphoreTakeFromISR( xNetworkBufferSemaphore, NULL ) == pdPASS ) {
            /* Protect the structure as it is accessed from tasks and interrupts. */
            uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
            {
                pxReturn = ( xNetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
                uxListRemove( &( pxReturn->xBufferListItem ) );
            }
            portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );

            iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR( pxReturn );
        }
    }

    if( pxReturn == NULL ) {
        iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR();
    }

    return pxReturn;
}
コード例 #2
0
ファイル: cmsis_os.c プロジェクト: Casa2011/devices
/**
* @brief Wait until a Semaphore token becomes available
* @param  semaphore_id  semaphore object referenced with \ref osSemaphore.
* @param  millisec      timeout value or 0 in case of no time-out.
* @retval  number of available tokens, or -1 in case of incorrect parameters.
* @note   MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
*/
int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec)
{
  TickType_t ticks;
  portBASE_TYPE taskWoken = pdFALSE;  
  
  
  if (semaphore_id == NULL) {
    return osErrorParameter;
  }
  
  ticks = 0;
  if (millisec == osWaitForever) {
    ticks = portMAX_DELAY;
  }
  else if (millisec != 0) {
    ticks = millisec / portTICK_PERIOD_MS;
    if (ticks == 0) {
      ticks = 1;
    }
  }
  
  if (inHandlerMode()) {
    if (xSemaphoreTakeFromISR(semaphore_id, &taskWoken) != pdTRUE) {
      return osErrorOS;
    }
	portEND_SWITCHING_ISR(taskWoken);
  }  
  else if (xSemaphoreTake(semaphore_id, ticks) != pdTRUE) {
    return osErrorOS;
  }
  
  return osOK;
}
コード例 #3
0
ファイル: pios_semaphore.c プロジェクト: CheBuzz/TauLabs
/**
 *
 * @brief   Takes binary semaphore from ISR context.
 *
 * @param[in] sema         pointer to instance of @p struct pios_semaphore
 * @param[out] woken       pointer to bool which will be set true if a context switch is required
 *
 * @returns true on success or false on timeout or failure
 *
 */
bool PIOS_Semaphore_Take_FromISR(struct pios_semaphore *sema, bool *woken)
{
	PIOS_Assert(sema != NULL);

#if defined(PIOS_INCLUDE_FREERTOS)
	PIOS_Assert(woken != NULL);

	signed portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

	bool result = xSemaphoreTakeFromISR(sema->sema_handle, &xHigherPriorityTaskWoken) == pdTRUE;

	*woken = *woken || xHigherPriorityTaskWoken == pdTRUE;

	return result;
#else
	bool result = true;

	PIOS_IRQ_Disable();

	if (sema->sema_count != 0)
		--sema->sema_count;
	else
		result = false;

	PIOS_IRQ_Enable();

	return result;
#endif
}
コード例 #4
0
ファイル: equistack.c プロジェクト: BrownCubeSat/EQUiSat
// guts of equistack_Push, with ISR option
// exactly the same as equistack_Stage_helper but calls equistack_Push_Unsafe
static void* equistack_Push_helper(equistack* S, void* data, bool from_isr) 
{
	void *staged_pointer = NULL;
	bool got_mutex;
	// take mutex using appropriate function
	if (from_isr) {
		got_mutex = xSemaphoreTakeFromISR(S->mutex, NULL);
	} else {
		got_mutex = xSemaphoreTake(S->mutex, (TickType_t) EQUISTACK_MUTEX_WAIT_TIME_TICKS);
	}
	
	if (got_mutex) {
		// actually get staged pointer with normal function
		staged_pointer = equistack_Push_Unsafe(S, data);
		
		// give mutex using appropriate function
		if (from_isr) {
			xSemaphoreGiveFromISR(S->mutex, NULL);
		} else {
			xSemaphoreGive(S->mutex);
		}
	}
	else
	{
		// log error if mutex can't be obtained, and give pointer to previously staged
		// struct (the one currently at the top index)
		log_error(ELOC_EQUISTACK_PUT, ECODE_EQUISTACK_MUTEX_TIMEOUT, false);
		staged_pointer = ((uint8_t*) S->data) + (S->data_size)*((S->top_index + 1) % S->max_size);
	}
	return staged_pointer;
}
コード例 #5
0
ファイル: i2c2.c プロジェクト: hampussandberg/HexConnect
/**
 * @brief	Transmits data as a master to a slave, used in ISR
 * @param	DevAddress: Address for the slave device
 * @param	Data: Pointer to a buffer where data will be stored
 * @param	Size: Size of the amount of data to receive
 * @retval	None
 */
void I2C2_ReceiveFromISR(uint8_t DevAddress, uint8_t* pBuffer, uint16_t Size)
{
	/* Try to take the semaphore in case some other process is using the device */
	if (xSemaphoreTakeFromISR(xSemaphore, NULL) == pdTRUE)
	{
		HAL_I2C_Master_Receive(&I2C_Handle, (uint16_t)(DevAddress << 1), pBuffer, Size, 500); /* TODO: Check timeout value */
		xSemaphoreGiveFromISR(xSemaphore, NULL);
	}
}
コード例 #6
0
void ADCIntHandler(void) {
    while(!ADCIntStatus(MODULE_ADC_BASE, MODULE_ADC_SEQUENCE_NUM, false));
    ADCIntClear(MODULE_ADC_BASE, MODULE_ADC_SEQUENCE_NUM);

    xSemaphoreTakeFromISR(adc_mutex, pdFALSE);
    ADCSequenceDataGet(MODULE_ADC_BASE, MODULE_ADC_SEQUENCE_NUM, adc_vals);
    xSemaphoreGiveFromISR(adc_mutex, pdTRUE);

    ADCProcessorTrigger(MODULE_ADC_BASE, MODULE_ADC_SEQUENCE_NUM);
}
コード例 #7
0
ファイル: spi_flash.c プロジェクト: efimefimefim/HexConnect
/**
  * @brief  Write one byte to the FLASH. Can be called from an ISR
  * @note   Addresses to be written must be in the erased state
  * @param  WriteAddress: FLASH's internal address to write to.
  * @param  Byte: the data to be written.
  * @retval None
  */
void SPI_FLASH_WriteByteFromISR(uint32_t WriteAddress, uint8_t Byte)
{
	/* Try to take the semaphore in case some other process is using the device */
	if (xSemaphoreTakeFromISR(xSemaphore, NULL) == pdTRUE)
	{
		prvSPI_FLASH_WriteByte(WriteAddress, Byte);

		/* Give back the semaphore */
		xSemaphoreGiveFromISR(xSemaphore, NULL);
	}
}
コード例 #8
0
ファイル: msg.c プロジェクト: danielchen76/TankController
void FreeMsgFromISR(Msg* pMsg, portBASE_TYPE* pWoken)
{
	assert_param(pMsg);
	// Lock
	xSemaphoreTakeFromISR(s_ArrayMutex, pWoken);

	pMsg->Id = MSG_UNUSED;
	s_MsgNumber--;

	// Unlock
	xSemaphoreGiveFromISR(s_ArrayMutex, pWoken);
}
コード例 #9
0
/*****************************************************************************
 Prototype    : DMA1_Channel3_IRQHandler
 Description  : uart3 DMA-Rx handler
 Input        : void  
 Output       : None
 Return Value : 
 Calls        : 
 Called By    : 
 
  History        :
  1.Date         : 2015/9/7
    Author       : qiuweibo
    Modification : Created function

*****************************************************************************/
void DMA1_Channel3_IRQHandler(void)
{
    BaseType_t xHigherPriorityTaskWoken, xResult;

    // xHigherPriorityTaskWoken must be initialised to pdFALSE.
    xHigherPriorityTaskWoken = pdFALSE;

    DMA_ClearITPendingBit(DMA1_IT_TC3); 
    DMA_Cmd(DMA1_Channel3, DISABLE);            //close DMA incase receive data while handling

    if( pdTRUE != xSemaphoreTakeFromISR( xSerialRxHandleLock, &xHigherPriorityTaskWoken))
    {
        return;
    }

    if (uart3_rx_dma_buf.IdleBufferIndex) //buf1 busy, buf2 idle
    {
        //buffer1 finished recevied mission (full), switch to buffer2
        uart3_rx_dma_buf.nBuff1Offset = uart3_rx_dma_buf.nBuff1MaxLength;
        
        DMA1_Channel3->CMAR = (uint32_t)uart3_rx_dma_buf.pPingPongBuff2;
        DMA1_Channel3->CNDTR = uart3_rx_dma_buf.nBuff2MaxLength;
        uart3_rx_dma_buf.IdleBufferIndex = 0;
    }
    else //buf2 busy, buf1 idle
    {
        //buffer2 finished recevied mission (full), switch to buffer1
        uart3_rx_dma_buf.nBuff2Offset = uart3_rx_dma_buf.nBuff2MaxLength;
        
        DMA1_Channel3->CMAR = (uint32_t)uart3_rx_dma_buf.pPingPongBuff1;
        DMA1_Channel3->CNDTR = uart3_rx_dma_buf.nBuff1MaxLength;
        uart3_rx_dma_buf.IdleBufferIndex = 1;
    }
    xSemaphoreGiveFromISR( xSerialRxHandleLock ,&xHigherPriorityTaskWoken);
    DMA_Cmd(DMA1_Channel3, ENABLE);             //open DMA after handled

    //boardcast message to handle
    xResult = xEventGroupSetBitsFromISR(
                    xUart3RxEventGroup,             // The event group being updated.
                    UART_DMA_RX_COMPLETE_EVENT_BIT, // The bits being set.
                    &xHigherPriorityTaskWoken );

    // Was the message posted successfully?
    if( xResult == pdPASS )
    {
        // If xHigherPriorityTaskWoken is now set to pdTRUE then a context
        // switch should be requested.  The macro used is port specific and 
        // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - 
        // refer to the documentation page for the port being used.
        portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
    }
}
コード例 #10
0
 void logFromISR(String text) {
     // ToDo: Add other debug outputs
     if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
         if (xSemaphoreTakeFromISR(serialPortMutex, NULL) == pdTRUE) {
             DEBUG_SERIAL.println(text);
             BaseType_t xHigherPriorityTaskWoken;
             xSemaphoreGiveFromISR(serialPortMutex, &xHigherPriorityTaskWoken);
             portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
         }
     } else {
         DEBUG_SERIAL.println(text);
     }
 }
コード例 #11
0
ファイル: msg.c プロジェクト: danielchen76/TankController
Msg* MallocMsgFromISR(portBASE_TYPE* pWoken)
{
	Msg*		pMsg = NULL;

	// Lock
	xSemaphoreTakeFromISR(s_ArrayMutex, pWoken);

	pMsg = GetBlankMsg();

	// Unlock
	xSemaphoreGiveFromISR(s_ArrayMutex, pWoken);

	return pMsg;
}
コード例 #12
0
ファイル: rtos_button.c プロジェクト: JonahTsai/libHemp
static void button_handler(uint32_t portId, uint32_t mask) {
	portBASE_TYPE xHigherTaskWoken = pdFALSE;
	xSemaphoreTakeFromISR(g_rtos_button_data.mutex, &xHigherTaskWoken);
	rtos_button_pio_port_t* my_port = &g_rtos_button_data.ports[portId - ID_PIOA];
	Pio* calculated_pio = (Pio*)(((uint32_t)PIOA) + PIO_DELTA * (portId - ID_PIOA));
	my_port->last_update_mask = mask;
	my_port->last_update_data = calculated_pio->PIO_PDSR;
	my_port->flags |= RTOS_BUTTON_PORT_UPDATED_MASK;

	xSemaphoreGiveFromISR(g_rtos_button_data.mutex, &xHigherTaskWoken);
	xHigherTaskWoken = pdFALSE;
	xSemaphoreGiveFromISR(g_rtos_button_data.rtos_internal_task_semaphore, &xHigherTaskWoken);

	portEND_SWITCHING_ISR(xHigherTaskWoken);
}
コード例 #13
0
void uart_rx(int length) {
    if (!sock_connected) {
        uart_rx_one_char(UART);
        return;
    }


    int i = 0;
    unsigned char c;
    bool rb_full = false;

    if (xSemaphoreTakeFromISR(ringbuf_mutex, NULL)) {
        while (ringbuf_get(&ringbuf_t, &c) == 0) {
            if (ringbuf_owr(&ringbuf_m, c)) {
                rb_full = true;
            }
        }

        for (i = 0; i < length; i++) {
            if (ringbuf_owr(&ringbuf_m, uart_rx_one_char(UART0))) {
                rb_full = true;
            }
        }
        xSemaphoreGiveFromISR(ringbuf_mutex, NULL);
    } else {
        DBG("uart_rx: failed to take semphr");

        // ringbuf is taken by send task
        // all uart data is copied in temporary ringbuffer that will be copied in main ringbuffer once it is available
        for (i = 0; i < length; i++) {
            if (ringbuf_owr(&ringbuf_t, uart_rx_one_char(UART0))) {
                rb_full = true;
            }
        }
    }

    //DBG("uart_rx: %d b", length);

    // notify send task that there is data to be sent
    xQueueSendToBackFromISR(tx_queue, &length, NULL);

    if (rb_full) {
        // not every byte could be put in one of the two ringbuffers
        // we can just print a message about it
        DBG("uart_rx: ringbuff overflow");
    }
}
コード例 #14
0
/**
  * @brief  Write one byte to the EEPROM. Can be called from an ISR
  * @param  WriteAddress: EEPROM's internal address to write to.
  * @param  Byte: the data to be written.
  * @retval None
  */
void I2C_EEPROM_WriteByteFromISR(uint32_t WriteAddress, uint8_t Byte)
{
  if (WriteAddress <= I2C_EEPROM_LAST_ADDRESS && !prvWriteProtected)
  {
    /* Try to take the semaphore in case some other process is using the device */
    if (xSemaphoreTakeFromISR(xSemaphore, NULL) == pdTRUE)
    {
      /* Wait until some time has passed since the last write */
      vTaskDelayUntil(&xNextWriteTime, I2C_EEPROM_MS_BETWEEN_WRITES / portTICK_PERIOD_MS);

      /* Transmit the address + data byte*/
      uint8_t tempData[3] = {(WriteAddress >> 8) & 0x7F, WriteAddress & 0xFF, Byte};
      I2C3_Transmit(I2C_EEPROM_BUS_ADDRESS, tempData, 3);

      /* Give back the semaphore */
      xSemaphoreGive(xSemaphore);
    }
  }
}
コード例 #15
0
/** Lock a mutex
 * @param mutex the mutex to lock */
void sys_mutex_lock( sys_mutex_t *pxMutex )
{
BaseType_t xGotSemaphore;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;

	if( xInsideISR == 0 )
	{
		while( xSemaphoreTake( *pxMutex, portMAX_DELAY ) != pdPASS );
	}
	else
	{
		xGotSemaphore = xSemaphoreTakeFromISR( *pxMutex, &xHigherPriorityTaskWoken );
		configASSERT( xGotSemaphore );
		portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

		/* Prevent compiler warnings if configASSERT() is not defined. */
		( void ) xGotSemaphore;
	}
}
コード例 #16
0
ファイル: i2c_base.cpp プロジェクト: BrzTit/Tricopter-4
bool I2C_Base::transfer(char deviceAddress, char firstReg, char* pData, unsigned int transferSize)
{
    bool status = false;
    if(mDisableOperation || !pData) {
        return status;
    }

    // If scheduler not running, perform polling transaction
    if(taskSCHEDULER_RUNNING != xTaskGetSchedulerState())
    {
        i2cKickOffTransfer(deviceAddress, firstReg, pData, transferSize);

        // Wait for transfer to finish
        const uint64_t timeout = sys_get_uptime_ms() + I2C_TIMEOUT_MS;
        while (!xSemaphoreTakeFromISR(mTransferCompleteSignal, NULL)) {
            if (sys_get_uptime_ms() > timeout) {
                break;
            }
        }

        status = (0 == mTransaction.error);
    }
    else if (xSemaphoreTake(mI2CMutex, OS_MS(I2C_TIMEOUT_MS)))
    {
        // Clear potential stale signal and start the transfer
        xSemaphoreTake(mTransferCompleteSignal, 0);
        i2cKickOffTransfer(deviceAddress, firstReg, pData, transferSize);

        // Wait for transfer to finish and copy the data if it was read mode
        if (xSemaphoreTake(mTransferCompleteSignal, OS_MS(I2C_TIMEOUT_MS))) {
            status = (0 == mTransaction.error);
        }

        xSemaphoreGive(mI2CMutex);
    }

    return status;
}
コード例 #17
0
 bool MTD_FLASHMEM Mutex::lockFromISR()
 {
     signed portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
     return xSemaphoreTakeFromISR(m_handle, &xHigherPriorityTaskWoken);
 }
コード例 #18
0
ファイル: wifi_os_adapter.c プロジェクト: A-Paul/RIOT
static int32_t IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw)
{
    return (int32_t)xSemaphoreTakeFromISR(semphr, hptw);
}
コード例 #19
0
/*****************************************************************************
 Prototype    : DMA1_Channel2_IRQHandler
 Description  : uart3 DMA-Tx Handler
 Input        : void  
 Output       : None
 Return Value : 
 Calls        : 
 Called By    : 
 
  History        :
  1.Date         : 2015/9/7
    Author       : qiuweibo
    Modification : Created function

*****************************************************************************/
void DMA1_Channel2_IRQHandler(void)
{
    BaseType_t xHigherPriorityTaskWoken, xResult;

    // xHigherPriorityTaskWoken must be initialised to pdFALSE.
    xHigherPriorityTaskWoken = pdFALSE;

    DMA_ClearITPendingBit(DMA1_IT_TC2);
    DMA_Cmd(DMA1_Channel2, DISABLE);    // close DMA
    
    xResult = xSemaphoreTakeFromISR( xSerialTxHandleLock, &xHigherPriorityTaskWoken);
    if( pdTRUE != xResult)
    {
        return;
    }

    //After finish this send mission, need to do: clear status --> check next mission
    if (uart3_tx_dma_buf.IdleBufferIndex)
    {
        // reset buffer1
        uart3_tx_dma_buf.nBuff1Offset = 0;

        // check for buffer2
        if (uart3_tx_dma_buf.nBuff2Offset > 0)
        {
            DMA1_Channel2->CMAR = (uint32_t)uart3_tx_dma_buf.pPingPongBuff2;
            DMA1_Channel2->CNDTR = uart3_tx_dma_buf.nBuff2Offset;
            uart3_tx_dma_buf.IdleBufferIndex = 0;
            DMA_Cmd(DMA1_Channel2, ENABLE); // open DMA
        }
        else
        {
            uart3_tx_dma_buf.IsDMAWroking = 0;
        }
    }
    else
    {
        //reset buffer2
        uart3_tx_dma_buf.nBuff2Offset = 0;
        
        // check for buffer1
        if (uart3_tx_dma_buf.nBuff1Offset > 0)
        {
            DMA1_Channel2->CMAR = (uint32_t)uart3_tx_dma_buf.pPingPongBuff1;
            DMA1_Channel2->CNDTR = uart3_tx_dma_buf.nBuff1Offset;
            uart3_tx_dma_buf.IdleBufferIndex = 1;
            DMA_Cmd(DMA1_Channel2, ENABLE); // open DMA
        }
        else
        {
            uart3_tx_dma_buf.IsDMAWroking = 0;
        }
    }
    
    xResult = xSemaphoreGiveFromISR( xSerialTxHandleLock , &xHigherPriorityTaskWoken);
    if( xResult == pdPASS )
    {
        // If xHigherPriorityTaskWoken is now set to pdTRUE then a context
        // switch should be requested.  The macro used is port specific and 
        // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - 
        // refer to the documentation page for the port being used.
        portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
    }
}
コード例 #20
0
void USART3_IRQHandler(void)
{
    volatile u32 tem_reg;
    volatile u16 u16BufferUsedLen = 0;
    BaseType_t xHigherPriorityTaskWoken, xResult;

    // xHigherPriorityTaskWoken must be initialised to pdFALSE.
    xHigherPriorityTaskWoken = pdFALSE;
    
    // error happen
    if(USART_GetITStatus(USART3, USART_IT_PE) != RESET)
    {
        USART_ClearITPendingBit(USART3, USART_IT_PE);
        xSerialRxParityFlag = DMA_UART_PACKET_PARITY_ERR;
    }
    
    // uart idle interrupt
    if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)
    {
        USART_ClearITPendingBit(USART3, USART_IT_IDLE);
        DMA_ClearFlag(DMA1_FLAG_GL3);//clear all interrupt flags     
        DMA_Cmd(DMA1_Channel3, DISABLE); //close DMA incase receive data while handling
        
        xResult = xSemaphoreTakeFromISR( xSerialRxHandleLock, &xHigherPriorityTaskWoken);
        if( pdTRUE == xResult)
        {
            if (uart3_rx_dma_buf.IdleBufferIndex) //buf1 busy, buf2 idle
            {
                u16BufferUsedLen = uart3_rx_dma_buf.nBuff1MaxLength - DMA_GetCurrDataCounter(DMA1_Channel3); 
                if (u16BufferUsedLen > 0)
                {
                    uart3_rx_dma_buf.nBuff1Offset = u16BufferUsedLen;
                    DMA1_Channel3->CMAR = (uint32_t)uart3_rx_dma_buf.pPingPongBuff2;
                    DMA1_Channel3->CNDTR = uart3_rx_dma_buf.nBuff2MaxLength;
                    uart3_rx_dma_buf.IdleBufferIndex = 0;
                }
            }
            else
            {
                u16BufferUsedLen = uart3_rx_dma_buf.nBuff2MaxLength - DMA_GetCurrDataCounter(DMA1_Channel3); 
                if (u16BufferUsedLen > 0)
                {
                    uart3_rx_dma_buf.nBuff2Offset = u16BufferUsedLen;
                    DMA1_Channel3->CMAR = (uint32_t)uart3_rx_dma_buf.pPingPongBuff1;
                    DMA1_Channel3->CNDTR = uart3_rx_dma_buf.nBuff1MaxLength;
                    uart3_rx_dma_buf.IdleBufferIndex = 1;
                }
            }
            xResult = xSemaphoreGiveFromISR( xSerialRxHandleLock ,&xHigherPriorityTaskWoken);

            if (u16BufferUsedLen > 0)
            {
                //boardcast message to handle
                xResult = xEventGroupSetBitsFromISR(
                                xUart3RxEventGroup,	// The event group being updated.
                                UART_DMA_RX_INCOMPLETE_EVENT_BIT,// The bits being set.
                                &xHigherPriorityTaskWoken );
            } //End if u16BufferUsedLen > 0
        }// End if pdTRUE == xSemaphoreTakeFromISR
        DMA_Cmd(DMA1_Channel3, ENABLE);                 //open DMA after handled
        
        //clear Idle flag by read SR and DR
        tem_reg = USART3->SR;
        tem_reg = USART3->DR;
        tem_reg = tem_reg; // slove warning 
    }// End if USART_IT_IDLE
    
    if(USART_GetITStatus(USART3, USART_IT_FE | USART_IT_NE) != RESET)
    {
        USART_ClearITPendingBit(USART3, USART_IT_FE | USART_IT_NE);
    }

    if( xResult == pdPASS )
    {
        // If xHigherPriorityTaskWoken is now set to pdTRUE then a context
        // switch should be requested.  The macro used is port specific and 
        // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - 
        // refer to the documentation page for the port being used.
        portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
    }
}
コード例 #21
0
ファイル: tm_stick.c プロジェクト: dorght/libHemp
static void configure_time_trigger_for_ssc(uint32_t ssc_trigger_hz)
{
	
#if 0
	gpio_configure_pin(PIO_PA12_IDX, PIO_PERIPH_B);
	pmc_enable_periph_clk(ID_PWM);

	/* Disable PWM channels */
	pwm_channel_disable(PWM, PWM_CHANNEL_1);

	/* Set PWM clock A as PWM_FREQUENCY*PERIOD_VALUE (clock B is not used) */
	pwm_clock_t clock_setting = {
		.ul_clka = 1000 * 100,
		.ul_clkb = 0,
		.ul_mck = sysclk_get_cpu_hz()
	};
	pwm_init(PWM, &clock_setting);
	
	pwm_channel_t g_pwm_channel;

	/* Period is left-aligned */
	g_pwm_channel.alignment = PWM_ALIGN_LEFT;
	/* Output waveform starts at a low level */
	g_pwm_channel.polarity = PWM_LOW;
	/* Use PWM clock A as source clock */
	g_pwm_channel.ul_prescaler = PWM_CMR_CPRE_CLKA;
	/* Period value of output waveform */
	g_pwm_channel.ul_period = 100;
	/* Duty cycle value of output waveform */
	g_pwm_channel.ul_duty = 50;
	g_pwm_channel.channel = PWM_CHANNEL_1;
	pwm_channel_init(PWM, &g_pwm_channel);
	
	/* Disable channel counter event interrupt */
	pwm_channel_disable_interrupt(PWM, PWM_CHANNEL_1, 0);
	
	pwm_channel_enable(PWM, PWM_CHANNEL_1);
#endif


	
	uint32_t ul_div = 0;
	uint32_t ul_tc_clks = 0;
	uint32_t ul_sysclk = sysclk_get_cpu_hz();

	pmc_set_writeprotect(false);

	// Enable peripheral clock.
	pmc_enable_periph_clk(CONF_SSC_CLOCK_SOURCE_ID);

	// TIOA configuration 
	// gpio_configure_pin(PIN_TC0_TIOA0, PIN_TC0_TIOA0_FLAGS);
	// tc_set_writeprotect(TC2, true);
	tc_set_writeprotect(CONF_SSC_CLOCK_TC, false);

	// Configure TC for a 1Hz frequency and trigger on RC compare.
	tc_find_mck_divisor(ssc_trigger_hz, ul_sysclk, &ul_div, &ul_tc_clks, ul_sysclk);
	tc_init(CONF_SSC_CLOCK_TC, CONF_SSC_CLOCK_CHANNEL, ul_tc_clks | TC_CMR_WAVSEL_UP_RC | TC_CMR_WAVE | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET);
	uint32_t tmp_val = (ul_sysclk / ul_div) / ssc_trigger_hz;
	
	tc_write_ra(CONF_SSC_CLOCK_TC, CONF_SSC_CLOCK_CHANNEL, tmp_val / 2);
	tc_write_rc(CONF_SSC_CLOCK_TC, CONF_SSC_CLOCK_CHANNEL, tmp_val);

	// Start the Timer.
	tc_start(CONF_SSC_CLOCK_TC, CONF_SSC_CLOCK_CHANNEL);

}

void tm_stick_init(uint32_t bus_speed_hz) {
	if(g_tm_stick_data.mutex == NULL) {
		g_tm_stick_data.mutex =  xSemaphoreCreateMutex();
	}
	
	if(g_tm_stick_data.rtos_task_semaphore == NULL) {
		vSemaphoreCreateBinary(g_tm_stick_data.rtos_task_semaphore);
	}
	
	configure_time_trigger_for_ssc(1000);
	
	sysclk_enable_peripheral_clock(ID_SSC);
	ssc_reset(SSC);
	// Do not go over 1MHz, the pulse will be too long and extend over to the next clock's rising edge (The spec. sheet of 4021BCM does not really list the operation times of 3.3V operation.
	// I tested a couple of speeds.... at 1.25MHz, I found that it sometimes misses some pulses.
	if(bus_speed_hz > TM_STICK_MAX_BUS_SPEED){
		bus_speed_hz = TM_STICK_MAX_BUS_SPEED;
	}
	ssc_set_clock_divider(SSC, bus_speed_hz, sysclk_get_cpu_hz()); 
	clock_opt_t rx_clk_opt = {
		.ul_cks = SSC_RCMR_CKS_MCK,
		.ul_cko = SSC_RCMR_CKO_TRANSFER,
// TODO: Fix the SSC clock for some reason shift 1/2 clock pulse position.
// This makes the button results shift one position to the right. So we have to change rising/falling edge to "correct" it (oh, well, "hack" around it).
// Don't know why.
// One possible patch up is to use a pin to signal which one is desired to determine which of the following settings to use..
#if defined(CONF_BOARD_ARDUINO_DUE) 
		.ul_cki = 0, //SSC_RCMR_CKI,
#else
		.ul_cki = SSC_RCMR_CKI,
#endif
		.ul_ckg = SSC_RCMR_CKG_CONTINUOUS,
		.ul_start_sel = SSC_RCMR_START_RF_FALLING,
		.ul_period = 0,
		.ul_sttdly = 0
	};
	
	data_frame_opt_t rx_data_frame_opt = {
		.ul_datlen = 23,
		.ul_msbf = 0,  //SSC_RFMR_MSBF,
		.ul_fsos = SSC_RFMR_FSOS_NONE,
		.ul_datnb = 0,
		.ul_fsedge = SSC_RFMR_FSEDGE_NEGATIVE,
		.ul_fslen = 0,
		.ul_fslen_ext = 0
	};
	
	ssc_set_receiver(SSC, &rx_clk_opt, &rx_data_frame_opt);
	ssc_enable_interrupt(SSC, SSC_IER_RXRDY);
	
	// It is VERY IMPORTANT to set the priority of the interrupt to conform to what FreeRTOS needs because we are calling FreeRTOS interrupt-safe APIs (those *FromISR) from within interrupt handlers.
	// If we don't do this, if would work at the beginning, and then eventually the whole thing will come crashing down.
	// And it's not gonna crash even after millions of interrupts are handled. It will come crashing down in some very weird place after you start using another interrupt handler, like the pio handlers, and only after some handlling...
	// And, it will appear random. You press the button a couple of times, it dies. Then, at other times, you press and hold the button, etc. etc. Each time will be different.
	// You would be suspecting your stack overflowed, your code does a wild pointer, etc. etc. It's very difficult to debug. Trust me, you don't wanna go there.
	NVIC_ClearPendingIRQ(SSC_IRQn);
	NVIC_SetPriority(SSC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
	
	NVIC_EnableIRQ(SSC_IRQn); 
	
	ssc_enable_rx(SSC);
}

void SSC_Handler( void ) {	
	portBASE_TYPE xHigherTaskWoken = pdFALSE;
	uint32_t* in_data_buf = (uint32_t*)g_tm_stick_data.data;
	uint32_t in_data = 0;
	static uint32_t previous_in_data = 0;
	static bool is_first_time = true;
	// calculate the mask needed to wipe off extra high bit junk.
	static uint32_t mask = 0xFFFFFFFF;
	if(is_first_time) {
		for(int i = 4; i > TM_STICK_NUM_DATA_BYTES; i--) {
			mask = mask >> 8;
		}
	}

	if(ssc_is_rx_ready(SSC) == SSC_RC_YES) {
		xSemaphoreTakeFromISR(g_tm_stick_data.mutex, &xHigherTaskWoken);
		in_data = SSC->SSC_RHR;
		// in_data >>= 1; // No idea why it always reads 25bits (one too many bit at the end LSB), instead of 24 I told it to. Therefore, we shift it off.
		in_data = ~in_data; // reverse it. So, now 1 is on, 0 is off.
		in_data &= mask;
		
		// Glitch filtering below.
		if(is_first_time
			||  (previous_in_data ^ in_data) == 0) {
			is_first_time = false;
			*in_data_buf = in_data;
		}
		previous_in_data = in_data;
		xSemaphoreGiveFromISR(g_tm_stick_data.mutex, &xHigherTaskWoken);
	
		xHigherTaskWoken = pdFALSE;
		xSemaphoreGiveFromISR(g_tm_stick_data.rtos_task_semaphore, &xHigherTaskWoken); // if there is an RTOS waiting for the ADC task mutex, wake it up.
		portEND_SWITCHING_ISR(xHigherTaskWoken);
	}
}

#ifdef __cplusplus
}