Hi!
The code had 2 task (T1 and T2), and worked fine. When I added a third task (T3), it does not run, even with highest priority. As you can see in the screen below, the task2 "moveTalon" has priority 3, and the others have max 2. The other tasks runs ok, but, "moveTalon" doesn't even launch.
There is the full code. I'm using TM4C1294XL board, with CCS V6.0.1 and the latest TI-RTOS platform.
Thanks!
/*
* main.c
*
* Created on: 23/02/2015
* Author: Hk
*/
/* ********************************************************
* ** Universidade Tecnológica Federal do Paraná - UTFPR **
* ** Departamento Acadêmico de Eletrônica **
* ** Curso de Engenharia Eletrônica **
* ** Disciplina de Sistemas Operacionais **
* ** Prof.: L. F. Copetti **
* ** Aluno: H. C. Kaiser **
* ********************************************************
*
* Este trabalho visa projetar um sistema de controle de braço robótico.
* O braço será controlado por acelerômetro e botão de ação, e atuado por servomotores.
* A programação embarcada utilizará a placa TI Tiva-C Connected Launchpad TM4C1294XL, com sistema
* operacional RTOS.
* Os códigos foram gerados no programa Code Composer Studio V6.0, com TI-RTOS instalado.
*
*/
// --------------------------------------------------------
// Inclusões das bibliotecas usadas no programa
// --------------------------------------------------------
// Bibliotecas SYS/BIOS
#include <xdc/std.h> //mandatory - have to include first, for BIOS types
#include <ti/sysbios/BIOS.h> //mandatory - if you call APIs like BIOS_start()
#include <xdc/runtime/Log.h> //needed for any Log_info() call
#include <xdc/cfg/global.h> //header file for statically defined objects/handles
// Bibliotecas TIVAWARE
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_gpio.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/adc.h"
#include "driverlib/pwm.h"
#include "driverlib/pin_map.h"
// --------------------------------------------------------
// Definições estáticas
// --------------------------------------------------------
#define PWM_FREQ 50 // Define a frequência de
// funcionamento dos servomotores
// --------------------------------------------------------
// Declaração de protótipos
// --------------------------------------------------------
void hardware_init (void);
void delay (void);
void moveTalon (void);
void moveServo (void);
void readAcc (void);
// --------------------------------------------------------
// Definição de estrutura para mailboxes
// --------------------------------------------------------
typedef struct MsgObj {
uint32_t AccX;
uint32_t AccY;
} MsgObj, *Msg;
typedef struct TalonObj {
int talonDir; // Último movimento registrado - 1 abre, -1 fecha
uint32_t talonPos; // Posição final da garra
} TalonObj, *Talon;
// --------------------------------------------------------
// Código principal
//---------------------------------------------------------
void main (void)
{
hardware_init(); // Inicialização do dispositivo
BIOS_start(); // Inicia o agendador de BIOS
}
void hardware_init (void)
{
int i;
// Variáveis para configuração do PWM
volatile uint32_t ui32SysClkFreq; // Valor retornado por SysClockFreqSet()
volatile uint32_t ui32PWMClock; // Frequência do clock do PWM
volatile uint32_t ui32Load; // Período do PWM
volatile uint32_t ui32Adjust; // Valor inicial de posição dos servos
// Mailbox para acionamento da garra
TalonObj talon;
ui32SysClkFreq = SysCtlClockFreqSet ((SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL|
SYSCTL_CFG_VCO_480), 120000000);
// Habilitação da porta P4 para acionamento da garra
SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOD);
GPIOPinTypeGPIOInput (GPIO_PORTD_BASE, GPIO_PIN_0);
GPIOPadConfigSet (GPIO_PORTD_BASE, GPIO_PIN_0, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPD);
// Habilitação do ADC
SysCtlPeripheralEnable (SYSCTL_PERIPH_ADC0);
SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOE);
// Habilitação do PWM
SysCtlPeripheralEnable (SYSCTL_PERIPH_PWM0);
SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOF);
SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOG);
// Configurações do ADC
ADCHardwareOversampleConfigure (ADC0_BASE, 64);
GPIOPinTypeADC (GPIO_PORTE_BASE, GPIO_PIN_0 | // Pino PE0
GPIO_PIN_1 | // Pino PE1
GPIO_PIN_2 ); // Pino PE2
ADCSequenceConfigure (ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);
ADCSequenceStepConfigure (ADC0_BASE, 1, 0, ADC_CTL_CH3);
ADCSequenceStepConfigure (ADC0_BASE, 1, 1, ADC_CTL_CH2);
ADCSequenceStepConfigure (ADC0_BASE, 1, 2, ADC_CTL_CH1|ADC_CTL_IE|ADC_CTL_END);
ADCSequenceEnable (ADC0_BASE, 1);
// Configurações do PWM
PWMClockSet (PWM0_BASE,PWM_SYSCLK_DIV_64); // CLK do PWM em 1.875 MHz
GPIOPinConfigure (GPIO_PF1_M0PWM1); // Direciona saida do PWM da garra
GPIOPinConfigure (GPIO_PF2_M0PWM2); // Direciona saida do PWM do pulso
GPIOPinConfigure (GPIO_PF3_M0PWM3); // Direciona saida do PWM do cotovelo superior
GPIOPinConfigure (GPIO_PG0_M0PWM4); // Direciona saida do PWM do cotovelo inferior
GPIOPinConfigure (GPIO_PG1_M0PWM5); // Direciona saida do PWM da base
GPIOPinTypePWM (GPIO_PORTF_BASE, GPIO_PIN_1 |
GPIO_PIN_2 |
GPIO_PIN_3); // Configura porta F pinos 1~3 para PWM
GPIOPinTypePWM (GPIO_PORTG_BASE, GPIO_PIN_0 |
GPIO_PIN_1); // Configura porta G pinos 0~1 para PWM
ui32PWMClock = ui32SysClkFreq / 64; // 120MHz/64
ui32Load = (ui32PWMClock / PWM_FREQ) - 1; // 1875000/55 - 1
ui32Adjust = 700; // Servos na posição central
PWMGenConfigure (PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_DBG_RUN);
PWMGenConfigure (PWM0_BASE, PWM_GEN_1, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_DBG_RUN);
PWMGenConfigure (PWM0_BASE, PWM_GEN_2, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_DBG_RUN);
PWMGenPeriodSet (PWM0_BASE, PWM_GEN_0, ui32Load);
PWMGenPeriodSet (PWM0_BASE, PWM_GEN_1, ui32Load);
PWMGenPeriodSet (PWM0_BASE, PWM_GEN_2, ui32Load);
PWMGenEnable (PWM0_BASE, PWM_GEN_0);
PWMGenEnable (PWM0_BASE, PWM_GEN_1);
PWMGenEnable (PWM0_BASE, PWM_GEN_2);
PWMPulseWidthSet (PWM0_BASE, PWM_OUT_1, ui32Adjust * ui32Load / 10000);
PWMPulseWidthSet (PWM0_BASE, PWM_OUT_2, ui32Adjust * ui32Load / 10000);
PWMPulseWidthSet (PWM0_BASE, PWM_OUT_3, ui32Adjust * ui32Load / 10000);
PWMPulseWidthSet (PWM0_BASE, PWM_OUT_4, ui32Adjust * ui32Load / 10000);
PWMPulseWidthSet (PWM0_BASE, PWM_OUT_5, ui32Adjust * ui32Load / 10000);
PWMOutputState (PWM0_BASE, PWM_OUT_1_BIT, true);
PWMOutputState (PWM0_BASE, PWM_OUT_2_BIT, true);
PWMOutputState (PWM0_BASE, PWM_OUT_3_BIT, true);
PWMOutputState (PWM0_BASE, PWM_OUT_4_BIT, true);
PWMOutputState (PWM0_BASE, PWM_OUT_5_BIT, true);
talon.talonDir = 1;
talon.talonPos = 700;
Mailbox_post (Talon_Mbx, &talon, BIOS_WAIT_FOREVER);
for (i = 0; i < 100; i++) delay();
}
void delay (void)
{
SysCtlDelay(1200000);
}
void moveTalon (void)
{
// Estático para configuração do PWM
static uint32_t ui32SysClkFreq = 120000000;
// Variáveis para controle do punho
uint32_t ui32AdjustTalon;
uint32_t ui32Load;
int talonLastDir;
uint32_t flagMove = 0;
// Mailbox para leitura do último valor da garra e direção
TalonObj talon;
ui32Load = (ui32SysClkFreq/64)/PWM_FREQ - 1;
while (1){
Mailbox_pend (Talon_Mbx, &talon, BIOS_WAIT_FOREVER);
ui32AdjustTalon = talon.talonPos;
talonLastDir = talon.talonDir;
flagMove = GPIOPinRead (GPIO_PORTD_BASE, GPIO_PIN_0);
while (GPIOPinRead (GPIO_PORTD_BASE, GPIO_PIN_0) == 1){
if (ui32AdjustTalon > 400 && ui32AdjustTalon < 850){
if (talonLastDir == 1) ui32AdjustTalon -= 5;
else ui32AdjustTalon += 5;
PWMPulseWidthSet (PWM0_BASE, PWM_OUT_1, ui32AdjustTalon * ui32Load / 10000);
delay();
}
}
if (ui32AdjustTalon <= 400) ui32AdjustTalon = 405;
if (ui32AdjustTalon >= 850) ui32AdjustTalon = 845;
if (flagMove == 1){
talonLastDir = -1*talonLastDir;
flagMove = 0;
}
talon.talonDir = talonLastDir;
talon.talonPos = ui32AdjustTalon;
Mailbox_post (Talon_Mbx, &talon, BIOS_WAIT_FOREVER);
}
}
void moveServo (void)
{
// Estático para configuração do PWM
static uint32_t ui32SysClkFreq = 120000000;
// Variáveis para controle dos servos
uint32_t ui32AdjustWrist = 640;
uint32_t ui32AdjustSupElbow;
uint32_t ui32AdjustInfElbow = 1250;
uint32_t ui32AdjustBase = 500;
uint32_t ui32Load;
// Variáveis diferenciais para controle do pulso
uint32_t ui32BasePrev;
int difBase;
// Criação da caixa de mensagens
MsgObj msg;
ui32Load = (ui32SysClkFreq/64)/PWM_FREQ - 1;
while (1) {
// Leitura das mensagens na mailbox
Mailbox_pend (MonCtl_Mbx, &msg, BIOS_WAIT_FOREVER);
// Armazenamento de valores prévios para controle do pulso
ui32BasePrev = ui32AdjustBase;
// Carregamento dos valores
ui32AdjustBase = msg.AccX/3 + 100;
ui32AdjustInfElbow = msg.AccY/2 - 200;
// Ajuste do pulso
difBase = ui32AdjustBase - ui32BasePrev;
if (difBase > 25) ui32AdjustWrist -= 50;
else if (difBase < -25) ui32AdjustWrist += 50;
else{
if (ui32AdjustWrist > 670) ui32AdjustWrist -= 14;
if (ui32AdjustWrist > 640) ui32AdjustWrist -= 1;
if (ui32AdjustWrist < 640) ui32AdjustWrist += 1;
if (ui32AdjustWrist < 620) ui32AdjustWrist += 14;
}
// Ajuste do cotovelo superior
if (ui32AdjustInfElbow > 650) ui32AdjustSupElbow = ui32AdjustInfElbow - 400;
// Movimentação dos servos
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2, ui32AdjustWrist * ui32Load / 10000);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_3, ui32AdjustSupElbow * ui32Load / 10000);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_4, ui32AdjustInfElbow * ui32Load / 10000);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_5, ui32AdjustBase * ui32Load / 10000);
}
}
void readAcc (void)
{
// Variáveis para leitura do acelerômetro
uint32_t ui32ACCValues [4];
volatile uint32_t ui32AccX;
volatile uint32_t ui32AccY;
// Criação da caixa de mensagens
MsgObj msg;
// Leitura do ADC
while (1){
ADCIntClear(ADC0_BASE, 1);
ADCProcessorTrigger (ADC0_BASE, 1);
while(!ADCIntStatus (ADC0_BASE, 1, false)) {}
ADCSequenceDataGet (ADC0_BASE, 1, ui32ACCValues);
ui32AccX = ui32ACCValues [0];
ui32AccY = ui32ACCValues [1];
// Envio dos valores para a caixa de mensagens
msg.AccX = ui32AccX;
msg.AccY = ui32AccY;
Mailbox_post (MonCtl_Mbx, &msg, BIOS_WAIT_FOREVER);
}
}




