CCS Tutorial: Setting up the Environment

This post shows how to configure a project environment for building software for the C6713 DSK in TI Code Composer Studio (CCS) 6. The steps are similar regardless of the version of CCS being used, but the screen captures show the Eclipse-based IDE that was adopted by TI in recent releases of CCS. When creating any project for the C6713DSK, this procedure should be completed in the begging to ensure that all necessary libraries are included.

To begin, first create a new project for the C6713 DSK. After the project has been created, right-click on the new project in the Project Explorer area in the left menu pane, and select properties from the drop down menu. The Project Explorer pane is show below:


project

The C header-file include paths, C linkable libraries, and the DSP chipset must be specified so that the build tools can find all of the necessary files. After the project properties menu opens, under the Build section, navigate to C6000 compiler, and then to Include Options. Set the path to the directory where the C6000 Chip Set Library (CSL) was installed. I installed the CSL to C:\TI\C6xCSL on my workstation.

csl_include

 

The Chip Support Library is available for free from Texas Instruments and provides many helpful macros for defining registers as well as various masks and macro routines for manipulating the contents of the registers. The Board Support Library (BSL) include files from the board vendor–Spectrum Digital in the case of the C6713 DSK–must also be specified. Add another directory path for the BSL include files:

dsk_include

After adding all of the include files, under the C6000 compiler section, navigate to the advanced options sub menu, and then to predefined symbols. The compiler needs to know which chipset the project will use as its target, so create a new symbol and enter CHIP_6713, as shown below:

chip_set

Now, under the Build section, in the C6000 linker sub section, the BSL linkable file and path to the BSL must be specified. In the File Search Path pane, first add a new directory path to the search path. For my installation of the BSL, the path is C:\TI\DSK6713\c6000\dsk6713\lib.

lib_path

 

Finally, the linkable library for the BSL needs to be explicitly called out so the C6000 linker knows where the BSL code is located. The BSL file is dsk6713bsl.lib, and it is installed at C:\TI\DSK6713\c6000\dsk6713\lib.

dsk_lib

 

The project is now setup so that the CSL and BSL can be used to make working with the C6713 more easy and more pleasant. Any other third-party libraries to be included should be setup in this manner.

Disable console bell in FreeBSD

I use Bash and frequently utilize tab completion. On my FreeBSD, when there are multiple options during tab completion, the annoying console bell rings. For C programmers, it is the ‘\a’ that you included in your printf() calls when first learning C to drive others crazy.

To disable it, as root user you can run:

# sysctl hw.syscons.bell=0
hw.syscons.bel;: 1-> 0

Add that command to /etc/sysctl.conf to permanently disable it.  Good riddance!

Erlang Programming Exercise 12-3: The Database Server as an Application

First create an OTP Application directory structure. The work flow resembles something like the following if you’re on UNIX.

cd ~/work/erlang
mkdir ~/work/erlang/chapter12/{src,ebin,include,priv}
cp db_server_otp.erl db_server_sup.erl ~/work/erlang/chapter12/src
cd ~/work/erlang/chapter12/src
erlc *.erl
mv *.beam ../ebin

With the source code and BEAM files ready, now create an app file, db_server_app.erl:

-module(db_server_app).
-export([start/2,stop/1]).
-behavior(application).

start(_Type, _StartArgs) ->
    db_server_sup:start().

stop(_State) ->
    ok.

Compile this code and then move the BEAM file to the ebin folder. Create an application resource file describing the application, db_server.app in the ebin folder:

{application,
 db_server,
 [{description, "Erlang Prgramming Ch. 12 DB Server"},
  {vsn, "1.0"},
  {modules, [db_server_otp, db_server_sup, db_server_app]},
  {registered, [db_server_sup]},
  {applications, [kernel, stdlib]},
  {env, []},
  {mod, {db_server_app, []}}
 ]
}.

The final directory structure should look like this:

~/work/erlang/chapter12$ ls -1
ebin
include
priv
src
~/work/erlang/chapter12$ ls -1 ebin
db_server.app
db_server_app.beam
db_server_otp.beam
db_server_sup.beam
~/work/erlang/chapter12$ ls -1 src
db_server_app.erl
db_server_otp.erl
db_server_sup.erl

With the BEAM files and app files in the ebin directory, the application can now be tested with the Erlang shell.

Erlang R13B03 (erts-5.7.4)  [64-bit] [smp:8:2] [rq:8] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.7.4  (abort with ^G)
1> code:add_path("/home/bryan/work/erlang/chapter12/ebin").
true
2> application:start(db_server).                               
ok
3> db_server_otp:write("Ted", "7").
ok
4> db_server_otp:read("Ted").
{ok,"7"}
5> application:stop(db_server).
ok

=INFO REPORT==== 3-Nov-2011::16:32:08 ===
    application: db_server
    exited: stopped
    type: temporary
6> whereis(db_server_sup).
undefined

Success! (Note: this was much easier than the first time I tried to get a Tomcat servlet working…)

Erlang Proramming Exercise 12-2: Supervising the Database Server


-module(db_server_sup).
-export([start/0,init/1]).
-behavior(supervisor).

start() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init(_Arguments) ->
    DbServerOtp = {db_server_otp,                %% Id
                   {db_server_otp, start, []},   %% child process
                   permanent,                    %% restart 
                   30000,                        %% shutdown (ms)
                   worker,                       %% type
                   [db_server_otp]},             %% required modules
    {ok, 
     {{one_for_all,           %% terminate all children and restart
       5,                     %% max of n restarts in MaxSeconds
       3600},                 %% MaxSeconds (s)
      [DbServerOtp]}}.        %% child process list

