mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
378 lines
11 KiB
C
378 lines
11 KiB
C
/* Copyright (C) 2023 Alif Semiconductor - All Rights Reserved.
|
|
* Use, distribution and modification of this code is permitted under the
|
|
* terms stated in the Alif Semiconductor Software License Agreement
|
|
*
|
|
* You should have received a copy of the Alif Semiconductor Software
|
|
* License Agreement with this file. If not, please write to:
|
|
* contact@alifsemi.com, or visit: https://alifsemi.com/license
|
|
*
|
|
*/
|
|
|
|
/**************************************************************************//**
|
|
* @file QEC_testapp.c
|
|
* @author Manoj A Murudi
|
|
* @email manoj.murudi@alifsemi.com
|
|
* @version V1.0.0
|
|
* @date 21-July-2023
|
|
* @brief FreeRTOS demo application for QEC0 channel.
|
|
* @bug None.
|
|
* @Note None
|
|
******************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include "Driver_UTIMER.h"
|
|
#include "pinconf.h"
|
|
#include "Driver_GPIO.h"
|
|
|
|
/*RTOS Includes */
|
|
#include "RTE_Components.h"
|
|
#include CMSIS_device_header
|
|
|
|
#include "FreeRTOS.h"
|
|
#include "FreeRTOSConfig.h"
|
|
#include "task.h"
|
|
#if defined(RTE_Compiler_IO_STDOUT)
|
|
#include "retarget_stdout.h"
|
|
#endif /* RTE_Compiler_IO_STDOUT */
|
|
|
|
|
|
/* GPIO related definitions */
|
|
#define GPIO1 1
|
|
#define GPIO1_PIN0 0
|
|
#define GPIO1_PIN1 1
|
|
#define GPIO1_PIN2 2
|
|
|
|
/* UTIMER0 Driver instance */
|
|
extern ARM_DRIVER_UTIMER DRIVER_UTIMER0;
|
|
ARM_DRIVER_UTIMER *ptrUTIMER = &DRIVER_UTIMER0;
|
|
|
|
/* GPIO1 Driver instance */
|
|
extern ARM_DRIVER_GPIO ARM_Driver_GPIO_(GPIO1);
|
|
ARM_DRIVER_GPIO *ptrGPIO = &ARM_Driver_GPIO_(GPIO1);
|
|
|
|
/* Thread id of thread */
|
|
TaskHandle_t qec0_xHandle;
|
|
|
|
/**
|
|
* @function int pinmux_config(void)
|
|
* @brief QEC h/w pin init using pinmux driver
|
|
* @note none
|
|
* @param none
|
|
* @retval execution status
|
|
*/
|
|
static int32_t pinmux_config(void)
|
|
{
|
|
int32_t ret;
|
|
|
|
ret = pinconf_set (PORT_8, PIN_4, PINMUX_ALTERNATE_FUNCTION_3, PADCTRL_READ_ENABLE);
|
|
if(ret != ARM_DRIVER_OK) {
|
|
printf("\r\n Error in PINMUX.\r\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = pinconf_set (PORT_8, PIN_5, PINMUX_ALTERNATE_FUNCTION_3, PADCTRL_READ_ENABLE);
|
|
if(ret != ARM_DRIVER_OK) {
|
|
printf("\r\n Error in PINMUX.\r\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = pinconf_set (PORT_8, PIN_6, PINMUX_ALTERNATE_FUNCTION_3, PADCTRL_READ_ENABLE);
|
|
if(ret != ARM_DRIVER_OK) {
|
|
printf("\r\n Error in PINMUX.\r\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @function int gpio_init(void)
|
|
* @brief GPIO initialization using gpio driver
|
|
* @note none
|
|
* @param none
|
|
* @retval execution status
|
|
*/
|
|
static int32_t gpio_init(void)
|
|
{
|
|
int32_t ret = ARM_DRIVER_OK;
|
|
|
|
/* init P1_0 as GPIO */
|
|
ret = pinconf_set (PORT_1, PIN_0, PINMUX_ALTERNATE_FUNCTION_0, 0);
|
|
if(ret != ARM_DRIVER_OK) {
|
|
printf("\r\n Error in PINMUX.\r\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = ptrGPIO->Initialize (GPIO1_PIN0, NULL);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to initialize GPIO1_PIN0 as GPIO\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = ptrGPIO->PowerControl (GPIO1_PIN0, ARM_POWER_FULL);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to Power up GPIO1_PIN0\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = ptrGPIO->SetDirection (GPIO1_PIN0, GPIO_PIN_DIRECTION_OUTPUT);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to set direction for GPIO1_PIN0\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = ptrGPIO->SetValue (GPIO1_PIN0, GPIO_PIN_OUTPUT_STATE_LOW);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to set value for GPIO1_PIN0\n");
|
|
return -1;
|
|
}
|
|
|
|
/* init P1_1 as GPIO */
|
|
ret = pinconf_set (PORT_1, PIN_1, PINMUX_ALTERNATE_FUNCTION_0, 0);
|
|
if(ret != ARM_DRIVER_OK) {
|
|
printf("\r\n Error in PINMUX.\r\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = ptrGPIO->Initialize (GPIO1_PIN1, NULL);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to initialize GPIO1_PIN1 as GPIO\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = ptrGPIO->PowerControl (GPIO1_PIN1, ARM_POWER_FULL);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to Power up GPIO1_PIN1\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = ptrGPIO->SetDirection (GPIO1_PIN1, GPIO_PIN_DIRECTION_OUTPUT);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to set direction for GPIO1_PIN1\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = ptrGPIO->SetValue (GPIO1_PIN1, GPIO_PIN_OUTPUT_STATE_LOW);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to set value for GPIO1_PIN1\n");
|
|
return -1;
|
|
}
|
|
|
|
/* init P1_2 as GPIO */
|
|
ret = pinconf_set (PORT_1, PIN_2, PINMUX_ALTERNATE_FUNCTION_0, 0);
|
|
if(ret != ARM_DRIVER_OK) {
|
|
printf("\r\n Error in PINMUX.\r\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = ptrGPIO->Initialize (GPIO1_PIN2, NULL);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to initialize GPIO1_PIN2 as GPIO\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = ptrGPIO->PowerControl (GPIO1_PIN2, ARM_POWER_FULL);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to Power up GPIO1_PIN2\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = ptrGPIO->SetDirection (GPIO1_PIN2, GPIO_PIN_DIRECTION_OUTPUT);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to set direction for GPIO1_PIN2\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = ptrGPIO->SetValue (GPIO1_PIN2, GPIO_PIN_OUTPUT_STATE_LOW);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to set value for GPIO1_PIN2\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @function void qec0_app(void *pvParameters)
|
|
* @brief QEC0 demo application
|
|
* @note none
|
|
* @param none
|
|
* @retval none
|
|
*/
|
|
static void qec0_app (void *pvParameters)
|
|
{
|
|
int32_t ret;
|
|
uint8_t channel = 12;
|
|
uint32_t init_count = 0;
|
|
|
|
ARM_UTIMER_TRIGGER_CONFIG upcount_trig = {
|
|
.triggerTarget = ARM_UTIMER_TRIGGER_UPCOUNT,
|
|
.triggerSrc = ARM_UTIMER_SRC_0,
|
|
.trigger = ARM_UTIMER_SRC0_TRIG0_RISING
|
|
};
|
|
|
|
ARM_UTIMER_TRIGGER_CONFIG downcount_trig = {
|
|
.triggerTarget = ARM_UTIMER_TRIGGER_DOWNCOUNT,
|
|
.triggerSrc = ARM_UTIMER_SRC_0,
|
|
.trigger = ARM_UTIMER_SRC0_TRIG1_RISING
|
|
};
|
|
|
|
ARM_UTIMER_TRIGGER_CONFIG clear_trig = {
|
|
.triggerTarget = ARM_UTIMER_TRIGGER_CAPTURE_A,
|
|
.triggerSrc = ARM_UTIMER_SRC_0,
|
|
.trigger = ARM_UTIMER_SRC0_TRIG2_RISING
|
|
};
|
|
|
|
/*
|
|
* utimer channel 12 is configured as QEC0.
|
|
* For testing purpose, QEC inputs are connected to gpio's. And GPIO's are toggled accordingly.
|
|
*
|
|
* H/W connection : short P1_0 and P8_4, short P1_1 and P8_5, short P1_2 and P8_6.
|
|
**/
|
|
|
|
printf("*** QEC demo application started ***\n");
|
|
|
|
ret = pinmux_config();
|
|
if (ret) {
|
|
printf("pinmux failed\n");
|
|
}
|
|
|
|
ret = gpio_init();
|
|
if (ret) {
|
|
printf("gpio init failed\n");
|
|
}
|
|
|
|
ret = ptrUTIMER->Initialize (channel, NULL);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("utimer channel %d failed initialize \n", channel);
|
|
return;
|
|
}
|
|
|
|
ret = ptrUTIMER->PowerControl (channel, ARM_POWER_FULL);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("utimer channel %d failed power up \n", channel);
|
|
goto error_qec_uninstall;
|
|
}
|
|
|
|
ret = ptrUTIMER->ConfigCounter (channel, ARM_UTIMER_MODE_TRIGGERING, ARM_UTIMER_COUNTER_TRIANGLE);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("utimer channel %d mode configuration failed \n", channel);
|
|
goto error_qec_poweroff;
|
|
}
|
|
|
|
ret = ptrUTIMER->SetCount (channel, ARM_UTIMER_CNTR, init_count);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("utimer channel %d set count failed \n", channel);
|
|
goto error_qec_poweroff;
|
|
}
|
|
|
|
ret = ptrUTIMER->ConfigTrigger (channel, &upcount_trig);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("utimer channel %d trigger configuration failed \n", channel);
|
|
goto error_qec_poweroff;
|
|
} else {
|
|
printf("utimer channel %d triggered for up count using Trig0\n", channel);
|
|
}
|
|
|
|
ret = ptrUTIMER->ConfigTrigger (channel, &downcount_trig);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("utimer channel %d trigger configuration failed \n", channel);
|
|
goto error_qec_poweroff;
|
|
} else {
|
|
printf("utimer channel %d triggered for down count using Trig1\n", channel);
|
|
}
|
|
|
|
ret = ptrUTIMER->ConfigTrigger (channel, &clear_trig);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("utimer channel %d trigger configuration failed \n", channel);
|
|
goto error_qec_poweroff;
|
|
} else {
|
|
printf("utimer channel %d triggered for counter clear using Trig3\n", channel);
|
|
}
|
|
|
|
/* Toggling gpio's connected to x for 20 times to increment cnt value for 10 times */
|
|
for(int i=0; i<20; i++)
|
|
{
|
|
ret = ptrGPIO->SetValue (GPIO1_PIN0, GPIO_PIN_OUTPUT_STATE_TOGGLE);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to set value for GPIO1_PIN0\n");
|
|
}
|
|
}
|
|
|
|
printf("counter value after counter increment : %d\n", ptrUTIMER->GetCount (channel, ARM_UTIMER_CNTR));
|
|
|
|
/* Toggling gpio's connected to x for 10 times to increment cnt value for 5 times */
|
|
for(int i=0; i<10; i++)
|
|
{
|
|
ret = ptrGPIO->SetValue (GPIO1_PIN1, GPIO_PIN_OUTPUT_STATE_TOGGLE);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to set value for GPIO1_PIN1\n");
|
|
}
|
|
}
|
|
|
|
printf("counter value after counter decrement: %d\n", ptrUTIMER->GetCount (channel, ARM_UTIMER_CNTR));
|
|
|
|
/* Making z event as high to clear count value */
|
|
ret = ptrGPIO->SetValue (GPIO1_PIN2, GPIO_PIN_OUTPUT_STATE_HIGH);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("ERROR: Failed to set value for GPIO1_PIN2\n");
|
|
}
|
|
|
|
printf("counter value after counter clear: %d\n", ptrUTIMER->GetCount (channel, ARM_UTIMER_CNTR));
|
|
|
|
ret = ptrUTIMER->Stop (channel, ARM_UTIMER_COUNTER_CLEAR);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("utimer channel %d failed to stop \n", channel);
|
|
} else {
|
|
printf("utimer channel %d :timer stopped\n", channel);
|
|
}
|
|
|
|
error_qec_poweroff:
|
|
|
|
ret = ptrUTIMER->PowerControl (channel, ARM_POWER_OFF);
|
|
if (ret != ARM_DRIVER_OK) {
|
|
printf("utimer channel %d failed power off \n", channel);
|
|
}
|
|
|
|
error_qec_uninstall:
|
|
|
|
ret = ptrUTIMER->Uninitialize (channel);
|
|
if(ret != ARM_DRIVER_OK) {
|
|
printf("utimer channel %d failed to un-initialize \n", channel);
|
|
}
|
|
|
|
printf("*** FreeRTOS demo application: QEC completed *** \r\n\n");
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Main: Initialize and start the FreeRTOS Kernel
|
|
*---------------------------------------------------------------------------*/
|
|
int main( void )
|
|
{
|
|
BaseType_t xReturned;
|
|
|
|
#if defined(RTE_Compiler_IO_STDOUT_User)
|
|
int32_t ret;
|
|
ret = stdout_init();
|
|
if(ret != ARM_DRIVER_OK)
|
|
{
|
|
while(1)
|
|
{
|
|
}
|
|
}
|
|
#endif
|
|
/* System Initialization */
|
|
SystemCoreClockUpdate();
|
|
|
|
/* Create application main thread */
|
|
xReturned = xTaskCreate (qec0_app, "qec_app", 256, NULL,configMAX_PRIORITIES-1, &qec0_xHandle);
|
|
if (xReturned != pdPASS)
|
|
{
|
|
vTaskDelete (qec0_xHandle);
|
|
return -1;
|
|
}
|
|
|
|
/* Start thread execution */
|
|
vTaskStartScheduler();
|
|
}
|