1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-29 07:24:13 +01:00

Added beginnings to POIS_PWM for RC Input.

Enabled ADC, needs reworking still.

git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@139 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
gussy 2010-01-25 15:23:55 +00:00 committed by gussy
parent c1ab22f595
commit b2c23c5473
10 changed files with 316 additions and 89 deletions

View File

@ -96,6 +96,7 @@ SRC += $(PIOSSTM32F10X)/pios_adc.c
SRC += $(PIOSSTM32F10X)/pios_servo.c
SRC += $(PIOSSTM32F10X)/pios_i2c.c
SRC += $(PIOSSTM32F10X)/pios_spi.c
SRC += $(PIOSSTM32F10X)/pios_pwm.c
## PIOS Hardware (Common)
SRC += $(PIOSCOMMON)/pios_sdcard.c

View File

@ -216,7 +216,7 @@ int32_t PIOS_COM_SendFormattedString(COMPortTypeDef port, char *format, ...)
/**
* Checks for incoming COM messages, calls the callback function which has
* been installed via COMReceiveCallbackInit()
* been installed via PIOS_COM_ReceiveCallbackInit()
*
* Not for use in an application - this function is called by
* by a task in the programming model!

View File

@ -231,7 +231,7 @@ int32_t PIOS_SDCARD_PowerOff(void)
* // If multiple tasks are accessing the SD card, add a semaphore/mutex
* // to avoid IO access collisions with other tasks!
* u8 sdcard_available;
* int32_t SEQ_FILE_CheckSDCard(void)
* int32_t CheckSDCard(void)
* {
* // check if SD card is available
* // High speed access if the card was previously available

View File

@ -36,6 +36,7 @@ static uint16_t adc_conversion_values[NUM_ADC_PINS] __attribute__((aligned(4)));
static uint16_t adc_conversion_values_sum[NUM_ADC_PINS] __attribute__((aligned(4)));
static uint16_t adc_pin_values[NUM_ADC_PINS];
static uint32_t adc_pin_changed[NUM_ADC_PINS];
/**
@ -53,6 +54,9 @@ void PIOS_ADC_Init(void)
for(i=0; i < NUM_ADC_PINS; ++i) {
adc_pin_values[i] = 0;
}
for(i=0; i < NUM_ADC_PINS; ++i) {
adc_pin_changed[i] = 1;
}
/* Setup analog pins */
GPIO_InitTypeDef GPIO_InitStructure;
@ -64,16 +68,16 @@ void PIOS_ADC_Init(void)
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Enable ADC1/2 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2, ENABLE);
/* Map channels to conversion slots depending on the channel selection mask */
/* Distribute this over the three ADCs, so that channels can be converted in parallel */
/* Sample time: */
/* With an ADCCLK = 14 MHz and a sampling time of 293.5 cycles: */
/* Tconv = 239.5 + 12.5 = 252 cycles = 18µs */
/* To be pedantic, we take A and B simulataneously, and Z and Temp simulataneously */
/* To be pedantic, we take A and B simultaneously, and Z and Temp simultaneously */
ADC_RegularChannelConfig(ADC1, ADC_A_CHANNEL, 1, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 2, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 2, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC2, ADC_B_CHANNEL, 1, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC2, ADC_Z_CHANNEL, 2, ADC_SampleTime_239Cycles5);
@ -110,17 +114,17 @@ void PIOS_ADC_Init(void)
ADC_StartCalibration(ADC2);
while(ADC_GetCalibrationStatus(ADC2));
// enable DMA1 clock
/* Enable DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// configure DMA1 channel 1 to fetch data from ADC result register
/* Configure DMA1 channel 1 to fetch data from ADC result register */
DMA_InitTypeDef DMA_InitStructure;
DMA_StructInit(&DMA_InitStructure);
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&adc_conversion_values;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 2; /* number of conversions depends on number of used channels */
DMA_InitStructure.DMA_BufferSize = 2; /* Number of conversions depends on number of used channels */
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
@ -131,7 +135,7 @@ void PIOS_ADC_Init(void)
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
/* trigger interrupt when all conversion values have been fetched */
/* Trigger interrupt when all conversion values have been fetched */
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
/* Configure and enable DMA interrupt */
@ -150,7 +154,7 @@ void PIOS_ADC_Init(void)
/**
* Returns value of an ADC Pin
* \param[in] pin number
* \return ADC pin value - resolution depends on the selected oversampling rate Set in Settings.ini
* \return ADC pin value - resolution depends on the selected oversampling rate
* \return -1 if pin doesn't exist
*/
int32_t PIOS_ADC_PinGet(uint32_t pin)
@ -192,7 +196,9 @@ int32_t PIOS_ADC_Handler(void *_callback)
/* Call application hook */
/* Note that due to dual conversion approach, we have to convert the pin number */
/* If an uneven number of channels selected */
callback(pin, pin_value);
if(adc_pin_changed[pin] == 1) {
callback(pin, pin_value);
}
}
/* Start next scan */
@ -210,24 +216,45 @@ int32_t PIOS_ADC_Handler(void *_callback)
void DMA1_Channel1_IRQHandler(void)
{
int32_t i;
uint16_t *src_ptr, *dst_ptr;
uint16_t *src_ptr, *dst_ptr, *changed_ptr;
/* Clear the pending flag(s) */
DMA_ClearFlag(DMA1_FLAG_TC1 | DMA1_FLAG_TE1 | DMA1_FLAG_HT1 | DMA1_FLAG_GL1);
/* Copy conversion values to adc_pin_values */
src_ptr = (uint16_t *)adc_conversion_values;
dst_ptr = (uint16_t *)&adc_pin_values[NUM_ADC_PINS];
// src_ptr = (uint16_t *)adc_conversion_values;
// dst_ptr = (uint16_t *)&adc_pin_values[NUM_ADC_PINS];
// changed_ptr = (uint16_t *)&adc_pin_changed[NUM_ADC_PINS];
//
// for(i = 0; i < NUM_ADC_PINS; ++i) {
// /* Takeover new value */
// if(*dst_ptr != *src_ptr) {
// *dst_ptr = *src_ptr;
// *changed_ptr = 1;
// } else {
// *changed_ptr = 0;
// }
//
// /* Switch to next results */
// ++dst_ptr;
// ++src_ptr;
// ++changed_ptr;
// }
for(i=0; i < NUM_ADC_PINS; ++i) {
src_ptr = (uint16_t *)adc_conversion_values;
for(i = 0; i < NUM_ADC_PINS; ++i) {
/* Takeover new value */
*dst_ptr = *src_ptr;
/* Switch to next results */
++dst_ptr;
if(adc_pin_values[i] != *src_ptr) {
adc_pin_values[i] = *src_ptr;
adc_pin_changed[i] = 1;
} else {
adc_pin_changed[i] = 0;
}
++src_ptr;
}
/* Request next conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
}

View File

@ -0,0 +1,116 @@
/**
******************************************************************************
*
* @file pios_pwm.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2009.
* @brief PWM Input functions
* @see The GNU Public License (GPL) Version 3
* @defgroup PIOS_PWM PWM Input Functions
* @{
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Project Includes */
#include "pios.h"
/* Local Variables */
volatile uint16_t IC3Value = 0;
volatile uint16_t DutyCycle = 0;
volatile uint32_t Frequency = 0;
/**
* Initialises all the LED's
*/
void PIOS_PWM_Init(void)
{
/* Setup RCC */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* Enable the TIM3 global Interrupt */
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* TIM3 channel 2 pin (PA.01) configuration */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//GPIO_Mode_AF_OD
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Pin = RECEIVER1_PIN;
GPIO_Init(RECEIVER1_GPIO_PORT, &GPIO_InitStructure);
/* TIM3 configuration: PWM Input mode ------------------------
The Rising edge is used as active edge,
The TIM3 CCR2 is used to compute the frequency value
The TIM3 CCR1 is used to compute the duty cycle value
------------------------------------------------------------ */
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInitStructure.TIM_Channel = RECEIVER1_CH;
TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
/* Select the TIM3 Input Trigger: TI2FP2 */
TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2);
/* Select the slave Mode: Reset Mode */
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
/* Enable the Master/Slave Mode */
TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);
/* TIM enable counter */
TIM_Cmd(TIM3, ENABLE);
/* Enable the CC3 Interrupt Request */
TIM_ITConfig(TIM3, TIM_IT_CC3, ENABLE);
}
/**
* This function handles TIM3 global interrupt request.
*/
void TIM3_IRQHandler(void)
{
/* Clear TIM3 Capture compare interrupt pending bit */
TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
/* Get the Input Capture value */
IC3Value = TIM_GetCapture3(TIM3);
// if (IC3Value != 0)
// {
// /* Duty cycle computation */
// DutyCycle = (TIM_GetCapture1(TIM3) * 100) / IC3Value;
//
// /* Frequency computation */
// Frequency = 72000000 / IC3Value;
// } else {
// DutyCycle = 0;
// Frequency = 0;
// }
}

