Hy all,
I have developed my own board based on a i.MX6 from Freescale and I want to configure the device tree.
I am using this software : Processor Expert for i.MX to generate all the pin's configurations.
The software is generating .c and .h files :
GPIO.c
I2C.c
...
iomux_config.c
iomux_config.h
...
My question is : How and where I have to implement those files in my linux kernel or in my u-boot files ? Or do I have to generate a dts file ?
Thanks in adance for your help !
EDIT :
Here is some of the generated files :
iomux_config.c :
#include "iomux_config.h"
/*
** ===================================================================
** Method : pin_init_iomux_config (component PinSettings)
*/
/*!
** #brief
** This method sets registers according routing settings. Call
** this method in user code to route desired pins into
** peripherals. The method is useful for reinitialization HW
** after some routing changes.
*/
/* ===================================================================*/
void iomux_config(void)
{
configure_audmux_pins(0u);
configure_ecspi_pins(1u);
configure_enet_pins(0u);
configure_gpio_pins(0u);
configure_gpio_pins(1u);
configure_gpio_pins(3u);
configure_gpio_pins(5u);
configure_gpio_pins(6u);
configure_i2c_pins(0u);
configure_i2c_pins(1u);
configure_i2c_pins(2u);
configure_i2c_pins(3u);
configure_ipu1_pins(0u);
configure_pwm_pins(0u);
configure_pwm_pins(1u);
configure_pwm_pins(2u);
configure_pwm_pins(3u);
configure_src_pins(0u);
configure_uart_pins(1u);
configure_uart_pins(2u);
configure_uart_pins(3u);
configure_usb_pins(0u);
configure_usdhc_pins(2u);
configure_usdhc_pins(3u);
}
/* END pin_init. */
i2c.c :
#include "iomux_config.h"
void configure_i2c_pins(uint32_t instance)
{
switch(instance) {
case HW_I2C1: /* I2C1 */
HW_IOMUXC_I2C1_SCL_IN_SELECT_INPUT_WR(IOMUXC_BASE, 0x00UL);
HW_IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA09_SET(IOMUXC_BASE, 0x04UL);
HW_IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA09_CLR(IOMUXC_BASE, 0x03UL);
HW_IOMUXC_I2C1_SDA_IN_SELECT_INPUT_WR(IOMUXC_BASE, 0x00UL);
HW_IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA08_SET(IOMUXC_BASE, 0x04UL);
HW_IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA08_CLR(IOMUXC_BASE, 0x03UL);
break;
case HW_I2C2: /* I2C2 */
HW_IOMUXC_I2C2_SCL_IN_SELECT_INPUT_WR(IOMUXC_BASE, 0x00UL);
HW_IOMUXC_SW_MUX_CTL_PAD_EIM_EB2_B_SET(IOMUXC_BASE, 0x06UL);
HW_IOMUXC_SW_MUX_CTL_PAD_EIM_EB2_B_CLR(IOMUXC_BASE, 0x09UL);
HW_IOMUXC_I2C2_SDA_IN_SELECT_INPUT_WR(IOMUXC_BASE, 0x00UL);
HW_IOMUXC_SW_MUX_CTL_PAD_EIM_DATA16_SET(IOMUXC_BASE, 0x06UL);
HW_IOMUXC_SW_MUX_CTL_PAD_EIM_DATA16_CLR(IOMUXC_BASE, 0x09UL);
break;
case HW_I2C3: /* I2C3 */
HW_IOMUXC_I2C3_SCL_IN_SELECT_INPUT_WR(IOMUXC_BASE, 0x00UL);
HW_IOMUXC_SW_MUX_CTL_PAD_EIM_DATA17_SET(IOMUXC_BASE, 0x06UL);
HW_IOMUXC_SW_MUX_CTL_PAD_EIM_DATA17_CLR(IOMUXC_BASE, 0x09UL);
HW_IOMUXC_I2C3_SDA_IN_SELECT_INPUT_WR(IOMUXC_BASE, 0x00UL);
HW_IOMUXC_SW_MUX_CTL_PAD_EIM_DATA18_SET(IOMUXC_BASE, 0x06UL);
HW_IOMUXC_SW_MUX_CTL_PAD_EIM_DATA18_CLR(IOMUXC_BASE, 0x09UL);
break;
case HW_I2C4: /* I2C4 */
HW_IOMUXC_I2C4_SCL_IN_SELECT_INPUT_WR(IOMUXC_BASE, 0x01UL);
HW_IOMUXC_SW_MUX_CTL_PAD_GPIO07_SET(IOMUXC_BASE, 0x08UL);
HW_IOMUXC_SW_MUX_CTL_PAD_GPIO07_CLR(IOMUXC_BASE, 0x07UL);
HW_IOMUXC_I2C4_SDA_IN_SELECT_INPUT_WR(IOMUXC_BASE, 0x01UL);
HW_IOMUXC_SW_MUX_CTL_PAD_GPIO08_SET(IOMUXC_BASE, 0x08UL);
HW_IOMUXC_SW_MUX_CTL_PAD_GPIO08_CLR(IOMUXC_BASE, 0x07UL);
break;
default:
break;
}
}
The others are quite identical.
Related
I want to implement a simple "GPT" timer that generates an interrupt every 1ms.
However, I get an interrupt exactly every 3ms (instead of the desired 1ms).
Where is my error? What values should I set to get a 1ms timer?
Here is my calculation for the GPT timer:
EXPLANATION OF TIMER VALUES:
We take for source clock the PLL1 DIV2 400MHz
We define the root divisor at 4 => 400MHz / 4 = 100MHz
100MHz = one increment every 10ns
We want an interrupt to be generated every 1 ms
So we have :
Output_compare_value = delay_time x GPT_frequency
Output_compare_value = 1 x 10^-3 x (1/(10 x 10^-9)) = 100000
Here is my code (I change the state of a GPIO at each interrupt to check the operation of my timer on the oscilloscope):
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_debug_console.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_gpt.h"
#include "fsl_gpio.h"
#include "fsl_common.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define GPT_IRQ_ID GPT1_IRQn
#define EXAMPLE_GPT GPT1
//#define EXAMPLE_GPT_CLK_FREQ \
// (CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / (CLOCK_GetRootPreDivider(kCLOCK_RootGpt1)) / \
// (CLOCK_GetRootPostDivider(kCLOCK_RootGpt1)) / 2) /* SYSTEM PLL1 DIV2 */
#define EXAMPLE_GPT_CLK_FREQ 100000
#define EXAMPLE_GPT_IRQHandler GPT1_IRQHandler
#define EXAMPLE_LED_GPIO GPIO3
#define EXAMPLE_LED_GPIO_PIN 23U
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
volatile bool gptIsrFlag = false;
/* The PIN status */
volatile bool g_pinSet = false;
/*******************************************************************************
* Code
******************************************************************************/
void EXAMPLE_GPT_IRQHandler(void)
{
/* Clear interrupt flag.*/
GPT_ClearStatusFlags(EXAMPLE_GPT, kGPT_OutputCompare1Flag);
gptIsrFlag = true;
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F, Cortex-M7, Cortex-M7F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U || __CORTEX_M == 7U)
__DSB();
#endif
}
/*!
* #brief Main function
*/
int main(void)
{
uint32_t gptFreq;
gpt_config_t gptConfig;
/* Define the init structure for the output LED pin*/
gpio_pin_config_t led_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
/* Board pin, clock, debug console init */
/* Board specific RDC settings */
BOARD_RdcInit();
BOARD_InitBootPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
BOARD_InitMemory();
CLOCK_SetRootMux(kCLOCK_RootGpt1, kCLOCK_GptRootmuxSysPll1Div2); /* Set GPT1 source to SYSTEM PLL1 DIV2 400MHZ */
CLOCK_SetRootDivider(kCLOCK_RootGpt1, 1U, 4U); /* Set root clock to 400MHZ / 4 = 100MHZ */
GPT_GetDefaultConfig(&gptConfig);
/* Initialize GPT module */
GPT_Init(EXAMPLE_GPT, &gptConfig);
/* Divide GPT clock source frequency by 3 inside GPT module */
GPT_SetClockDivider(EXAMPLE_GPT, 1);
/* Get GPT clock frequency */
gptFreq = EXAMPLE_GPT_CLK_FREQ;
/* GPT frequency is divided by 3 inside module */
gptFreq /= 1;
/* Set both GPT modules to 1 second duration */
GPT_SetOutputCompareValue(EXAMPLE_GPT, kGPT_OutputCompare_Channel1, gptFreq);
/* Enable GPT Output Compare1 interrupt */
GPT_EnableInterrupts(EXAMPLE_GPT, kGPT_OutputCompare1InterruptEnable);
/* Enable at the Interrupt */
EnableIRQ(GPT_IRQ_ID);
PRINTF("\r\nPress any key to start the example");
GETCHAR();
/* Init output LED GPIO. */
GPIO_PinInit(EXAMPLE_LED_GPIO, EXAMPLE_LED_GPIO_PIN, &led_config);
/* Start Timer */
PRINTF("\r\nStarting GPT timer ...");
GPT_StartTimer(EXAMPLE_GPT);
while (true)
{
/* Check whether occur interupt and toggle LED */
if (true == gptIsrFlag)
{
PRINTF("\r\n GPT interrupt is occurred !");
gptIsrFlag = false;
if (g_pinSet)
{
GPIO_PinWrite(EXAMPLE_LED_GPIO, EXAMPLE_LED_GPIO_PIN, 0U);
g_pinSet = false;
}
else
{
GPIO_PinWrite(EXAMPLE_LED_GPIO, EXAMPLE_LED_GPIO_PIN, 1U);
g_pinSet = true;
}
}
else
{
__WFI();
}
}
}
I found out what my problem was with the timer. The truth is that all my values were fine, but it was the execution of the logging that was taking time (line PRINTF("GPT interrupt is occurred !");) So I could have lowered my reload value even more, but I would still have the logging that was taking time to run.
I am designing an IIR 2nd order Lowpass filter with sampling frequency = 100Hz and cutoff frequency = 10 Hz. The filter coefficients are of Chebyshev Type I using fdatool in Matlab.
But the code is not able to filter the signal (i.e. for all frequencies it gives the output with same amplitudes as the input signal) . Only minor decrease in amplitude is observed for an input signal of 10 KHz and above. I assure you that the ADC and DAC are working fine as i have tested the for FFT filter.
Here is the code:
/* Include core modules */
#include "stm32f4xx.h"
#include "stdint.h"
#include "stdlib.h"
#include "arm_math.h"
#include "my_files.h"
#define URS 2
#define numStages 1
#define NUM_TAPS 5*numStages
#define samples 3
////////ADC FUNCTION//////////////////
void ADC_configure(void)
{
RCC->APB2ENR|=1Ul<<8; // ADC1 clock enabled
ADC1->CR2|=0x00000001; // enable ADC
ADC1->CR1|=0; // single conversion ADC1 pin 0 has been selected
}
int32_t readADC(void)
{
ADC1->CR2|=(1UL<<30);
return(ADC1->DR);
}
////////DAC FUNCTION/////////////////
int32_t dv1,dv2,ds;
//---function declaration--//
// initilising DAC---------//
void DAC_init(void)
{
RCC->APB1ENR|=1UL<<29;
DAC->CR|=((1UL<<16)|(1UL<<0));
RCC->AHB1ENR|=0x00000001; // clock to gpio A
GPIOA->MODER|=0x00000F03; // pt0,4,5 in Analog mode
}
// Sending to DAC...........//
void Send_DAC(int32_t data_in1, int32_t data_in2)
{ dv1=data_in1;
dv2=data_in2<<16;
ds=dv2+dv1;
DAC->DHR12RD=ds;
}
/* IIR settings */
float32_t pState[2*numStages];
const float pCoeffs[NUM_TAPS] = {1,2,1,-1.1997,0.5157};//{b0,b1,b2,a1,a2}
/* Global variables */
float32_t Input[samples]; /* Data to be read from ADC */
float32_t InputData[samples]; /* Data to be processed */
float32_t Output[samples]; /* Output filtered Data */
arm_biquad_cascade_df2T_instance_f32 S; /* ARM IIR module */
uint16_t i;
void TIM3_Init (void) {
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; /* enable clock for TIM1 */
TIM3->PSC = 8600; /* set prescaler = 10KHz */
TIM3->ARR = 100; /* set auto-reload = 10ms */
TIM3->RCR = 0; /* set repetition counter */
TIM3->CR1 |= (1UL << URS);
TIM3->DIER = TIM_DIER_UIE; /* Update Interrupt enable */
NVIC_EnableIRQ(TIM3_IRQn); /* TIM1 Interrupt enable */
NVIC_SetPriority (TIM3_IRQn, 0);
TIM3->CR1 |= TIM_CR1_CEN; /* timer enable */
}
void TIM3_IRQHandler() {
/*Shift Operation*/
for(i=samples-1;i>0;i--){
Input[i]= Input[i-1];
InputData[i]= Input[i];
}
/* Input part from the ADC */
Input[0] = (float32_t)readADC();
InputData[0] = Input[0];
//////////IIR//////////////////////
/* Initialize the IIR module */
arm_biquad_cascade_df2T_init_f32(&S, numStages, pCoeffs, pState);
/* Process the data through the IIR module */
arm_biquad_cascade_df2T_f32(&S, InputData, Output, samples);
////////DAC Output/////////////////
Send_DAC(Input[0], Output[0]);
}
/////////main function///////////////
int main(void) {
/* Initialize system */
SystemInit();
DAC_init();
ADC_configure();
TIM3_Init();
while (1) {
}
}
Any suggestion or solution would be of great help.
Some possible problems:
Did you enable the FPU?
Check alignment for ADC (and DAC?).
Ensure the interrupt-handler does not run too long (overflow).
Good you do not use the stdlib for much more tha init, btw. But you really should use symbolic constants for the register initialization! This does not cost extra.
Not directly related, but will(!) give wrong results: If I get it right, you trigger each conversion in readADC. This leads to jitter (resulting in noise on the digitized signal); trigger the conversations by a timer (that's what the trigger system is for actually) and use the ADC-interrupt to read the data or use a DMA (the STM DMA provides a double-buffer mode which is perfect for this). In this simple example, if using DMA, you can even get along completely without interrupt and do the calculations in the main program.
For the DAC you should the same.
Not sure why use a timer anyway; the ADC can self-trigger. Is that not sufficient?
You do not need to init IIR filter every time. Do it only once in init code. Init procedure clears previous values in pState, but they are required for IIR to perform correctly. That's the reason why your filter doesn't work. Presence of FPU only influences the speed of computation.
I am using FRDM-KL25Z arm board from freescale and I have successfully Written LED blink program using code warrior IDE. I am also able to run all the sample program from freescale start up kit.
Now I am writing A MQX Lite program to blink LED's using MQX tasks.
I made three tasks One for Initialising and 2 other for blinkin the LEDs on the board using task.
The task declaration in task_template_list.c is below
#define TASK_TEMPLATE_LIST_END {0, 0, 0, 0, 0, 0, 0}
/* MQX task template list */
const TASK_TEMPLATE_STRUCT MQX_template_list[] =
{
/* Task: InitTask */
{
/* Task number */ INITTASK_TASK,
/* Entry point */ (TASK_FPTR)InitTask,
/* Stack size */ INITTASK_TASK_STACK_SIZE,
/* Task priority */ 8U,
/* Task name */ "inittask",
/* Task attributes */ (MQX_AUTO_START_TASK),
/* Task parameter */ (uint32_t)(0)
},
/* Task: LEDTask */
{
/* Task number */ LEDTASK_TASK,
/* Entry point */ (TASK_FPTR)LEDTask,
/* Stack size */ LEDTASK_TASK_STACK_SIZE,
/* Task priority */ 10U,
/* Task name */ "ledtask",
/* Task attributes */ (0),
/* Task parameter */ (uint32_t)(0)
},
/* Task: GR_LED_ON */
{
/* Task number */ GR_LED_ON_TASK,
/* Entry point */ (TASK_FPTR)GR_LED_ON,
/* Stack size */ GR_LED_ON_TASK_STACK_SIZE,
/* Task priority */ 9U,
/* Task name */ "gr_led_on",
/* Task attributes */ (0),
/* Task parameter */ (uint32_t)(0)
},
TASK_TEMPLATE_LIST_END
};
Now in the mqx_tasks.c I have written a code like below
/* ###################################################################
** Filename : mqx_tasks.c
** Project : ProcessorExpert
** Processor : MKL25Z128VLK4
** Component : Events
** Version : Driver 01.00
** Compiler : GNU C Compiler
** Date/Time : 2013-05-27, 17:44, # CodeGen: 0
** Abstract :
** This is user's event module.
** Put your event handler code here.
** Settings :
** Contents :
** InitTask - void InitTask(uint32_t task_init_data);
**
** ###################################################################*/
/*!
** #file mqx_tasks.c
** #version 01.00
** #brief
** This is user's event module.
** Put your event handler code here.
*/
/*!
** #addtogroup mqx_tasks_module mqx_tasks module documentation
** #{
*/
/* MODULE mqx_tasks */
#include "Cpu.h"
#include "Events.h"
#include "mqx_tasks.h"
#ifdef __cplusplus
extern "C" {
#endif
/* User includes (#include below this line is not maintained by Processor Expert) */
#define RED_LED_LOC (1<<18)
#define GREEN_LED_LOC (1<<19)
#define BLUE_LED_LOC (1<<1)
#define RED_LED_OFF GPIOB_PSOR = RED_LED_LOC
#define RED_LED_ON GPIOB_PCOR = RED_LED_LOC
void Delay(int Ticks)
{
int i;
for(i=0;i<Ticks;i++)
{
}
}
/*
** ===================================================================
** Event : InitTask (module mqx_tasks)
**
** Component : Task1 [MQXLite_task]
** Description :
** MQX task routine. The routine is generated into mqx_tasks.c
** file.
** Parameters :
** NAME - DESCRIPTION
** task_init_data -
** Returns : Nothing
** ===================================================================
*/
void InitTask(uint32_t task_init_data)
{
//First order of business is to enable the Clocks to the ports!
SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTD_MASK;
//Now, setup the port mux for GPIO! See Page 163 and 183 of KL25 Sub-Family Reference Manual, Rev. 3, September 2012
PORTB_PCR18 = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
PORTB_PCR19 = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
PORTD_PCR1 = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
//Set the GPIO to outputs in the data direction register
//See Page 778 of KL25 Sub-Family Reference Manual, Rev. 3, September 2012
GPIOB_PDDR |= RED_LED_LOC | GREEN_LED_LOC;
GPIOD_PDDR |= BLUE_LED_LOC;
RED_LED_OFF;
/* _task_id task_id;
task_id=_task_create_at(0, LEDTASK_TASK, 0, LEDTask_task_stack, LEDTASK_TASK_STACK_SIZE);
if(task_id=MQX_NULL_TASK_ID){
printf("\n can not create led task");
}else{
printf("\n LED task created");
}
task_id=_task_create_at(0, GR_LED_ON_TASK, 0, GR_LED_ON_task_stack, GR_LED_ON_TASK_STACK_SIZE);
if(task_id=MQX_NULL_TASK_ID){
printf("\n can not create led task");
}else{
printf("\n LED task created");
}*/
_task_create_at(0, GR_LED_ON_TASK, 0, GR_LED_ON_task_stack, GR_LED_ON_TASK_STACK_SIZE);
_task_create_at(0, LEDTASK_TASK, 0, LEDTask_task_stack, LEDTASK_TASK_STACK_SIZE);
}
/*
** ===================================================================
** Event : LEDTask (module mqx_tasks)
**
** Component : Task2 [MQXLite_task]
** Description :
** MQX task routine. The routine is generated into mqx_tasks.c
** file.
** Parameters :
** NAME - DESCRIPTION
** task_init_data -
** Returns : Nothing
** ===================================================================
*/
void LEDTask(uint32_t task_init_data)
{
int value=0;
while(TRUE)
{
//The dedicated GPIO Set and clear registers make bit banging easier. Just write to the port what bits
//you want set or cleared. The or-ing / not-anding is done in *hardware*
//see pages 775 - 778 of KL25 Sub-Family Reference Manual, Rev. 3, September 2012
// RED_LED_OFF;
// Delay(1000000);
GPIOB_PSOR = GREEN_LED_LOC;
Delay(1000000);
GPIOD_PSOR = BLUE_LED_LOC;
Delay(1000000);
// RED_LED_ON;
// Delay(1000000);
GPIOB_PCOR = GREEN_LED_LOC;
Delay(1000000);
GPIOD_PCOR = BLUE_LED_LOC;
Delay(1000000);
value=value^1;
}
}
/*
** ===================================================================
** Event : GR_LED_ON (module mqx_tasks)
**
** Component : Task3 [MQXLite_task]
** Description :
** MQX task routine. The routine is generated into mqx_tasks.c
** file.
** Parameters :
** NAME - DESCRIPTION
** task_init_data -
** Returns : Nothing
** ===================================================================
*/
void GR_LED_ON(uint32_t task_init_data)
{
int value=0;
while(TRUE)
{
//The dedicated GPIO Set and clear registers make bit banging easier. Just write to the port what bits
//you want set or cleared. The or-ing / not-anding is done in *hardware*
//see pages 775 - 778 of KL25 Sub-Family Reference Manual, Rev. 3, September 2012
/* GPIOB_PSOR = GREEN_LED_LOC;
Delay(1000000);
GPIOD_PSOR = BLUE_LED_LOC;
Delay(1000000);*/
RED_LED_ON;
Delay(1000000);
/* GPIOB_PCOR = GREEN_LED_LOC;
Delay(1000000);
GPIOD_PCOR = BLUE_LED_LOC;
Delay(1000000);*/
RED_LED_OFF;
Delay(1000000);
value=value^1;
}
}
/* END mqx_tasks */
#ifdef __cplusplus
} /* extern "C" */
#endif
/*!
** #}
*/
/*
** ###################################################################
**
** This file was created by Processor Expert 10.2 [05.06]
** for the Freescale Kinetis series of microcontrollers.
**
** ###################################################################
*/
**
But when I debug the program I only blinks the LED of the higher priority and the other task is not working .....
Can anyone suggest me what mistake I am doing .
Thanks**
You've made a fatal mistake with your Delay() function !
What you have written in Delay() is an active loop that consumes all the CPU,
leaving no CPU time available for threads with lower priorities.
Please use _time_delay() (MQX API) instead of your Delay() function, then everything should be OK.
I am having some trouble, and I cannot tell if it's my understanding of the Atmel syntax, the Atmel Studio 6.0 or, the program itself.
I cannot seem to get the interrupt handler to receive a simple string then do something. I have success with just implimenting a single character turning an LED when USART receives one character it turns the LED on, then if it receives a different character it turns the LED off. By the way I have a design board that the program is having some trouble getting to the receive sub routine because the send code within the main is so large, so it was suggested to me to utilize interrupts to fix this.
By the way, I am trialing this program on an EVK1100 AVR32 board MCU:AT32UC3A0512-U, not sure if any of you have played with these before, but they're pretty great. Not sure I like Atmel syntax though.
Anyway, you can see I'm doing nothing in the main at the moment until I get the receive portion working.
I'm fairly new to interrupts in the Atmel world.
Any help would be much appreciated. I made just a few modifications to the built in ASF USART interrup "INTC" project example.
Thanks,
#include <string.h>
#include <avr32/io.h>
#include "compiler.h"
#include "board.h"
#include "print_funcs.h"
#include "intc.h"
#if defined (__GNUC__)
# if defined (__AVR32_AP7000__)
# include "pm_at32ap7000.h"
# else
# include "power_clocks_lib.h"
# endif
#elif defined (__ICCAVR32__) || defined (__AAVR32__)
# if defined (__AT32AP7000__)
# include "pm_at32ap7000.h"
# else
# include "power_clocks_lib.h"
# endif
#endif
#include "gpio.h"
#include "usart.h"
//#include "conf_example.h"
# define EXAMPLE_TARGET_PBACLK_FREQ_HZ FOSC0 // PBA clock target frequency, in Hz
#if BOARD == EVK1100
# define EXAMPLE_USART (&AVR32_USART1)
# define EXAMPLE_USART_RX_PIN AVR32_USART1_RXD_0_0_PIN
# define EXAMPLE_USART_RX_FUNCTION AVR32_USART1_RXD_0_0_FUNCTION
# define EXAMPLE_USART_TX_PIN AVR32_USART1_TXD_0_0_PIN
# define EXAMPLE_USART_TX_FUNCTION AVR32_USART1_TXD_0_0_FUNCTION
# define EXAMPLE_USART_CLOCK_MASK AVR32_USART1_CLK_PBA
# define EXAMPLE_PDCA_CLOCK_HSB AVR32_PDCA_CLK_HSB
# define EXAMPLE_PDCA_CLOCK_PB AVR32_PDCA_CLK_PBA
# define EXAMPLE_USART_IRQ AVR32_USART1_IRQ
# define EXAMPLE_USART_BAUDRATE 57600
#endif
/**
* \brief The USART interrupt handler.
*
* \note The `__attribute__((__interrupt__))' (under GNU GCC for AVR32) and
* `__interrupt' (under IAR Embedded Workbench for Atmel AVR32) C function
* attributes are used to manage the `rete' instruction.
*/
#if defined (__GNUC__)
__attribute__((__interrupt__))
#elif defined(__ICCAVR32__)
__interrupt
#endif
static void usart_int_handler(void)
{
static char Cmnd[30];
int index = 0;
int c;
usart_read_char(EXAMPLE_USART, &c);
Cmnd[index++] = c;
if (c = '\r')
{
Cmnd[index] = '\0';
usart_write_line(EXAMPLE_USART, Cmnd);
}
}
/**
* \brief The main function.
*
* It sets up the USART module on EXAMPLE_USART. The terminal settings are 57600
* 8N1.
* Then it sets up the interrupt handler and waits for a USART interrupt to
* trigger.
*/
int main(void)
{
static const gpio_map_t USART_GPIO_MAP =
{
{EXAMPLE_USART_RX_PIN, EXAMPLE_USART_RX_FUNCTION},
{EXAMPLE_USART_TX_PIN, EXAMPLE_USART_TX_FUNCTION}
};
// USART options.
static const usart_options_t USART_OPTIONS =
{
.baudrate = 57600,
.charlength = 8,
.paritytype = USART_NO_PARITY,
.stopbits = USART_1_STOPBIT,
.channelmode = USART_NORMAL_CHMODE
};
#if BOARD == EVK1100 || BOARD == EVK1101 || BOARD == UC3C_EK \
|| BOARD == EVK1104 || BOARD == EVK1105 || BOARD == STK600_RCUC3L0 \
|| BOARD == STK600_RCUC3D
/*
* Configure Osc0 in crystal mode (i.e. use of an external crystal
* source, with frequency FOSC0) with an appropriate startup time then
* switch the main clock source to Osc0.
*/
pcl_switch_to_osc(PCL_OSC0, FOSC0, OSC0_STARTUP);
#elif BOARD == STK1000
pm_reset();
#elif BOARD == UC3L_EK
/*
* Note: on the AT32UC3L-EK board, there is no crystal/external clock
* connected to the OSC0 pinout XIN0/XOUT0. We shall then program the
* DFLL and switch the main clock source to the DFLL.
*/
pcl_configure_clocks(&pcl_dfll_freq_param);
/*
* Note: since it is dynamically computing the appropriate field values
* of the configuration registers from the parameters structure, this
* function is not optimal in terms of code size. For a code size
* optimal solution, it is better to create a new function from
* pcl_configure_clocks_dfll0() and modify it to use preprocessor
* computation from pre-defined target frequencies.
*/
#end if
// Assign GPIO to USART.
gpio_enable_module(USART_GPIO_MAP,
sizeof(USART_GPIO_MAP) / sizeof(USART_GPIO_MAP[0]));
// Initialize USART in RS232 mode.
usart_init_rs232(EXAMPLE_USART, &USART_OPTIONS,
EXAMPLE_TARGET_PBACLK_FREQ_HZ);
print(EXAMPLE_USART, ".: Using interrupts with the USART :.\r\n\r\n");
// Disable all interrupts.
Disable_global_interrupt();
// Initialize interrupt vectors.
INTC_init_interrupts();
/*
* Register the USART interrupt handler to the interrupt controller.
* usart_int_handler is the interrupt handler to register.
* EXAMPLE_USART_IRQ is the IRQ of the interrupt handler to register.
* AVR32_INTC_INT0 is the interrupt priority level to assign to the
* group of this IRQ.
*/
INTC_register_interrupt(&usart_int_handler, EXAMPLE_USART_IRQ, AVR32_INTC_INT0);
// Enable USART Rx interrupt.
EXAMPLE_USART->ier = AVR32_USART_IER_RXRDY_MASK;
print(EXAMPLE_USART, "Type a character to use the interrupt handler."
"\r\nIt will show up on your screen.\r\n\r\n");
// Enable all interrupts.
Enable_global_interrupt();
/**
* We have nothing left to do in the main, so we may switch to a device
* sleep mode: we just need to be sure that the USART module will be
* still be active in the chosen sleep mode. The sleep mode to use is
* the FROZEN sleep mode: in this mode the PB clocks are still active
* (so the USART module which is on the Peripheral Bus will still be
* active while the CPU and HSB will be stopped).
* --
* Modules communicating with external circuits should normally be
* disabled before entering a sleep mode that will stop the module
* operation: this is not the case for the FROZEN sleep mode.
* --
* When the USART interrupt occurs, this will wake the CPU up which will
* then execute the interrupt handler code then come back to the
* while(1) loop below to execute the sleep instruction again.
*/
while(1)
{
/*
* If there is a chance that any PB write operations are
* incomplete, the CPU should perform a read operation from any
* register on the PB bus before executing the sleep
* instruction.
*/
AVR32_INTC.ipr[0]; // Dummy read
/*
* When the device wakes up due to an interrupt, once the
* interrupt has been serviced, go back into FROZEN sleep mode.
*/
}
}
Try to keep your interrupt handlers short. Interrupt handlers or ISRs are executed usually with interrupts disabled. Their goal is to get in, do something, and get out quickly. If you have other interrupts running (like a real-time clock for example), they are blocked out while you're in the ISR and that can cause problems such as lost interrupts.
The best thing to do here would be to declare the input buffer as a global static. Also define a static uchar_t have_line or similar, and in the ISR, save each character until either the buffer is full (an important check!), or you receive a CR (\r). Also check for newline (\n). Save a zero to null-terminate the buffer, and then set have_line = 1.
In your main loop, wait for have_line to be non-zero, and then process what's in the input buffer. Finally, set have_line back to zero.
That way, your ISR is brief and fairly robust.
In your sample code, does the function usart_write_line require interrupts to be enabled?
Oops! Sorry, I just noticed that your index isn't a static variable. That means it'll be initialized to zero each time the routine is called. Add a static declarator in front of int index and that should sort it out.
Hardware:
NXP M4 MKE14
Software:
MCUXpresso 10.1.1
Implementation of one software timer goes very well. When starting a second timer the microcontroller doesn't respond anymore. I get the error back "taskSCHEDULER_RUNNING". But if this not runs the system doesn't do anything.
I implemented the timers and one task like this:
/* Create the queue used by the queue send and queue receive tasks. */
xQueue = xQueueCreate(/* The number of items the queue can hold. */
mainQUEUE_LENGTH,
/* The size of each item the queue holds. */
sizeof(uint32_t));
xSensorTimer = xTimerCreate(/* A text name, purely to help
debugging. */
"SensorTimer",
/* The timer period, in this case
1000ms (1s). */
SENSOR_TIMER_PERIOD_MS,
/* This is a periodic timer, so
xAutoReload is set to pdTRUE. */
pdTRUE,
/* The ID is not used, so can be set
to anything. */
(void *)0,
/* The callback function */
vTimerCallback_SensorTimer);
if(xSensorTimer==NULL) {
for(;;); /*failure! */
}
xSUS_BUS_TIMEOUT_Timer = xTimerCreate(/* A text name, purely to help
debugging. */
"SUS_BUS_TIMEOUT_Timer",
/* The timer period, in this case
1000ms (1s). */
SUS_BUS_TIMEOUT_PERIOD_MS,
/* This is a periodic timer, so
xAutoReload is set to pdTRUE. */
pdFALSE,
/* The ID is not used, so can be set
to anything. */
(void *)1,
/* The callback function */
vTimerCallback_SUSBUSTIMEOUT);
if(xSUS_BUS_TIMEOUT_Timer==NULL) {
for(;;); /*failure! */
}
xTaskCreate(/* The function that implements the task. */
prvQueueModuleTask,
/* Text name for the task, just to help debugging. */
"Module",
/* The size (in words) of the stack that should be created
for the task. */
configMINIMAL_STACK_SIZE + 166,
/* A parameter that can be passed into the task. Not used
in this simple demo. */
NULL,
/* The priority to assign to the task. tskIDLE_PRIORITY
(which is 0) is the lowest priority. configMAX_PRIORITIES - 1
is the highest priority. */
mainQUEUE_MODULE_TASK_PRIORITY,
/* Used to obtain a handle to the created task. Not used in
this simple demo, so set to NULL. */
NULL);
/* Start the tasks and timers running. */
vTaskStartScheduler();
/* The program should never enter this while loop */
while(1)
{
;
}
}
static void vTimerCallback_SensorTimer (xTimerHandle pxTimer)
{
ReadTemperature();
ADCMeasurement();
}
static void vTimerCallback_SUSBUSTIMEOUT (xTimerHandle pxTimer)
{
//Reset the communication state back to the header state
}
Not sure what you mean by "got the error taskSCHEDULER_RUNNING back". When and how did you get that error?
With regards to the creating of timers; have you allocated enough heap for FreeRTOS (in your FreeRTOSConfig.h)?