33 #include <px4_platform_common/px4_config.h> 34 #include <px4_platform_common/log.h> 35 #include <px4_platform_common/tasks.h> 38 #include <nuttx/clock.h> 41 #include <px4_platform_common/workqueue.h> 52 #include <nuttx/board.h> 53 #include <arch/chip/chip.h> 78 #define RESOURCE_DEBUG 79 #if defined(RESOURCE_DEBUG) 80 #define resources(s) ::syslog(LOG_INFO," %s\n",(s)); \ 81 if (UavcanNode::instance()) { \ 82 syslog(LOG_INFO,"UAVCAN getPeakNumUsedBlocks() in bytes %d\n", \ 83 UAVCAN_MEM_POOL_BLOCK_SIZE * UavcanNode::instance()->get_node().getAllocator().getPeakNumUsedBlocks()); \ 104 .major_version = APP_VERSION_MAJOR,
105 .minor_version = APP_VERSION_MINOR,
106 .reserved = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
117 _node(can_driver, system_clock),
119 _time_sync_slave(_node),
120 _fw_update_listner(_node),
123 const int res = pthread_mutex_init(&_node_mutex,
nullptr);
129 px4_sem_init(&_sem, 0, 0);
131 px4_sem_setprotocol(&_sem, SEM_PRIO_NONE);
152 }
while (_task != -1);
156 px4_sem_destroy(&_sem);
163 if (_instance !=
nullptr) {
164 warnx(
"Already started");
171 static CanInitHelper can;
172 static bool can_initialized =
false;
174 if (!can_initialized) {
175 const int can_init_res = can.init(bitrate);
177 if (can_init_res < 0) {
178 warnx(
"CAN driver init failed %i", can_init_res);
182 can_initialized =
true;
190 if (_instance ==
nullptr) {
191 warnx(
"Out of memory");
197 const int node_init_res = _instance->init(node_id, can.driver.updateEvent());
200 if (node_init_res < 0) {
203 warnx(
"Node init failed %i", node_init_res);
204 return node_init_res;
210 _instance->active_bitrate = bitrate;
215 static auto run_trampoline = [](int,
char *[]) {
return UavcanNode::_instance->
run();};
216 _instance->_task = px4_task_spawn_cmd(
"uavcan", SCHED_DEFAULT, SCHED_PRIORITY_ACTUATOR_OUTPUTS, StackSize,
217 static_cast<main_t>(run_trampoline),
nullptr);
219 if (_instance->_task < 0) {
220 warnx(
"start failed: %d", errno);
230 uavcan::protocol::SoftwareVersion swver;
233 char fw_git_short[9] = {};
236 swver.vcs_commit = std::strtol(fw_git_short, &end, 16);
237 swver.optional_field_flags |= swver.OPTIONAL_FIELD_FLAG_VCS_COMMIT;
242 warnx(
"SW version vcs_commit: 0x%08x",
unsigned(swver.vcs_commit));
244 _node.setSoftwareVersion(swver);
247 uavcan::protocol::HardwareVersion hwver;
249 hwver.major = HW_VERSION_MAJOR;
250 hwver.minor = HW_VERSION_MINOR;
253 board_get_mfguid(mfgid);
254 uavcan::copy(mfgid, mfgid +
sizeof(mfgid), hwver.unique_id.begin());
256 _node.setHardwareVersion(hwver);
261 px4_systemreset(
false);
267 uavcan::ServiceResponseDataStructure<UavcanNode::BeginFirmwareUpdate::Response> &rsp)
269 static bool inprogress =
false;
271 rsp.error = rsp.ERROR_UNKNOWN;
273 if (req.image_file_remote_path.path.size()) {
274 rsp.error = rsp.ERROR_IN_PROGRESS;
280 shared.
node_id = _node.getNodeID().get();
284 _reset_timer.startOneShotWithDelay(uavcan::MonotonicDuration::fromMSec(1000));
285 rsp.error = rsp.ERROR_OK;
301 _node.setName(HW_UAVCAN_NAME);
303 _node.setNodeID(node_id);
310 if (srv_start_res < 0) {
316 return _node.start();
327 ::syslog(LOG_INFO,
"UAVCAN: Restarting by request from %i\n",
int(request_source.get()));
328 ::usleep(20 * 1000 * 1000);
329 px4_systemreset(
false);
336 const int spin_res = _node.spin(uavcan::MonotonicTime());
339 warnx(
"node spin error %i", spin_res);
346 px4_sem_t *sem = (px4_sem_t *)arg;
349 if (px4_sem_getvalue(sem, &semaphore_value) == 0 && semaphore_value > 1) {
373 ::syslog(LOG_INFO,
"UAVCAN: Indication controller init failed\n");
378 ::syslog(LOG_INFO,
"UAVCAN: sim controller init failed\n");
382 (void)pthread_mutex_lock(&_node_mutex);
388 const int slave_init_res = _time_sync_slave.start();
390 if (slave_init_res < 0) {
391 warnx(
"Failed to start time_sync_slave");
395 _node.setModeOperational();
397 uint32_t start_tick = clock_systimer();
404 (void)pthread_mutex_unlock(&_node_mutex);
406 while (px4_sem_wait(&_sem) != 0);
408 (void)pthread_mutex_lock(&_node_mutex);
416 if (clock_systimer() - start_tick > TICK_PER_SEC) {
417 start_tick = clock_systimer();
422 const bool active = _time_sync_slave.isActive();
424 const int master_node_id = _time_sync_slave.getMasterNodeID().get();
426 const long msec_since_last_adjustment = (_node.getMonotonicTime() - _time_sync_slave.getLastAdjustmentTime()).toMSec();
428 syslog(LOG_INFO,
"Time:%lld\n" 429 " Time sync slave status:\n" 431 " Master Node ID: %d\n" 432 " Last clock adjustment was %ld ms ago\n",
433 utc .toUSec(),
int(active), master_node_id, msec_since_last_adjustment);
434 syslog(LOG_INFO,
"UTC %lu sec Rate corr: %fPPM Jumps: %lu Locked: %i\n\n",
435 static_cast<unsigned long>(utc.toMSec() / 1000),
445 (void)pthread_mutex_unlock(&_node_mutex);
476 if (ret == -ENOTTY) {
477 ret = CDev::ioctl(filp, cmd, arg);
487 warnx(
"not running, start first");
490 (void)pthread_mutex_lock(&_node_mutex);
493 (void)pthread_mutex_unlock(&_node_mutex);
502 "\tuavcannode {start|status|stop|arm|disarm}");
509 resources(
"Before board_app_initialize");
511 board_app_initialize(NULL);
541 if (node_id < 0 || node_id > uavcan::NodeID::Max || !uavcan::NodeID(node_id).isUnicast()) {
542 warnx(
"Invalid Node ID %i", node_id);
547 warnx(
"Node ID %u, bitrate %u", node_id, bitrate);
562 if (!std::strcmp(argv[1],
"start")) {
565 errx(1,
"already started");
575 errx(1,
"application not running");
578 if (!std::strcmp(argv[1],
"status") || !std::strcmp(argv[1],
"info")) {
583 if (!std::strcmp(argv[1],
"stop")) {
volatile bool _task_should_exit
float getUtcRateCorrectionPPM()
Clock rate error.
static int start(uavcan::NodeID node_id, uint32_t bitrate)
__EXPORT void bootloader_app_shared_invalidate(void)
static void signal_callback(void *arg)
#define UAVCAN_DEVICE_PATH
static void cb_reboot(const uavcan::TimerEvent &)
__EXPORT int param_get(param_t param, void *val)
Copy the value of a parameter.
uavcan::uint32_t getUtcJumpCount()
Number of non-gradual adjustments performed so far.
static void busevent_signal_trampoline()
static SystemClock & instance()
Calls clock::init() as needed.
static void print_usage()
__EXPORT int bootloader_app_shared_read(bootloader_app_shared_t *shared, eRole_t role)
High-resolution timer with callouts and timekeeping.
int init_sim_controller(uavcan::INode &node)
Global flash based parameter store.
UavcanNode(uavcan::ICanDriver &can_driver, uavcan::ISystemClock &system_clock)
void init()
Activates/configures the hardware registers.
bool handleRestartRequest(uavcan::NodeID request_source) override
__EXPORT void bootloader_app_shared_write(bootloader_app_shared_t *shared, eRole_t role)
void cb_beginfirmware_update(const uavcan::ReceivedDataStructure< UavcanNode::BeginFirmwareUpdate::Request > &req, uavcan::ServiceResponseDataStructure< UavcanNode::BeginFirmwareUpdate::Response > &rsp)
__EXPORT int uavcannode_start(int argc, char *argv[])
uavcan::UtcTime getUtc()
Returns UTC time if it has been set, otherwise returns zero time.
Simple error/warning functions, heavily inspired by the BSD functions of the same names...
__EXPORT void hrt_call_every(struct hrt_call *entry, hrt_abstime delay, hrt_abstime interval, hrt_callout callout, void *arg)
Call callout(arg) after delay, and then after every interval.
#define APP_DESCRIPTOR_SIGNATURE
const char * px4_firmware_version_string(void)
Firmware version as human readable string (git tag)
__EXPORT param_t param_find(const char *name)
Look up a parameter by name.
Tools for system version detection.
static UavcanNode * _instance
singleton pointer
int init_indication_controller(uavcan::INode &node)
uavcan::MethodBinder< UavcanNode *, void(UavcanNode::*)(const uavcan::ReceivedDataStructure< UavcanNode::BeginFirmwareUpdate::Request > &, uavcan::ServiceResponseDataStructure< UavcanNode::BeginFirmwareUpdate::Response > &)> BeginFirmwareUpdateCallBack
static UavcanNode * instance()
struct @83::@85::@87 file
boot_app_shared_section app_descriptor_t AppDescriptor
bool isUtcLocked()
Whether UTC is synchronized and locked.
#define boot_app_shared_section
void rgb_led(int r, int g, int b, int freqs)
virtual int ioctl(file *filp, int cmd, unsigned long arg)
uint8_t signature[sizeof(uint64_t)]
__EXPORT int uavcannode_main(int argc, char *argv[])
RestartRequestHandler restart_request_handler
__EXPORT void hrt_cancel(struct hrt_call *entry)
Remove the entry from the callout list.