用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/JohnNuwan/EVA_CORE --skill c-cpp-industrial-embedded命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | c-cpp-industrial-embedded |
| description | Programmer en C et C++ pour l'embarqué et le temps réel. |
| version | 1.1.0 |
| author | EVA |
| license | Privée EVA St-Étienne |
| platforms | ["linux","windows"] |
| metadata | {"tags":["c","cpp","embedded","realtime","plcnext","twincat","ethercat","profinet","fieldbus","cross-compilation"],"related_skills":["iec61131-3-programming-standards","rust-cython-for-industry","ot-it-integration-languages"]} |
Cette compétence encadre le développement d'applications bas niveau en C et C++ destinées aux microcontrôleurs, aux ordinateurs industriels durcis (IPC), aux automates programmables ouverts (PLCnext, TwinCAT) et aux bus de terrain temps réel.
Pour garantir qu'une tâche s'exécute précisément à intervalles réguliers (gigue inférieure à quelques microsecondes), il est indispensable d'utiliser l'ordonnanceur temps réel et de verrouiller l'espace mémoire.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sched.h>
#include <sys/mman.h>
#include <pthread.h>
#define NANO_SECONDS_PER_SEC 1000000000
// Fonction exécutée par le thread temps réel
void* rt_periodic_task(void* arg) {
struct sched_param param;
param.sched_priority = 99; // Priorité temps réel max sous Linux
// Définition de la politique d'ordonnancement FIFO temps réel
if (pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m) == -1) {
perror("pthread_setschedparam a échoué");
return NULL;
}
// Verrouillage de la mémoire virtuelle pour éviter les défauts de page (page faults)
if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
perror("mlockall a échoué");
return NULL;
}
struct timespec next_period;
clock_gettime(CLOCK_MONOTONIC, &next_period);
period_ns = ;
() {
next_period.tv_nsec += period_ns;
(next_period.tv_nsec >= NANO_SECONDS_PER_SEC) {
next_period.tv_nsec -= NANO_SECONDS_PER_SEC;
next_period.tv_sec++;
}
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next_period, );
}
;
}
Les composants C++ PLCnext s'interfacent avec le Global Data Space (GDS).
#include "Arp/System/Core/Arp.h"
#include "Arp/System/Commons/Logging.h"
#include "Arp/Plc/Commons/Domain/ComponentBase.h"
namespace EVA {
class MainPlcComponent : public Arp::Plc::Commons::Domain::ComponentBase
{
public:
MainPlcComponent(IApplication& application, const String& name);
virtual ~MainPlcComponent() = default;
void Initialize() override;
void LoadConfig() override;
void SetupConfig() override;
void ResetConfig() override;
// Déclaration des ports d'E/S mappés dans le GDS
//#port
//#attributes(Input)
int32 input_laser_distance_mm = 0;
//#port
//#attributes(Output)
bool output_ejection_cylinder = false;
// Méthode appelée cycliquement par le gestionnaire d'exécution
void ExecuteCyclic()
{
(input_laser_distance_mm > ) {
output_ejection_cylinder = ;
} {
output_ejection_cylinder = ;
}
}
};
}
CANopen et DeviceNet s'appuient sur le bus physique CAN. Sous Linux, SocketCAN permet de manipuler les trames comme des connexions réseau.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
int init_can_port(const char* interface_name) {
int s;
struct sockaddr_can addr;
struct ifreq ifr;
// Création d'un socket CAN brut
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("Erreur création socket CAN");
return -1;
}
strcpy(ifr.ifr_name, interface_name);
ioctl(s, SIOCGIFINDEX, &ifr); // Résolution de l'index de l'interface (ex: can0)
memset(&addr, 0, sizeof(addr));
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if (bind(s, (struct sockaddr *)&addr, (addr)) < ) {
perror();
close(s);
;
}
s;
}
{
frame.can_id = + node_id;
frame.can_dlc = ;
frame.data[] = (torque_value >> ) & ;
frame.data[] = torque_value & ;
(write(socket_fd, &frame, ( can_frame)) != ( can_frame)) {
perror();
;
}
;
}
std::vector::push_back, std::string ou std::shared_ptr dans la boucle temps réel car ils provoquent des allocations mémoire dynamiques invisibles sous le capot. Utilisez std::array ou pré-allouez la capacité des vecteurs au démarrage (std::vector::reserve).cppcheck, clang-tidy) et compilez avec -Wall -Wextra -Werror pour interdire tout comportement indéterminé du compilateur.