EP Exercise 12-1: Database Server Revisited

-module(db_server_otp).
-export([start/0,stop/0]).
-export([write/2,read/1,delete/1,match/1]).
-export([init/1,terminate/2,handle_cast/2,handle_call/3]).
-behavior(gen_server).

%%
%% Operations & Maintenance API
%%

start() ->
    gen_server:start({local, ?MODULE}, ?MODULE, [], []).


stop() ->
    gen_server:cast(?MODULE, stop).

%%
%% DB Server API
%%

write(Key, Data) ->
    gen_server:call(?MODULE, {write, Key, Data}).

read(Key) ->
    gen_server:call(?MODULE, {read, Key}).

delete(Key) ->
    gen_server:call(?MODULE, {delete, Key}).

match(Element) ->
    gen_server:call(?MODULE, {match, Element}).

%%
%% OTP gen_server Callback Functions
%%


init(_Arguments) ->
    {ok, []}.

terminate(_Reason, _LoopData) ->
    ok.

handle_cast(stop, LoopData) ->
    {stop, normal, LoopData}.

handle_call({write, Key, Data}, _From, LoopData) ->
    case lists:keymember(Key, 1, LoopData) of
        true ->
            NewLoopData = lists:keyreplace(Key, 1, LoopData, {Key, Data}),
            Reply = ok;
        false ->
            NewLoopData = LoopData ++ [{Key, Data}],
            Reply = ok
    end,
    {reply, Reply, NewLoopData};
handle_call({read, Key}, _From, LoopData) ->
    case lists:keymember(Key, 1, LoopData) of
        true ->
            {_, Value} = lists:keyfind(Key, 1, LoopData),
            Reply = {ok, Value};
        false ->
            Reply = {error, instance}
    end,
    {reply, Reply, LoopData};

handle_call({delete, Key}, _From, LoopData) ->
    case lists:keymember(Key, 1, LoopData) of
        true ->
            NewLoopData = lists:keydelete(Key, 1, LoopData),
            Reply = ok;
        false ->
            NewLoopData = LoopData,
            Reply = ok
    end,
    {reply, Reply, NewLoopData};

handle_call({match, Element}, _From, LoopData) ->
    Matches = lists:filter(
                fun({_ ,Value}) ->
                  if 
                     Value =:= Element -> true;
                     true -> false
                  end end, 
                LoopData),
   Reply = get_db_keys(Matches, []),
   {reply, Reply, LoopData}.
                                   

get_db_keys([], KeyList) -> KeyList;
get_db_keys(ListOfTuples, KeyList) ->
    [H|T] = ListOfTuples,
    {Key, _} = H,
    get_db_keys(T, KeyList ++ [Key]).

EP Exercise 5-1: A Database Server


-module(db_server).
-export([start/0,stop/0,upgrade/1,code_upgrade/0]).
-export([write/2,read/1,delete/1]).
-export([init/0,loop/1]).
-vsn(1.0).

start() ->
    register(deb_server, spawn(db_server, init, [])).

stop() ->
    db_server ! stop.

upgrade(Data) ->
    db_server ! {upgrade, Data}.

write(Key, Data) ->
    db_server ! {write, Key, Data}.

read(Key) ->
    db_server ! {read, self(), Key},
    receive Reply ->
             Reply end.

delete(Key) ->
    db_server ! {delete, Key}.

code_upgrade(Data) ->
    db_server ! {code_upgrade, Data}.

init() ->
    loop(db:new()).

loop(Db) ->
    receive
        {write, Key, Data} ->
            loop(db:write(Key, Data, Db));
        {read, Pid, Key} ->
            Pid ! db:read(Key, Db),
            loop(Db);
        {delete, Key} ->
            loop(db:delete(Key, Db));
        {upgrade, Data} ->
            NewDb = db:convert(Data, Db),
            db_server:loop(NewDb);
        code_upgrade ->
            loop(db:code_upgrade(Data));
        stop ->
            db:destroy(Db)
    end.

EP Exercise 4-2: The Process Ring

My solution for Exercise 4-2 in the book Erlang Programming

%%
%% Erlang Programming Exercise 4-2
%%

-module(ring).
-export([start/3,create_node/3,stop/0]).

create_node(M,N,Msg) ->
    io:format("Creating node ~w (~w)~n", [N,self()]),
    if  
        N-1 > 0  -> NextPid = spawn(ring,create_node,[M,N-1,Msg]);
        N-1 == 0 -> NextPid = head
    end,
    print_m_times(NextPid,N,Msg,M),
    loop(NextPid).

start(M, N, Msg) ->
    io:format("Spawning ~w nodes!~n",[N]),
    Pid = spawn(ring,create_node,[M,N,Msg]),
    register(head, Pid),
    ok. 

stop() ->
    head ! quit,
    ok. 

loop(NextPid) ->
    receive
        {print, Pid, NodeNum, MsgContents} when Pid /= self() ->  
            io:format("(~w) msg from node ~w: ~s~n",[self(),NodeNum,MsgContents]),
            NextPid ! {print, Pid, NodeNum, MsgContents},
            loop(NextPid);
        quit ->  
            NextPid ! quit,
            io:format("Destroying node (~w)~n", [self()]),
            true
    end.

print_m_times(_,_,_,0) ->
    true;
print_m_times(NextPid,FromNode,Msg,M_Times) ->
    NextPid ! {print, self(), FromNode, Msg},
    print_m_times(NextPid,FromNode,Msg,M_Times-1).