Currently I am having issues with a program running a freertos program. The purpose of the program is to control a stepper motor as well as an led. Implementing the motor control without microstepping does not have any issues as the two tasks take no parameters and call no functions.
However, when I introduce microstepping which requires two nested functions to be called by the move_routine task, the program will not do anything (no led flashing, no motor turning) when it did before. Does anyone have any solutions for this or any reasons on why this shouldn't work? From what I can see it should be fine to call a function from a freertos task.
#include <Arduino.h>
#include <Stepper.h>
/*================PIN DEFINITIONS================*/
#define LEDC_CHANNEL_0 0
#define LEDC_CHANNEL_1 1
#define LEDC_CHANNEL_2 2
#define LEDC_CHANNEL_3 3
const int A1A = 14;
const int A1B = 27;
const int B1A = 26;
const int B2A = 25;
const int ledPin = 33;
/*================VARIABLE DEFINITIONS================*/
int stepnumber = 0;
int Pa; int Pb;
const int stepsPerRev = 200;
Stepper myStepper(stepsPerRev, 14,27,26,25);
/*================Function Definitions================*/
//Analogwrite using LEDC capabilities
void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 255) {
//calculation of duty cycle
uint32_t duty = (4095/valueMax)*min(value, valueMax);
ledcWrite(channel,duty);
}
void move(int stepnumber, int MAXpower, int wait) {
Pa = (sin(stepnumber*0.098174)*MAXpower);
Pb = (cos(stepnumber*0.098174)*MAXpower);
if (Pa>0)
{
ledcAnalogWrite(LEDC_CHANNEL_0,Pa);
ledcAnalogWrite(LEDC_CHANNEL_1,0);
}
else
{
ledcAnalogWrite(LEDC_CHANNEL_0,0);
ledcAnalogWrite(LEDC_CHANNEL_1,abs(Pa));
}
if (Pb>0)
{
ledcAnalogWrite(LEDC_CHANNEL_2,Pb);
ledcAnalogWrite(LEDC_CHANNEL_3,0);
}
else
{
ledcAnalogWrite(LEDC_CHANNEL_2,0);
ledcAnalogWrite(LEDC_CHANNEL_3,abs(Pb));
}
}
void move_routine(void *parameters) {
while(1) {
for (int i=0; i<3199; i++)
{
stepnumber++;
move(stepnumber,255,250);
}
vTaskDelay(3000/portTICK_PERIOD_MS);
for (int i=0; i<1599; i++)
{
stepnumber--;
move(stepnumber,255,1000);
}
vTaskDelay(3000/portTICK_PERIOD_MS);
}
}
void led_task(void * parameters){
while(1){
digitalWrite(ledPin, HIGH);
vTaskDelay(500/portTICK_PERIOD_MS);
digitalWrite(ledPin, LOW);
vTaskDelay(500/portTICK_PERIOD_MS);
}
}
void setup(){
myStepper.setSpeed(60);
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
xTaskCreatePinnedToCore(
move_routine,
"Move Routine",
8192,
NULL,
1,
NULL,
1
);
xTaskCreatePinnedToCore(
led_task,
"LED Task",
1024,
NULL,
1,
NULL,
1
);
}
void loop(){
}
Expected to see flashing led and motor turning but nothing witnessed
Your two tasks work as it were defined, the problem is your ledcAnalogWrite() function where you are calling ledcWrite() function with nowhere in your code initialise the LEDC with ledcSetup() and ledcAttachPin().
Read the documentation on LED Control(LEDC).
I'm modifying some existing open source library and there is a struct (say named as Node) containing bit-fields, e.g.
struct Node {
std::atomic<uint32_t> size:30;
std::atomic<uint32_t> isnull:1;
};
To fit my needs, these fields need to be atomic so I was expecting to use std::atomic for this and faced compile time error:
bit-field 'size' has non-integral type 'std::atomic<uint32_t>'
According to documentation, there is a restricted set of types which can be used for std::atomic
Can anyone advise/have idea on how to get functionality of atomic fields with the minimum impact to the existing source code?
Thanks in advance!
I used an unsigned short as an example below.
This is less ideal, but you could sacrifice 8 bits and insert a std::atomic_flag in the bit field with a union. Unfortunately, std::atomic_flag type is a std::atomic_bool type.
This structure can be spin locked manually every time you access it. However, the code should have minimal performance degradation (unlike creating, locking, unlocking, destroying with a std::mutex and std::unique_lock).
This code may waste about 10-30 clock cycles to enable low cost multi-threading.
PS. Make sure the reserved 8 bits below are not messed up by the endian structure of the processor. You may have to define at the end for big-endian processors. I only tested this code on an Intel CPU (always little-endian).
#include <iostream>
#include <atomic>
#include <thread>
union Data
{
std::atomic_flag access = ATOMIC_FLAG_INIT; // one byte
struct
{
typedef unsigned short ushort;
ushort reserved : 8;
ushort count : 4;
ushort ready : 1;
ushort unused : 3;
} bits;
};
class SpinLock
{
public:
inline SpinLock(std::atomic_flag &access, bool locked=true)
: mAccess(access)
{
if(locked) lock();
}
inline ~SpinLock()
{
unlock();
}
inline void lock()
{
while (mAccess.test_and_set(std::memory_order_acquire))
{
}
}
// each attempt will take about 10-30 clock cycles
inline bool try_lock(unsigned int attempts=0)
{
while(mAccess.test_and_set(std::memory_order_acquire))
{
if (! attempts) return false;
-- attempts;
}
return true;
}
inline void unlock()
{
mAccess.clear(std::memory_order_release);
}
private:
std::atomic_flag &mAccess;
};
void aFn(int &i, Data &d)
{
SpinLock lock(d.access, false);
// manually locking/unlocking can be tighter
lock.lock();
if (d.bits.ready)
{
++d.bits.count;
}
d.bits.ready ^= true; // alternate each time
lock.unlock();
}
int main(void)
{
Data f;
f.bits.count = 0;
f.bits.ready = true;
std::thread *p[8];
for (int i = 0; i < 8; ++ i)
{
p[i] = new std::thread([&f] (int i) { aFn(i, f); }, i);
}
for (int i = 0; i < 8; ++i)
{
p[i]->join();
delete p[i];
}
std::cout << "size: " << sizeof(f) << std::endl;
std::cout << "count: " << f.bits.count << std::endl;
}
The result is as expected...
size: 2
count: 4
From the post Understanding Frama-C slicer results, it seems Frama-C supports the forward conditioned slicing with Frama-C. For the following example test.c, I wonder how to do the forward conditioned slicing with the specific function "event". #Pascal Cuoq
/*# requires a == 1 ;
*/
#include <stdio.h>
int event() {
int r;
scanf("%d", &r);
if (r>10) return 1;
else return 0;
}
void event_process() {
int x=0;
printf("event process\n");
x=1;
}
void no_event()
{
int y=0;
printf("no event\n");
}
void main ( ) {
int a;
if((a=event()) == 1)
event_process();
else
no_event();
printf("in main\n");
return;
}
I tried frama-c test.c -slice-calls event -then-on 'Slicing export' -print, why it outputs as follows:
/* Generated by Frama-C */
void event_slice_1(void)
{
return;
}
void main(void)
{
event_slice_1();
return;
}
I am trying to use the advise found here: How to assert if a std::mutex is locked? to check if a mutex is currently locked. It seems to work at a first glance but it crashed when you try to use it from multiple threads. My guess is that unique_lock is not thread safe which would make a lot of sense which would mean there is no easy way to check if a mutex is already locked without writing a wrapper.
#include <iostream>
#include <thread>
#include <mutex>
long glob=0;
std::mutex mutex_;
std::unique_lock <std::mutex> glock (mutex_, std::defer_lock);
void call_from_thread (int tid)
{
std::cout <<"Started "<<tid<<std::endl;
for (int i=0; i<1000; ++i)
{
std::lock_guard< std::unique_lock <std::mutex> > lock2 (glock);
std::cout<<tid<<":"<<i<<":"<<glob<<std::endl;
++glob;
};
std::cout<<"Done "<<tid<<std::endl;
};
int main ()
{
std::thread t [10];
for (int i=0; i<10; ++i)
{
t[i]=std::thread (call_from_thread, i);
};
for (int i=0; i<10; ++i)
{
t[i].join ();
};
std::cout <<"Glob = "<<glob<<std::endl;
return 0;
}
I am writting firmware for AT90CAN32 using AVR Studio + WinAVR.
It seems simple for experienced AVR programmers.
I pass int argument to function, but inside the function it is always zero.
There is inside protocol.c file:
#include <uart.h>
static char packet[16] = ":AA111122223!f\r\n";
void vDivRequesting(void)
{
uint8_t cntOfBms = getCountOfBms( );
for(uint8_t i=0; i<cntOfBms; i++)
{
createPacket(getBmsNetworkNumber(i), REQUEST_V_DIV, 1);
usartSendString(packet,11);
_delay_ms(200);
}
}
There is uart.c file:
void usartSendString( char *data, uint8_t len )
{
uint8_t i=0;
usartSendByte(len + 0x30);
for( i=0; i<len; i++)
{
usartSendByte(*data);
*data++;
}
}
And it prints me that len argument is zero. usartSendString function is defined in uart.h file. What is wrong with that code?