I have the following commands
GPIO_PinOutClear(LED_PORT_E,15)
GPIO_PinModeSet(LED_PORT_A,15,gpioModePushPull,0)
GPIO_PinOutSet(LED_PORT_E,15)
I know that I should put ON value delay OFF value in a loop in order to make the LEDs blink constantly. I have tried to implement it, but it's not working.
Where did I go wrong?
#include <stdint.h>
#include <stdbool.h>
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_emu.h"
#include "bsp.h"
#include "bsp_trace.h"
#define LED_PORT_E gpioPortE
#define LED_PIN_E 15
#define LED_PORT_A gpioPortA
#define LED_PIN_A 15
volatile uint32_t msTicks; /* counts 1ms timeTicks */
void Delay(uint32_t dlyTicks);
/***************************************************************************//**
* #brief SysTick_Handler
* Interrupt Service Routine for system tick counter
******************************************************************************/
void SysTick_Handler(void)
{
msTicks++; /* increment counter necessary in Delay()*/
}
/***************************************************************************//**
* #brief Delays number of msTick Systicks (typically 1 ms)
* #param dlyTicks Number of ticks to delay
******************************************************************************/
void Delay(uint32_t dlyTicks)
{
uint32_t curTicks;
curTicks = msTicks;
while ((msTicks - curTicks) < dlyTicks) ;
}
/***************************************************************************//**
* #brief Main function
******************************************************************************/
int main(void)
{
/* Chip errata */
CHIP_Init();
CMU_ClockEnable(cmuClock_GPIO,true);
/* If first word of user data page is non-zero, enable Energy Profiler trace */
BSP_TraceProfilerSetup();
/* Setup SysTick Timer for 1 msec interrupts */
if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) {
while (1) ;
}
/* Initialize LED driver */
BSP_LedsInit();
BSP_LedSet(0);
GPIO_PinModeSet(LED_PORT_A,15,gpioModePushPull,0);
Delay(1000);
GPIO_PinModeSet(LED_PORT_E,15,gpioModePushPull,0);
while (1) {
GPIO_PinOutClear(LED_PORT_E,15);
GPIO_PinOutSet(LED_PORT_E,15);
}
}
Give delay in while loop .
while (1) {
GPIO_PinOutClear(LED_PORT_E,15);
Delay(1000);
GPIO_PinOutSet(LED_PORT_E,15);
Delay(1000);
}
If configuration of pins is ok then LEDS start blinking.
Related
I am working on trying to get the EEPROM Emulator from stm32 working. I have followed the example given for a stm32 l47x board however I am still running into issues. When I call EE_init I end up running into a stack overflow. I am not too familiar with this emulator and am using the default configurations from the example.
This is how I am initializing everything.
EE_Status ee_status = EE_OK;
/* Enable and set FLASH Interrupt priority */
/* FLASH interrupt is used for the purpose of pages clean up under interrupt */
HAL_NVIC_SetPriority(FLASH_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(FLASH_IRQn);
HAL_FLASH_Unlock();
if(__HAL_PWR_GET_FLAG(PWR_FLAG_SB) == RESET)
{
/* Blink LED_OK (Green) twice at startup */
LEDInterface_toggleColor(GREEN);
HAL_Delay(100);
LEDInterface_toggleColor(NONE);
HAL_Delay(100);
LEDInterface_toggleColor(GREEN);
HAL_Delay(100);
LEDInterface_toggleColor(NONE);
ee_status = EE_Init(EE_FORCED_ERASE);
if(ee_status != EE_OK)
{
while(1);
}
This is the eeprom_emul_conf.h settings which I also have not changed
/* Configuration of eeprom emulation in flash, can be custom */
#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
#define START_PAGE_ADDRESS 0x08100000U /*!< Start address of the 1st page in flash, for EEPROM emulation */
#else
#define START_PAGE_ADDRESS 0x08080000U /*!< Start address of the 1st page in flash, for EEPROM emulation */
#endif
#define CYCLES_NUMBER 1U /*!< Number of 10Kcycles requested, minimum 1 for 10Kcycles (default),
for instance 10 to reach 100Kcycles. This factor will increase
pages number */
#define GUARD_PAGES_NUMBER 2U /*!< Number of guard pages avoiding frequent transfers (must be multiple of 2): 0,2,4.. */
/* Configuration of crc calculation for eeprom emulation in flash */
#define CRC_POLYNOMIAL_LENGTH LL_CRC_POLYLENGTH_16B /* CRC polynomial lenght 16 bits */
#define CRC_POLYNOMIAL_VALUE 0x8005U /* Polynomial to use for CRC calculation *
/
I am running into the osal_hooks.c file where I am getting stuck in this while loop
#if defined(DOXYGEN)
void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
#else
OSAL_WEAK_FN(void, vApplicationStackOverflowHook)( TaskHandle_t xTask, char *pcTaskName )
#endif
{
volatile char * name = pcTaskName;
(void)name;
while (1)
{
;
}
}
Im sure I need to change where I allocate the memory but what is the best way to go about this. Thank you
I'm trying to program LPC824 microcontroller board ([https://www.switch-science.com/catalog/2265/][1]) with LPCOpen.
I'm using it with LPCLink 2 debugger board.
My goal is to get some information from the "pressure sensor" with an ADC.
My code stops with a HardFault when executing a NVIC_EnableIRQ function(on line: 92).
If I don't use "NVIC interrupt controller" then my code works and I can get value from sensor with ADC.
What I am doing wrong?
Here is my adc.c code:
#include "board.h"
static volatile int ticks;
static bool sequenceComplete = false;
static bool thresholdCrossed = false;
#define TICKRATE_HZ (100) /* 100 ticks per second */
#define BOARD_ADC_CH 2
/**
* #brief Handle interrupt from ADC sequencer A
* #return Nothing
*/
void ADC_SEQA_IRQHandler(void) {
uint32_t pending;
/* Get pending interrupts */
pending = Chip_ADC_GetFlags(LPC_ADC);
/* Sequence A completion interrupt */
if (pending & ADC_FLAGS_SEQA_INT_MASK) {
sequenceComplete = true;
}
/* Threshold crossing interrupt on ADC input channel */
if (pending & ADC_FLAGS_THCMP_MASK(BOARD_ADC_CH)) {
thresholdCrossed = true;
}
/* Clear any pending interrupts */
Chip_ADC_ClearFlags(LPC_ADC, pending);
}
/**
* #brief Handle interrupt from SysTick timer
* #return Nothing
*/
void SysTick_Handler(void) {
static uint32_t count;
/* Every 1/2 second */
if (count++ == TICKRATE_HZ / 2) {
count = 0;
Chip_ADC_StartSequencer(LPC_ADC, ADC_SEQA_IDX);
}
}
/**
* #brief main routine for ADC example
* #return Function should not exit
*/
int main(void) {
uint32_t rawSample;
int j;
SystemCoreClockUpdate();
Board_Init();
/* Setup ADC for 12-bit mode and normal power */
Chip_ADC_Init(LPC_ADC, 0);
Chip_ADC_Init(LPC_ADC, ADC_CR_MODE10BIT);
/* Need to do a calibration after initialization and trim */
Chip_ADC_StartCalibration(LPC_ADC);
while (!(Chip_ADC_IsCalibrationDone(LPC_ADC))) {
}
/* Setup for maximum ADC clock rate using sycnchronous clocking */
Chip_ADC_SetClockRate(LPC_ADC, ADC_MAX_SAMPLE_RATE);
Chip_ADC_SetupSequencer(LPC_ADC, ADC_SEQA_IDX,
(ADC_SEQ_CTRL_CHANSEL(BOARD_ADC_CH) | ADC_SEQ_CTRL_MODE_EOS));
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SWM);
Chip_SWM_EnableFixedPin(SWM_FIXED_ADC2);
Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SWM);
/* Setup threshold 0 low and high values to about 25% and 75% of max */
Chip_ADC_SetThrLowValue(LPC_ADC, 0, ((1 * 0xFFF) / 4));
Chip_ADC_SetThrHighValue(LPC_ADC, 0, ((3 * 0xFFF) / 4));
Chip_ADC_ClearFlags(LPC_ADC, Chip_ADC_GetFlags(LPC_ADC));
Chip_ADC_EnableInt(LPC_ADC,
(ADC_INTEN_SEQA_ENABLE | ADC_INTEN_OVRRUN_ENABLE));
Chip_ADC_SelectTH0Channels(LPC_ADC, ADC_THRSEL_CHAN_SEL_THR1(BOARD_ADC_CH));
Chip_ADC_SetThresholdInt(LPC_ADC, BOARD_ADC_CH, ADC_INTEN_THCMP_CROSSING);
/* Enable ADC NVIC interrupt */
NVIC_EnableIRQ(ADC_SEQA_IRQn);
Chip_ADC_EnableSequencer(LPC_ADC, ADC_SEQA_IDX);
SysTick_Config(SystemCoreClock / TICKRATE_HZ);
/* Endless loop */
while (1) {
/* Sleep until something happens */
__WFI();
if (thresholdCrossed) {
thresholdCrossed = false;
printf("********ADC threshold event********\r\n");
}
/* Is a conversion sequence complete? */
if (sequenceComplete) {
sequenceComplete = false;
/* Get raw sample data for channels 0-11 */
for (j = 0; j < 12; j++) {
rawSample = Chip_ADC_GetDataReg(LPC_ADC, j);
/* Show some ADC data */
if (rawSample & (ADC_DR_OVERRUN | ADC_SEQ_GDAT_DATAVALID)) {
printf("Chan: %d Val: %d\r\n", j, ADC_DR_RESULT(rawSample));
printf("Threshold range: 0x%x ",
ADC_DR_THCMPRANGE(rawSample));
printf("Threshold cross: 0x%x\r\n",
ADC_DR_THCMPCROSS(rawSample));
printf("Overrun: %s ",
(rawSample & ADC_DR_OVERRUN) ? "true" : "false");
printf("Data Valid: %s\r\n\r\n",
(rawSample & ADC_SEQ_GDAT_DATAVALID) ?
"true" : "false");
}
}
}
}
}
Hard fault usually means that you try to execute code outside allowed addresses. If you have not registered the interrupt in the vector table but enabled it, the MCU will jump to whatever address that's written there instead, after which the program crashes.
How to fix that depends on tool chain. Assuming LPCXpresso, you have several options to set up libraries (I don't know about LPCOpen specifically), so where to find the vector table is different from case to case. However, this works quite similar on most MCUs, ARM or not. Somewhere in a "crt start-up" file you should have something along the lines of this:
void (* const g_pfnVectors[])(void) = ...
This is an array of function pointers which will be the vector table allocated in memory at address 0 on Cortex M. You have to place your function at the relevant interrupt vector. For example it may say something like
PIN_INT0_IRQHandler, // PIO INT0
If that's the interrupt you should implement, then you replace that line:
#include "my_irq_stuff.h"
...
void (* const g_pfnVectors[])(void) =
...
my_INT0, // PIO INT0
Assuming my_irq_stuff.h contains the function prototype my_INT0 for the interrupt service routine. The actual routine should be implemented in the corresponding .c file.
I've been trying to implement a basic per-byte UART Rx Interrupt on a STM32F4 board using HAL skeleton code generated by STMCubeMX version 4.26.0
Quite simply - I want to receive a character in UART1 via an Rx interrupt and transmit it on UART 6
I have successfully implemented a polled version of what I want to achieve
uint8_t in_usart1[10];
HAL_StatusTypeDef usart1_status;
usart1_status = HAL_UART_Receive(&huart1, in_usart1, 1, 1);
if (usart1_status != HAL_TIMEOUT)
{
HAL_UART_Transmit(&huart6, in_usart1, 1, 100);
}
I've enabled the UART 1 NVIC interrupt in STMCubeMX and stm32f4xx_it.c contains the IRQ handler which I've added my own user handler to:
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
HAX_USART1_IRQHandler(&huart1); /* My Handler */
/* USER CODE END USART1_IRQn 1 */
}
I've seen lot's of commentary about UART_Receive_IT() - but I suspect this is based on older versions of HAL due to UART_Receive_IT() being defined in stm32f4xx_hal_uart.c
My suspicion is that I need to enable to interrupt / clear the interrupt flag as when I debug, USART1_IRQHandler() is NEVER called
Does any one have any code that demonstrates what I am trying to achieve? My google-foo has failed me
EDIT:
I've gotten a little closer... In main.c I added (comments are existing code)
/* USER CODE BEGIN PV */
uint8_t rx_buffer;
/* USER CODE END PV */
...
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1, (uint8_t *)rx_buffer, 10);
/* USER CODE END 2 */
And then created:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
HAL_UART_Transmit(&huart6, &rx_buffer, 1, 100);
}
}
Now the Rx interrupt gets fired - but it's a bit flakey on the USART6 Tx, and the Rx interrupt only gets fired once
Do not block HAL_UART_RxCpltCallback for a long time! Just set a flag and check it and then send data from the main function.
And rx_buffer is variable so correct call HAL_UART_Receive_IT(&huart1, &rx_buffer, 1);
For anybody stumbling across this question, the answer is embarrassingly simple. I have two UARTs - One I was using an Rx Interrupt, and the other using DMA.
Turns out the one I thought I had configured for Interrupt was actually configured for DMA and visa-versa...
In STMCubeMX
- USART1 (RS485) has DMA Tx and DMA Rx enabled
- USART6 (Debug - RS232) has global interrupt enabled
In main.c
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(debug_uart(), debug_rx_buffer, BUFFER_SIZE);
HAL_UART_Receive_DMA(rs485_uart(), rs485_rx_buffer, BUFFER_SIZE);
/* USER CODE END 2 */
I have a user_main.c which has the following code:
#include <string.h>
#include "stm32f4xx_hal.h"
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart6;
UART_HandleTypeDef *debug_uart(void)
{
return &huart6;
}
UART_HandleTypeDef *rs485_uart(void)
{
return &huart1;
}
#define BUFFER_SIZE 1
uint8_t debug_rx_buffer[BUFFER_SIZE];
uint8_t debug_tx_buffer[BUFFER_SIZE];
uint8_t rs485_rx_buffer[BUFFER_SIZE];
uint8_t rs485_tx_buffer[BUFFER_SIZE];
static void rs485_tx(uint8_t *tx_buffer, uint16_t len)
{
HAL_UART_Transmit_DMA(rs485_uart(), tx_buffer, len);
}
static void debug_tx(uint8_t *tx_buffer, uint16_t len)
{
HAL_UART_Transmit(debug_uart(), tx_buffer, len, 1000);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == debug_uart())
{
memcpy(rs485_tx_buffer, debug_rx_buffer, BUFFER_SIZE);
rs485_tx(rs485_tx_buffer, BUFFER_SIZE);
HAL_UART_Receive_IT(debug_uart(), debug_rx_buffer, BUFFER_SIZE);
}
else if (huart == rs485_uart())
{
memcpy(debug_tx_buffer, rs485_rx_buffer, BUFFER_SIZE);
debug_tx(debug_tx_buffer, BUFFER_SIZE);
HAL_UART_Receive_DMA(rs485_uart(), rs485_rx_buffer, BUFFER_SIZE);
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == debug_uart())
{
}
else if (huart == rs485_uart())
{
}
}
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
{
}
The memcpy()'s may not be strictly required, but they do provide a level of isolation between all the buffers. Technically, there probably should be semaphores providing even more protection...
Note that I DO NOT use HAL_UART_Transmit_IT() for the debug UART - If you want to use HAL_UART_Transmit_IT (i.e. interrupt generated on completion of Tx), you will need to write code that handles transmission of characters from a circular buffer
I'm writing a small embedded program, where I send some commands over uart to the atmega328p chip. The commands start with the character $ and end with the character # (so I know when to perform the parsing). Upon receiving the command I parse it and turn the device on (COMMAND:TURN_ON_I1) or off (COMMAND:TURN_OFF_I1). The application currently looks like this:
// ------- Defines -------- //
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/power.h>
#include <stdio.h>
#include <string.h>
#include "pinDefines.h"
#include "USART.h"
#define RECEIVE_BUFFER_SIZE 100
// Control output value
#define output_low(port,pin) port &= ~(1<<pin)
#define output_high(port,pin) port |= (1<<pin)
// Set pin mode (input or output)
#define set_input(portdir,pin) portdir &= ~(1<<pin)
#define set_output(portdir,pin) portdir |= (1<<pin)
// The DDRD port contains only two pins:
#define REL_BTN_SIM_2 PD6 // PD6 = REL_BTN_SIM_2
void initUSART(void) { /* requires BAUD */
UBRR0H = UBRRH_VALUE; /* defined in setbaud.h */
UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif
/* Enable USART transmitter/receiver */
UCSR0B = (1 << TXEN0) | (1 << RXEN0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); /* 8 data bits, 1 stop bit */
}
void printString(const char myString[]) {
uint8_t i = 0;
while (myString[i]) {
transmitByte(myString[i]);
i++;
}
}
uint8_t receiveByte(void) {
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait for incoming data */
return UDR0; /* return register value */
}
void transmitByte(uint8_t data) {
/* Wait for empty transmit buffer */
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = data; /* send data */
}
int main(void) {
//$COMMAND:TURN_ON_I1#
//$COMMAND:TURN_OFF_I1#
char s[RECEIVE_BUFFER_SIZE];
char readSerialCharacter;
// -------- Inits --------- //
DDRB = 0b00000111;
DDRC = 0b00001000;
DDRD = 0b11000000;
initUSART();
// ------ Event loop ------ //
while (1) {
printString("Waiting for the start of string (char $).\r\n");
do { } while ( receiveByte() != '$'); // Wait for start of string.
// Fill the array until the end of transmission is received
int i=0;
do {
// If nearing end of buffer, don't fill the buffer and exit the loop
if(i<RECEIVE_BUFFER_SIZE-1){
readSerialCharacter = receiveByte();
s[i++] = readSerialCharacter;
}else
break;
} while (readSerialCharacter != '#'); // Wait for end of string.
s[i] ='\0'; // Terminate the string
printString("The whole received command:\r\n");
printString(s);
printString("\r\n");
// Other commands (temperature, relay control)
// REL_BTN_SIM_2
else if(strstr(s, "COMMAND:TURN_ON_I1") != NULL)
{
printString("Will set I1 on!");
output_high(PORTD, REL_BTN_SIM_2);
}
else if(strstr(s, "COMMAND:TURN_OFF_I1") != NULL)
{
printString("Will set I1 off!");
output_low(PORTD, REL_BTN_SIM_2);
}
else
printString("Unknown command.\r\n");
// Clear the buffer
memset(s,'\0', sizeof(s));
}
/* End event loop */
return (0);
}
I noticed that after I send a command around seven or eight times (or more), the serial communication is interrupted or that the command is executed with a delay. I can also see, that the debug strings "Will set I1 off!", "Will set I1 on!" are printed, but the state of the outputs are not changed (or are changed with a delay of a couple of seconds).
I was wondering if someone would know, what I'm doing wrong?
Thanks.
You have a nice definition of set_output(), but you are not using it. So I suspect that you never enabled the output driver. By setting the port register, you just enable the weak pull-up. Maybe that is not strong enough to switch on your relay driver fast. Do you have a capacitor in that driver circuit?
This code for display on LCD according to which keep semaphore, it should begin from task with high priority, but it begin with task with low priority
if I delete the semaphore, it will begin with high priority.
#include <avr/io.h>
#include <avr/interrupt.h>
#include "lcd.h"
#include "macros.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#define F_CPU 16000000
#include <util/delay.h>
/*task function prototype */
void TASK1(void * pvParameters );
void TASK2(void * pvParameters );
//void TASK3(void * pvParameters );
/*create a semaphore handle*/
//xSemaphoreHandle task_sync_sem ;
xSemaphoreHandle Semaphore1;
int main(void)
{
DDRD=0xff;
DDRB=0xff;
/*init LCD*/
LCD_init();
//task_sync_sem = xSemaphoreCreateCounting(1,0);
Semaphore1=xSemaphoreCreateCounting(1,1);
/*create task */
xTaskCreate(TASK1,"task1",400,NULL,8,NULL);
xTaskCreate(TASK2,"task2",400,NULL,6,NULL);
//xTaskCreate(TASK3,"task3",400,NULL,3,NULL);
/*Start OS "Scheduler " */
vTaskStartScheduler();
}
void TASK1(void * pvParameters )
{
for (;;)
{
LCD_Clear();
u8 vale=xSemaphoreTake(Semaphore1,50);
if(vale==1)
{
LCD_WriteData('A');
LCD_WriteData('B');
LCD_WriteData('C');
xSemaphoreGive(Semaphore1);
}
_delay_ms(1000);
vTaskDelay(2000);
}
}
void TASK2(void * pvParameters )
{
for (;;)
{
LCD_Clear();
u8 vale=xSemaphoreTake(Semaphore1,50);
if(vale==1)
{
LCD_WriteData('X');
LCD_WriteData('Y');
LCD_WriteData('Z');
xSemaphoreGive(Semaphore1);
vTaskDelay(2000);
}
}
}
Check your configMAX_PRIORITIES is higher or equal to 8 (your maximum priority).
Task Priorities
For your case, a Mutex seems more appropriate Mutex
You should also include the LCD_Clear() within the semaphore lock.
Behavior:
Your problem is probably related to the fact you create a counting semaphore with a maximum value of 1 and a starting value of 1, so it is already "Taken".
Semaphore1=xSemaphoreCreateCounting(1,1);
My guess, when your Task 1 execute, it is not able to take the semaphore and thus wait for 50 tick, in which the Task 2 will execute, but should also fail to take the semaphore as it is never "given" since it was locked from the begining.
Try to initialize with Semaphore1=xSemaphoreCreateCounting(1,0); , or better, use a mutex.