Using Emacs with VxWorks
Table of Contents
- 1. How To Use This Document
- 2. License
- 3. Change History – What’s New
- 4. Getting Started
- 5. vxworks.el
- 6. What can we do?
- 6.1. Create a VIP
- 6.2. Configure a VIP
- 6.3. Build a VIP
- 6.4. Create a DKM
- 6.5. Build a DKM
- 6.6. Configure a VSB
- 6.7. Build a VSB
- 6.8. Associate DKM with VIP
- 6.9. Recompile an individual VSB file
- 6.10. Use GTAGS to find source code
- 6.11. Use GTAGS with Semantic
- 6.12. Autocomplete VxWorks code
- 6.13. Wind River code formatting
- 6.14. TODO Debugging VxWorks code with GDB
- 6.15. TODO yasnippet VxWorks code
VxWorks is a Real Time Operating System built by Wind River. Although VxWorks code can be developed from within the Workbench Eclipse environment, this documents how to develop VxWorks code from within Emacs. The advantages of this are better tools are available at your fingertips, rather than unwieldy tools available with a mouse move.
Speeding up the development environment and benefiting from increased efficiencies mean reduced software development costs
This code is specific to VxWorks 7, but I have had it working on all other versions of VxWorks (6.x, 653 and even Tornado). For this you will need to replace the build lines with vxprj or make.
1 How To Use This Document
This document assumes you know what VxWorks and Wind River Workbench is and how to use these tools.
You have to understand what a VIP and a VSB is, as well as what Emacs is and how you might add elisp into your .emacs file to configure initialisation.
Note this this is a live document and I will be adding more features as time goes on. For now its just a great way to keep my hands on the keyboard whilst building code. I need to get GDB working to make
things truly brilliant though.
If you have any questions or comments, please let me know. I am happy to send people on-site to help with your specific VxWorks/Embedded Linux issues.
Note I got the idea and some structure of this document from Bernt Hansens’ fabulous org-mode.org document:
Finally, this is my first pass at Emacs Lisp so please let me know if there is any way I can improve things.
Copyright (C) 2015 Harmonic Software Systems Ltd Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. Code in this document is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
The code examples and CSS style sheets are licensed under the GNU General Public License v3 or later
3 Change History – What’s New
This is the first release, version v0.01
4 Getting Started
This is all about emacs and VxWorks 7 integration on a Windows host. I haven’t tried it on a Linux host but things should still work.
To get Emacs to navigate and build VxWorks code can be abit tricky – but I think it is worth it to be able to get fast work-flows building and navigating source code.
The VxWorks command line build environment on Windows requires a DOS shell, it wont work under cygwin.
You will need to use GNU Global, generate a GTAGS file and the reconfigure emacs to use ecb, gtags, semantic and auto-complete:
4.1 Install GNU Global
Currently I use a WIN32 build of GNU Global. This will be used to parse the source code and to create GTAGS files. Emacs can then use these files for funky navigation of the source code.
Download W32 GNU global:
copy into Program Files (x86) and manually added to the path.
4.2 Create GTAGS from Windows Batch File
The following batch file will create a list of files for gtags to parse, and then create the gtags files. Execute this
generate-gtags.bat file from the Wind River installation directory (i.e. WINDBASE)
REM generate list of files that GTAGS can search dir /S /A-D /B vxworks-7*.c > gtags-files.txt dir /S /A-D /B vxworks-7*.h >> gtags-files.txt dir /S /A-D /B vxworks-7*.cdf >> gtags-files.txt dir /S /A-D /B vxworks-7*.vsbl >> gtags-files.txt dir /S /A-D /B vxworks-7*.s >> gtags-files.txt dir /S /A-D /B workspace*.c >> gtags-files.txt dir /S /A-D /B workspace*.h >> gtags-files.txt dir /S /A-D /B workspace*.cdf >> gtags-files.txt gtags -v -f gtags-files.txt
4.3 Emacs Configuration
I have a Win-64 bit build of Emacs, v24.5.1, from here:
I set the following up to make Emacs a powerful IDE for code building and browsing.
4.3.1 Emacs Code Browser
Emacs Code Browser gives emacs a brilliant build environment, allowing build windows to popup as well as file and function windows.
The ECB in melpa stable seems to be old and didn’t work for me. It wouldn’t install and build on my Windows machine.
A manual install is easy from here :
(add-to-list 'load-path "~/.emacs.d/lisp/ecb-master") (require 'ecb)
Enabling Emacs to work with GNU Global.
I have gtags.el installed, which I think came from the original gnu global installation.
(setq gtags-suggested-key-mapping t) (setq load-path (cons "~/.emacs.d/lisp" load-path)) (autoload 'gtags-mode "gtags" "" t) (add-hook 'c-mode-hook (lambda () (gtags-mode 1))) (global-set-key "M-]" 'gtags-find-tag-from-here) (global-set-key "M-[" 'gtags-pop-stack) (global-set-key "M-#" 'gtags-find-rtag)
I also have some code to update GTAGS for a single file change. Note that this can cause problems if there is no gtags file. (I think ggtags is more robust, but I haven’t tried it yet)
;; ;; get gtags to update for new files ;; (defun gtags-root-dir () "Returns GTAGS root directory or nil if doesn't exist." (with-temp-buffer (if (zerop (call-process "global" nil t nil "-pr")) (buffer-substring (point-min) (1- (point-max))) nil))) (defun gtags-update-single(filename) "Update Gtags database for changes in a single file" (interactive) (start-process "update-gtags" "update-gtags" "cmd" "-c" (concat "cd " (gtags-root-dir) " ; gtags --single-update " filename ))) (defun gtags-update-current-file() (interactive) (defvar filename) (setq filename (replace-regexp-in-string (gtags-root-dir) "." (buffer-file-name (current-buffer)))) (gtags-update-single filename) (message "Gtags updated for %s" filename)) (defun gtags-update-hook() "Update GTAGS file incrementally upon saving a file" (when (bound-and-true-p gtags-mode) (when (gtags-root-dir) (gtags-update-current-file)))) (add-hook 'after-save-hook 'gtags-update-hook)
4.3.3 Semantic and Auto-complete
This is where all the code searching magic happens.
Semantic is built in, but I have added some config code to allow for deep recursive searches, as well as to allow semantic to use the tags files, so I actually have two ways to navigate the source code (gtags and semantic)
With semantic-goto-definition and semantic-pop-tag-mark I can easily drill into source code, and then pop back out again.
And with semantic-ia-show-doc I can snarf the docs from the function comments and with semantic-ia-show-summary I can see the function arguments in the modeline.
Auto-complete v1.5.0 is built-into emacs. Configuring it to use semantic allows all the task in the entire vxworks source code to be used. Hello Intellisense!
I turn it on with this:
This is my complete semantic setup:
(semantic-mode 1) (global-ede-mode 1) ;; turn on idle time semantic scheduling of current buffer (global-semantic-idle-scheduler-mode 1) (global-semantic-idle-completions-mode 1) ;; ;; add semantic as a backend to auto complete and hook into c-mode-common-hook ;; (defun ed-add-semantic-to-autocomplete () (add-to-list 'ac-sources 'ac-source-semantic)) (add-hook 'c-mode-common-hook 'ed-add-semantic-to-autocomplete) ;; ;; enable support for gnu global ;; (semanticdb-enable-gnu-global-databases 'c-mode) (semanticdb-enable-gnu-global-databases 'c++-mode) ;; ;; semantic push and pop routines ;; (defvar semantic-tags-location-ring (make-ring 20)) (defun semantic-goto-definition (point) "Goto definition using semantic-ia-fast-jump save the pointer marker if tag is found" (interactive "d") (condition-case err (progn (ring-insert semantic-tags-location-ring (point-marker)) (semantic-ia-fast-jump point)) (error ;;if not found remove the tag saved in the ring (set-marker (ring-remove semantic-tags-location-ring 0) nil nil) (signal (car err) (cdr err))))) (defun semantic-pop-tag-mark () "popup the tag save by semantic-goto-definition" (interactive) (if (ring-empty-p semantic-tags-location-ring) (message "%s" "No more tags available") (let* ((marker (ring-remove semantic-tags-location-ring 0)) (buff (marker-buffer marker)) (pos (marker-position marker))) (if (not buff) (message "Buffer has been deleted") (switch-to-buffer buff) (goto-char pos)) (set-marker marker nil nil)))) ;; ;; had to hack gtags.el to remove gtags-find-tag binding for this to work ;; (global-set-key "M-." 'semantic-goto-definition) (global-set-key "M-," 'semantic-pop-tag-mark) (global-set-key "M-/" 'semantic-ia-show-doc) (global-set-key "C-c/" 'semantic-ia-show-summary)
4.3.4 Wind River code formatting
The following code allows emacs to reformat any code Wind River style.
Just mark the code block or file, and =C-M- (M-x indent-region)
(defconst wrs-c-style '((c-tab-always-indent . t) (c-comment-only-line-offset . 0) (c-hanging-braces-alist . ((substatement-open after) (brace-list-open))) (c-hanging-colons-alist . ((member-init-intro before) (inher-intro) (case-label after) (label after) (access-label after))) (c-cleanup-list . (scope-operator empty-defun-braces defun-close-semi)) (c-offsets-alist . ((arglist-close . c-lineup-arglist-close-under-paren) (topmost-intro . 0) (topmost-intro-cont . 4) (class-open . 4) (class-close . 4) (defun-open . 4) (defun-close . 0) (defun-block-intro . 0) (substatement-open . 4) (brace-list-open . 4) (statement-block-intro . 0) (case-label . 0) (statement-case-intro . 4) (block-open . 0) (arglist-intro . 0) (knr-argdecl-intro . -))) (c-echo-syntactic-information-p . t) ) "WRS Programming Style") ;; offset customizations not in my-c-style (setq c-offsets-alist '((member-init-intro . ++))) ;; Customizations for all modes in CC Mode. (defun my-c-mode-common-hook () (c-add-style "WRS" wrs-c-style t) (setq tab-width 4 ;; this will make sure spaces are used instead of tabs indent-tabs-mode nil) (define-key c-mode-base-map "C-m" 'c-context-line-break) ) (add-hook 'c-mode-common-hook 'my-c-mode-common-hook)
In addition to the emacs config, there is an elisp library that allows VxWorks Image Projects (VIP) Downloadable Kernel Modules (DKM) and VxWorks Source Build Projects (VSB) to be built and configured.
5.1.1 Setup the vxworks environment file
Two emacs lisp files are required:
a. vxworks.el – general lisp functions
b. vxworks7env.el – specific setup for a vxworks 7 installation
The vxworks7env.el file should be checked with your specific VxWorks installation, as compiler versions could have changed.
To do this, open a vxworks development shell and type:
wrenv -p vxworks-7 -o print_env
Make sure the the environment in the shell matches the environment setup in vxworks7env.el. Could probably write some lisp code to execute this and generate the env file automatically, but for now this is a manual process.
5.1.2 Edit .emacs
Add the following to your .emacs file:
(load-file "<path-to-file>/vxworks.el") (setq vxworks-install-dir "<your vxworks install dir - with a trailing slash!>") (setq vxworks-workspace-dir "<your workspace directory - with a trailing slash!>") (setup-vxworks-7-env)
(load-file "~/.emacs.d/lisp/vxworks.el") (setq vxworks-install-dir "C:/WindRiver_vxw7.0/") (setq vxworks-workspace-dir "C:/WindRiver_vxw7.0/workspace/") (setup-vxworks-7-env)
If you don’t set vxworks-install-dir you will be asked for it at startup.