I am new to the Cosmic compiler and STM8.
In iostm8s103.h the Switch control register is defined as
volatile char CLK_SWCR #0x50c5;
How do I address the switch busy bit (SWBSY bit 0) in that register?
I need to wait until the switch busy bit is clear. (While bit)
It is strange that I cannot find an example for the Cosmic compiler.
With the micro-controller, using volatile registers is simple.
#include <iostm8s103.h>
CLK_SWCR |= SWBSY; // to set the bit 0
CLK_SWCR &= ~SWBSY; // to reset the bit 0
In the iostm8s103.h, the register is defined as follow:
volatile char CLK_SWCR #0x50c5; /* Switch Control reg */
So, to wait while BUSY, with that iostm8s103.h, the code looks like:
while ((CLK_SWCR | SWBSY) != 0);
If using the stm8s.h instead of iostm8s103.h, the CLK registers
are defined as struct.
So, to wait while BUSY, with that stm8s.h, the code looks like:
while ((CLK->SWCR | CLK_SWCR_SWBSY) != 0);
or
while (CLK->SWCR & CLK_SWCR_SWBSY);
Related
I'm not sure if this is happening when assigning a variable specifically but when debugging the assembly code, the compiler executes RJMP $+0000 where it hangs the program.
EDIT: I added included libraries if that's relevant
#define __DELAY_BACKWARD_COMPATIBLE__
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/delay.h>
#include <stdint.h>
void ReadTemp(uint8_t address){
ADCSRA = ADCSRA | 0b10000111; //enable ADC, CLK/128 conversion speed
ADMUX = ADMUX | 0b01000000; //Use internal 2.56V Vref and PA0 as input, right-hand justified
ADCSRA |= (1 << ADSC); //start conversion
while(!(ADCSRA & (1 << ADIF))) {} // wait until process is finished;
uint8_t low_value = ADC & 0x00FF;
// or low_value = ADCL;
uint8_t high_value = ADC & 0xFF00; //problem here
...
}
I don't know what any of this is doing, but I do see an error in the bitwise math.
uint8_t low_value = ADC & 0x00FF;
uint8_t high_value = ADC & 0xFF00; //problem here
low_value and high_value are both 8 bits (uint8_t). I am going to go out on a limb here and say ADC is 16 bit. For high_value, you are anding ADC with 0xFF00 then truncating the value to 8 bit. high_value will always be zero.
What should be done is:
uint8_t high_value = (ADC & 0xFF00) >> 8;
This will grab the left byte of ADC and shift it right by 8 bits then assign it to the high_value byte storage giving you the correct value.
How you are doing low_value is correct. As a matter of fact, you could simply do:
uint8_t low_value = ADC;
There is something somewhat suboptimal here:
uint8_t low_value = ADC & 0x00FF;
You are reading ADC, which is a 16-bit register, implemented as a pair
of 8-bit registers. As shown in the disassembly, this requires two in
instructions, one per byte. And then you are just throwing away one of
those bytes. You may think that the compiler is smart enough to avoid
reading the byte it is going to discard right away. Unfortunately, it
cannot do that, as I/O registers are declared as volatile. The
compiler is forced to access the register as many times as the source
code does.
If you just want the low byte, you should read only that byte:
uint8_t low_value = ADCL;
You then wrote:
uint8_t high_value = ADC & 0xFF00;
As explained in the previous answer, high_value will be zero. Yet the
compiler will have to read the two bytes again, because the I/O register
is volatile. If you want to read the high byte, read ADCH.
But why would you want to read those two bytes one by one? Is it to put
them back together into a 16-bit variable? If this is the case, then
there is no need to read them separately. Instead, just read the 16-bit
register in the most straight-forward fashion:
uint16_t value = ADC;
A long time ago, gcc didn't know how to handle 16-bit registers, and
people had to resort to reading the bytes one by one, and then gluing
them together. You may still find very old example code on the Internet
that does that. Today, there is absolutely no reason to continue
programming this way.
Then you wrote:
//problem here
Nope, the problem is not here. That is not what generated the rjmp
instruction. The problem is probably right after that line, in the code
you have chosen not to post. You have some bug that manifests itself
only when optimizations are turned on. This is typical of code that
produces undefined behavior: works as expected with optimizations off,
then does weird “unexplainable” things when you enable optimizations.
I am new to Free RTOS, and I was following some tutorial line by line but things didn't sum up correctly, I used free RTOS to toggle 3 LEDS but it lights just 2 of them without toggling! random 2 LEDs, whatever I change the priorities or the delay time of toggling. random 2 LEDs just switch on and nothing more, I tried the code on proteus simulation and on real hardware and the same problem exists. can someone help me with this?
M/C: ATMEGA32A
RTOS: FreeRTOS
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
/* FreeRTOS files. */
#include "FreeRTOS.h"
#include "task.h"
#include "croutine.h"
#include "FreeRTOSConfig.h"
/* Define all the tasks */
static void ledBlinkingtask1(void* pvParameters);
static void ledBlinkingtask2(void* pvParameters);
static void ledBlinkingtask3(void* pvParameters);
int main(void) {
/* Call FreeRTOS APIs to create tasks, all tasks has the same priority "1" with the
same stack size*/
xTaskCreate( ledBlinkingtask1,"LED1",
configMINIMAL_STACK_SIZE, NULL, 1, NULL );
xTaskCreate( ledBlinkingtask2,"LED2",
configMINIMAL_STACK_SIZE, NULL,1, NULL );
xTaskCreate( ledBlinkingtask3,"LED3",
configMINIMAL_STACK_SIZE, NULL,1, NULL );
// Start the RTOS kernel
vTaskStartScheduler();
/* Do nothing here and just run infinte loop */
while(1){};
return 0;
}
static void ledBlinkingtask1(void* pvParameters){
/* Define all variables related to ledBlinkingtask1*/
const uint8_t blinkDelay = 100 ;
/* make PB0 work as output*/
DDRB |= (1<<0); //PB0
/* Start the infinte task 1 loop */
while (1)
{
PORTB ^= (1<<0); //toggle PB0 //PB0
vTaskDelay(blinkDelay); //wait some time
}
}
static void ledBlinkingtask2(void* pvParameters){
/* Define all variables related to ledBlinkingtask2*/
const uint8_t blinkDelay = 100;
/* make PB1 work as output*/
DDRB |= (1<<1);//PB0
/* Start the infinte task 2 loop */
while (1)
{
PORTB ^= (1<<1); //toggle PB0 //PB0
vTaskDelay(blinkDelay); //wait some time
}
}
static void ledBlinkingtask3(void* pvParameters){
/* Define all variables related to ledBlinkingtask3*/
const uint16_t blinkDelay = 100;
/* make PB2 work as output*/
DDRB |= (1<<2); //PB2
/* Start the infinte task 3 loop */
while (1)
{
PORTB ^= (1<<2); //toggle PB0 //PB0
vTaskDelay(blinkDelay); //wait some time
}
}
ps: every task works well alone but not together!
As already mentioned in comments - the major problem seems to be that access to the port register driving the LEDs is neither
PORTB ^= (1<<0); // in task 1
[...]
PORTB ^= (1<<1); // in task 2
[...]
PORTB ^= (1<<2); // in task 3
atomic
protected (by disabling interrupts during access, or by RTOS measures such as a mutex)
deployed to one unique task:
It may be misleading that the access to HW register is performed using a single instruction in the C code every time.
Still, this doesn't help because the compiler generates several assembler instructions (e.g., load previous port value to register, modify that register value, write it back to the port). This way, one task can interrupt another between those assembler/CPU instructions and modify the intermediate value.
Several tasks writing back "their" register value to the port in turn can revert what other task(s) may have just written to the port, so you miss a blinky event (or several, if this happens systematically).
The solution is therefore to protect the assignments against each other.
In the same order as numbered above, this may mean either of the following:
Check if the hardware offers a "set value" or "reset value" register beside the main PORTB port register. If so, writing a single bit to that port would be an atomic way to have the LED toggle.
I'm sorry that I don't know the hardware interface of Atmega. Maybe, this isn't possible, and you have to go on directly to 2. and 3.
a. Disable interrupts before changing the port register, reenable it afterwards. This way, the task scheduler won't run during that period (= critical section) and nobody disturbs the task that accesses the hardware.
b. Use taskENTER_CRITICAL()/taskEXIT_CRITICAL()
c. Use a mutex or similar.
Create a fourth task which waits (blocking) at a mailbox/queue.
Whenever it receives a value from the mailbox, it processes it (e.g., by XOR-ing it to the port register).
The three existing tasks don't access the LED port register themselves, but instead send such a value (= request message) to the new task.
Assign a higher priority to the new task in order to get a smooth blinking pattern.
If option 1. is possible on your controller, it is fastest (but it requires certain features in the hardware platform...). Otherwise, I agree with the hint from #Richard, option 2.b. are fastest (2.a. is as fast, but not as clean because you break the layering of the FreeRTOS lib).
Option 2.c. may introduce a notable overhead, and option 3. is very clean but a complete overkill in your situation: If your question is really only about blinking LEDs, please leave the bulldozer inside the garage and choose option 2.
I am using stm8l - discovery and i have created a code for toggling a led for every 1 second using timer (TIM1) but this is not working properly. I am missing something here in my configuration
I could enter the interrupt function for the first time but after that it does not enter the interrupt function. Someone please look into and help me out
enter code here
#include <iostm8l.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "defs.h"
unsigned int count = 0;
#svlreg #interrupt void TIM1(void)
{
count += 1;
TIM1_SR1 &= ~(0x01);
}
main()
{
CLK_DIVR = 0x00; // Set the frequency to 16Mhz
CLK_PCKENR2 = 0x02; // clock for timer1
PC_DDR = 0x80; // direction output for led
PC_CR1 = 0x80; // fast push pull mode
PE_DDR = 0x80; // direction output for led
PE_CR1 = 0x80; // fast push pull mode
TIM1_PSCRH = 0x3e; //to create a frequency for 1000 hz
TIM1_PSCRL = 0x80; // so prescalar is 16000
TIM1_CR1 = 0x01;
TIM1_IER = 0x01;
_asm("rim\n");
while(1)
{
if (count == 1000)
{
PE_ODR ^= 0x80;
count = 0;
}
}
}
The interrupt enters only one time but after that it does not enter. So variable "count" remains at value 1
You are using magic numbers for the bit masks instead of defined constants, so the code is pretty damn hard to read for you and me both. Change this so that the code ends up like for example
TIM1_SR1 &= ~TIM1_SR1_UIF;
Since this is a 8 bit MCU it is also absolutely essential that you u suffix all integer contants, or they will be of type signed int, which you don't want.
For example this code TIM1_SR1 &= ~(0x01); is equivalent to TIM1_SR1 &= -2. Very easy to write accidental subtle bugs this way. I recommend studying Implicit type promotion rules.
It is highly recommended to disassemble every ISR you write to see what machine code you actually end up with, and single step it through the debugger while watching the register as well. This particular register seems to ignore having 1 written to it, so you could probably just do TIM1_SR = TIM1_SR1_UIF;. Incorrectly cleared timer flags inside ISRs is one of the most common bugs in embedded systems.
Quoting the manual:
UIF: Update interrupt flag
– At overflow or underflow if UDIS = 0 in the TIM1_CR1 register
– When CNT is re-initialized by software using the UG bit in TIM1_EGR register, if URS = 0 and UDIS = 0 in the TIM1_CR1 register.
– When CNT is re-initialized by a trigger event (refer to the TIM1_SMCR register description), if URS = 0 and UDIS = 0 in the TIM1_CR1 register
Your code doesn't appear to do any of this, so it is pretty safe to assume the timer counter isn't reset.
Another problem is that count must be declared as volatile or otherwise the compiler might optimize out this code completely:
if (count == 1000)
{
PE_ODR ^= 0x80;
count = 0;
}
I have set up a project using a 16-bit Microcontroller called Thunderbird12, similar to the 9s12/Freescale 68HC12 family. It does a few things but mainly turn on an external water pump. Everything works fine except I need to implement an interrupt. I want to be able to stop the motor using an interrupt through a push button.
I have set up the button which sets pin 0 of port P to high when pressed. Using C, I have initialized the hardware and written the code but the flag is not called. Please see code below.
// Interrupt function
int interruptFlag;
void interrupt 56 WaterPumpRoutine() {
if ((PIFP & 0x01) == 0x01) { // check if pin 0 of port p is high (when button is pressed)
interruptFlag = 1; // set the flag to 1
}
// Main
void main() {
DDRP = 0x00; // set port P as input
PIEP = PIEP | 0x01; // enable interrupts on port P, pin 0
PERP = PERP | 0x01; // enable pull-up/down on port P, pin 0
if ( interruptFlag == 1)
PORTB = (PORTB & 0x00) // Here I'm turning off all the pins in Port B, which includes the pump.
}
If I put this code PORTB = (PORTB & 0x00) inside the WaterPumpRoutine() function, it works fine, but I need to be able to call the flag anywhere. I'm not sure what I'm missing. Any help would be appreciated!
Assuming that the interrupt call works fine..
Change the variable int interruptFlag; to volatile int interruptFlag;. This is to avoid optimizing away the if condition in main by the compiler.
In main you need to reset the interruptFlag on some condition. This is program dependent. Maybe you can do it like this.
if ( interruptFlag == 1)
{
PORTB = (PORTB & 0x00) // Here I'm turning off all the pins in Port B, which includes the pump.
interruptFlag = 0;
}
If you are using a push button, you should introduce a debounce mechanism to avoid detecting multiple inputs.
You need to add the if condition in main inside a while(1) loop as the interrupt can come at any time.
while(1)
{
if(interruptFlag == 1)
{
...
}
}
If u still can't get interrupt to fire , after things that other suggested, you should check if you got global interrupts or interrupt for specific part (GPIO) enabled since in most uc setting GPIO to generate interrupts doesn't enable interrupts
I'm using an Atmega328. I have output pins that are "randomly" distributed along the pinout, i.e. they don't belong to the same ports. For example, my output pins could be PB0, PB4, PC1, PC3 and PD1.
I have always used Assembly to program microcontrollers, so this would be my first time using C. What I want to know is if there is a way to avoid using DDRx and Px for each pin to set them or clear them.
For example, I would like to use something like this to set the first bit of Port B:
#define NAME_1 DDRB,0
sbi NAME_1;
Is this possible?
EDIT:
Maybe I didn't express myself clearly. What I want is to be able to refer to certain I/O port pins with some meaningful names. For example, name PD3 "blue_LED", so that the code is more readable and, if the blue LED's position is changed later, the code can be easily modified. Stated another way, I want to be able to turn on and off certain pins with their names not being hard-coded. Is there a way?
The sbi instruction is special in that it directly manipulates a bit in an I/O Port on the AVR platform. The normal course with I/O ports is that you have to use other instructions (like out) to copy whole words between the I/O port and a register.
That said, there's no sbi in C. C just doesn't know about these special features of one particular platform. For the assembly you give as an example, you would write in C:
DDRB |= 1<<0;
I personally think this looks quite concise, but of course you COULD define a macro
#define sbi(x,b) (x) |= 1<<(b)
sbi(DDRB, 0);
(where b is the "bit number") and maybe the other way around
#define cbi(x,b) (x) &= ~(1<<(b))
cbi(DDRB, 0)
This would work, but I recommend not to use it. While the first notation DDRB |= 1<<0; is obvious to any C programmer, using macros like this probably isn't.
As a final note, if you are concerned about performance: I haven't verified this, but I'm pretty sure avr-gcc is smart enough to emit sbi and cbi instructions when a bit mask operation on an I/O port effectively just changes a single bit. edit: see JLH's answer for an experimental result that gcc-avr indeed is smart enough to emit these sbi/cbi instructions.
I use avg-gcc on to program Atmel AVRs and the support packages most definitely know about cbi, sbi, and all instructions for that matter. So there's no need to resort to assembly unless you want to. Here's some disassembled C to prove it.
PORTD |= (1 << PD0);
d8: 58 9a sbi 0x0b, 0 ; 11
Now I'll show you how. You can set each bit of each port to do either input or output very easily.
DDRA |= (1<<PA0);
has the effect of making pin 0 on port A an output as shown:
bit76543210
00000001 // or-ing the 1 adds 1 leaving the other bits alone.
To also make pin A3 an output, do this:
DDRA |= (1<<PA3);
bit76543210
00001001 // now the DDRA register looks like this, pins 0 and 3 set as outputs
Tedious, right? Well, these right-side expressions evaluate to constants so you can combine these into one statement:
DDRA |= (1<<PA0) | (1<<PA3);
and the compiler will fold the right hand side into one constant and |= it into the register. So, you really need only one statement like this per port, and the compiler makes it very efficient.
That takes care of direction -- input or output. The next is to set and clear outputs.
To set an output:
PORTD |= (1<<PD); // turns pin 0 on port D on (high) as an output.
PORTD &= ~(1<<PD); // turns pin 0 on port D off (low) as an output.
PORTD ^= (1<<PD); // toggles it (high-> low) or (low->high as an output.
EDIT:
To the extra requirements you named about using meaningful names, of course you can do that. I routinely do this to avoid having to remember what's connected to what. For example, from that same project:
#define LED_INDICATOR_PIN PA0
#define LED_INDICATOR_PORT PORTA
#define LED_INDICATOR_DDR DDRA
I refer to the 'friendly' names in my code:
void initialize(void)
{
// Set up an output pin to blink an LED to show sign of life.
LED_INDICATOR_DDR |= (1 << LED_INDICATOR_PIN);
// Set up TTY port.
init_uart();
}
void toggleLED(void)
{
LED_INDICATOR_PORT ^= (1 << LED_INDICATOR_PIN);
}
Much easier to read. Is that what you're after? I know it's what I do every time.
With C++ I wrote something like this:
//IO = I/O Subsystem
inline void Io_LEDred_Configure() {DDRB |= 1<<0; } //Port B0
inline void Io_LEDred_On() {PORTB |= 1<<0; }
inline void Io_LEDred_Off() {PORTB &= ~(1<<0);}
inline void Io_LEDgreen_Configure() {DDRD |= 1<<3; } //Port D3
inline void Io_LEDgreen_On() {PORTD |= 1<<3; }
inline void Io_LEDgreen_Off() {PORTD &= ~(1<<3);}
If you have to switch an IO to a different port you have to change only those three lines and you're done.
In C++ the compiler emits exactly that code what you as an assembler coder would write. In C you have to use a regular function. But the calls coming with some overhead. If you want to avoid this you have to use macros:
#define IO_LEDRED_CONFIGURE DDRB |= 1<<0
#define IO_LEDRED_ON PORTB |= 1<<0
...