View File

@ -58,11 +58,15 @@ void PIOS_SYS_Init(void)
/* Ensure that pull-down is active on USB detach pin */
GPIO_InitStructure.GPIO_Pin = 0xffff & ~USB_PULLUP_PIN;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = USB_PULLUP_PIN;
GPIO_Init(USB_ACC_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = USB_PULLUP_PIN;
GPIO_Init(USB_ACC_GPIO_PORT, &GPIO_InitStructure);
/* And pull-up for detect pin */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = USB_PULLUP_PIN;
GPIO_Init(USB_ACC_GPIO_PORT, &GPIO_InitStructure);
/* Initialize Basic NVIC */
NVIC_Configuration();

View File

@ -172,7 +172,7 @@
// Receiver PWM inputs
//-------------------------
#define RECEIVER1_GPIO_PORT GPIOB
#define RECEIVER1_PIN GPIO_Pin_2 // PB2
#define RECEIVER1_PIN GPIO_Pin_0 // PB0
#define RECEIVER1_TIM_PORT TIM3
#define RECEIVER1_CH TIM_Channel_3 // TIM3_CH3
#define RECEIVER2_GPIO_PORT GPIOB

View File

@ -0,0 +1,37 @@
/**
******************************************************************************
*
* @file pios_pwm.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2009.
* @brief PWM Input functions header.
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PIOS_PWM_H
#define PIOS_PWM_H
/* Global variables */
extern volatile uint16_t IC3Value;
extern volatile uint16_t DutyCycle;
extern volatile uint32_t Frequency;
/* Public Functions */
extern void PIOS_PWM_Init(void);
#endif /* PIOS_PWM_H */

View File

@ -32,18 +32,20 @@
#include <openpilot.h>
/* Task Priorities */
#define PRIORITY_TASK_HOOKS (tskIDLE_PRIORITY + 3)
/* Global Variables */
/* Local Variables */
static uint32_t ulIdleCycleCount = 0;
static uint32_t IdleTimePercent = 0;
/* Global Functions */
void vApplicationIdleHook(void);
#define STRING_MAX 1024
static uint8_t line_buffer[STRING_MAX];
static uint16_t line_ix;
/* Function Prototypes */
void TickTask(void *pvParameters);
void Flashy(void);
void SysTick_Handler(void);
static void TaskTick(void *pvParameters);
static void TaskHooks(void *pvParameters);
int32_t CONSOLE_Parse(COMPortTypeDef port, char c);
void OP_ADC_NotifyChange(uint32_t pin, uint32_t pin_value);
/**
* Main function
@ -90,7 +92,79 @@ int main()
/* Initialise servo outputs */
PIOS_Servo_Init();
/* Used to test servos, cycles all servos from one side to the other
/* Analog to digital converter initialise */
PIOS_ADC_Init();
//PIOS_PWM_Init();
PIOS_COM_ReceiveCallbackInit(CONSOLE_Parse);
/* Initialise OpenPilot application */
// OpenPilotInit();
/* Create a FreeRTOS task */
xTaskCreate(TaskTick, (signed portCHAR *)"Test", configMINIMAL_STACK_SIZE , NULL, 3, NULL);
xTaskCreate(TaskHooks, (signed portCHAR *)"Hooks", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_HOOKS, NULL);
/* Start the FreeRTOS scheduler */
vTaskStartScheduler();
/* If all is well we will never reach here as the scheduler will now be running. */
/* If we do get here, it will most likely be because we ran out of heap space. */
return 0;
}
int32_t CONSOLE_Parse(COMPortTypeDef port, char c)
{
if(c == '\r') {
/* Ignore */
} else if(c == '\n') {
PIOS_COM_SendFormattedString(GPS, "String: %s\n", line_buffer);
line_ix = 0;
} else if(line_ix < (STRING_MAX - 1)) {
line_buffer[line_ix++] = c;
line_buffer[line_ix] = 0;
}
/* No error */
return 0;
}
void OP_ADC_NotifyChange(uint32_t pin, uint32_t pin_value)
{
/* HW v1.0 GPS/IR Connector
0000000
|||||||-- 5V
||||||--- TX (RXD on FDTI)
|||||---- RX (TXD on FDTI)
||||----- ADC PIN 3 (PC0)
|||------ ADC PIN 0 (PC1)
||------- ADC PIN 1 (PC2)
|-------- GND
*/
}
void TaskTick(void *pvParameters)
{
const portTickType xDelay = 500 / portTICK_RATE_MS;
/* Setup the LEDs to Alternate */
PIOS_LED_On(LED1);
PIOS_LED_Off(LED2);
for(;;)
{
PIOS_LED_Toggle(LED1);
//PIOS_LED_Toggle(LED2);
//PIOS_DELAY_Wait_mS(250);
vTaskDelay(xDelay);
}
/*
const portTickType xDelay = 1 / portTICK_RATE_MS;
Used to test servos, cycles all servos from one side to the other
for(;;) {
for(int i = 1000; i < 2000; i++) {
PIOS_Servo_Set(0, i);
@ -101,7 +175,7 @@ int main()
PIOS_Servo_Set(5, i);
PIOS_Servo_Set(6, i);
PIOS_Servo_Set(7, i);
PIOS_DELAY_Wait_uS(500);
vTaskDelay(xDelay);
}
for(int i = 2000; i > 1000; i--) {
PIOS_Servo_Set(0, i);
@ -112,60 +186,36 @@ int main()
PIOS_Servo_Set(5, i);
PIOS_Servo_Set(6, i);
PIOS_Servo_Set(7, i);
PIOS_DELAY_Wait_uS(500);
vTaskDelay(xDelay);
}
}
}
*/
Flashy();
/* Analog to digi init */
// PIOS_ADC_Init();
/* Initialise OpenPilot application */
// OpenPilotInit();
/* Create a FreeRTOS task */
xTaskCreate(TickTask, (signed portCHAR *) "Test", configMINIMAL_STACK_SIZE , NULL, 2, NULL);
/* Start the FreeRTOS scheduler */
vTaskStartScheduler();
/* If all is well we will never reach here as the scheduler will now be running. */
/* If we do get here, it will most likely be because we ran out of heap space. */
return 0;
}
void Flashy(void)
static void TaskHooks(void *pvParameters)
{
for(;;)
{
/* Setup the LEDs to Alternate */
PIOS_LED_On(LED1);
PIOS_LED_Off(LED2);
portTickType xLastExecutionTime;
/* Infinite loop */
for(;;)
{
PIOS_LED_Toggle(LED1);
//PIOS_LED_Toggle(LED2);
PIOS_DELAY_Wait_mS(250);
}
// Initialise the xLastExecutionTime variable on task entry
xLastExecutionTime = xTaskGetTickCount();
for(;;) {
vTaskDelayUntil(&xLastExecutionTime, 1 / portTICK_RATE_MS);
/* Skip delay gap if we had to wait for more than 5 ticks to avoid */
/* unnecessary repeats until xLastExecutionTime reached xTaskGetTickCount() again */
portTickType xCurrentTickCount = xTaskGetTickCount();
if(xLastExecutionTime < (xCurrentTickCount - 5))
xLastExecutionTime = xCurrentTickCount;
/* Check for incoming COM messages */
PIOS_COM_ReceiveHandler();
/* Check for incoming ADC notifications */
PIOS_ADC_Handler(OP_ADC_NotifyChange);
}
}
void TickTask(void *pvParameters)
{
const portTickType xDelay = 10 / portTICK_RATE_MS;
for(;;)
{
PIOS_LED_Toggle(LED2);
vTaskDelay(xDelay);
}
}
/**
* Idle hook function
*/
@ -173,15 +223,6 @@ void vApplicationIdleHook(void)
{
/* Called when the scheduler has no tasks to run */
/* In here we could implement full stats for FreeRTOS
Although this would need us to enable stats in FreeRTOS
which is *very* costly. With the function below we can
either print it out or just watch the variable using JTAG */
/* This can give a basic indication of how much time the system spends in idle */
/* IdleTimePercent is the percentage of time spent in idle since the scheduler started */
/* For example a value of 75 would mean we are spending 75% of FreeRTOS Cycles in idle */
ulIdleCycleCount++;
IdleTimePercent = ((ulIdleCycleCount / xTaskGetTickCount()) * 100);
}

View File

@ -61,6 +61,7 @@
#include <pios_servo.h>
#include <pios_i2c.h>
#include <pios_spi.h>
#include <pios_pwm.h>
/* PIOS Hardware Includes (Common) */
#include <pios_settings.h>