[修改] 增加freeRTOS
1. 版本FreeRTOSv202212.01,命名为kernel;
This commit is contained in:
30
kernel/FreeRTOS-Plus/Source/FreeRTOS-Cellular-Interface/test/unit-test/CMock/.gitattributes
vendored
Normal file
30
kernel/FreeRTOS-Plus/Source/FreeRTOS-Cellular-Interface/test/unit-test/CMock/.gitattributes
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
* text=auto
|
||||
|
||||
# These files are text and should be normalized (convert crlf to lf)
|
||||
*.rb text
|
||||
*.test text
|
||||
*.c text
|
||||
*.cpp text
|
||||
*.h text
|
||||
*.txt text
|
||||
*.yml text
|
||||
*.s79 text
|
||||
*.bat text
|
||||
*.xcl text
|
||||
*.inc text
|
||||
*.info text
|
||||
*.md text
|
||||
makefile text
|
||||
rakefile text
|
||||
|
||||
|
||||
#These files are binary and should not be normalized
|
||||
*.doc binary
|
||||
*.odt binary
|
||||
*.pdf binary
|
||||
*.ewd binary
|
||||
*.eww binary
|
||||
*.dni binary
|
||||
*.wsdt binary
|
||||
*.dbgdt binary
|
||||
*.mac binary
|
||||
@ -0,0 +1,42 @@
|
||||
---
|
||||
# Continuous Integration Workflow: Test case suite run + validation build check
|
||||
name: CI
|
||||
|
||||
# Controls when the action will run.
|
||||
# Triggers the workflow on push or pull request events but only for the master branch
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
# Job: Unit test suite
|
||||
unit-tests:
|
||||
name: "Unit Tests"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Install Multilib
|
||||
- name: Install Multilib
|
||||
run: |
|
||||
sudo apt-get update --assume-yes
|
||||
sudo apt-get install --assume-yes --quiet gcc-multilib
|
||||
|
||||
# Checks out repository under $GITHUB_WORKSPACE
|
||||
- name: Checkout Latest Repo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
# Install Ruby Testing Tools
|
||||
- name: Setup Ruby Testing Tools
|
||||
run: |
|
||||
sudo gem install bundler
|
||||
sudo gem install rspec
|
||||
sudo gem install rubocop -v 0.57.2
|
||||
bundle install
|
||||
|
||||
# Run Tests
|
||||
- name: Run All Unit Tests
|
||||
run: |
|
||||
cd test && rake ci
|
||||
10
kernel/FreeRTOS-Plus/Source/FreeRTOS-Cellular-Interface/test/unit-test/CMock/.gitignore
vendored
Normal file
10
kernel/FreeRTOS-Plus/Source/FreeRTOS-Cellular-Interface/test/unit-test/CMock/.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
test/system/build
|
||||
test/system/generated
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
Gemfile.lock
|
||||
.rake_t_cache
|
||||
.DS_Store
|
||||
*.swp
|
||||
examples/make_example/build
|
||||
examples/temp_sensor/build
|
||||
8
kernel/FreeRTOS-Plus/Source/FreeRTOS-Cellular-Interface/test/unit-test/CMock/.gitmodules
vendored
Normal file
8
kernel/FreeRTOS-Plus/Source/FreeRTOS-Cellular-Interface/test/unit-test/CMock/.gitmodules
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
[submodule "vendor/unity"]
|
||||
path = vendor/unity
|
||||
url = https://github.com/throwtheswitch/unity.git
|
||||
branch = master
|
||||
[submodule "vendor/c_exception"]
|
||||
path = vendor/c_exception
|
||||
url = https://github.com/throwtheswitch/cexception.git
|
||||
branch = master
|
||||
@ -0,0 +1,8 @@
|
||||
source "http://rubygems.org/"
|
||||
|
||||
gem "bundler"
|
||||
gem "rake"
|
||||
gem "minitest"
|
||||
gem "require_all"
|
||||
gem "constructor"
|
||||
gem "diy"
|
||||
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@ -0,0 +1,39 @@
|
||||
CMock 
|
||||
=====
|
||||
CMock is a mock and stub generator and runtime for unit testing C. It's been designed
|
||||
to work smoothly with Unity Test, another of the embedded-software testing tools
|
||||
developed by ThrowTheSwitch.org. CMock automagically parses your C headers and creates
|
||||
useful and usable mock interfaces for unit testing. Give it a try!
|
||||
|
||||
If you don't care to manage unit testing builds yourself, consider checking out Ceedling,
|
||||
a test-centered build manager for unit testing C code.
|
||||
|
||||
Getting Started
|
||||
================
|
||||
|
||||
If you're using Ceedling, there is no need to install CMock. It will handle it for you.
|
||||
For everyone else, the simplest way is to grab it off github. You can also download it
|
||||
as a zip if you prefer. The Github method looks something like this:
|
||||
|
||||
> git clone --recursive https://github.com/throwtheswitch/cmock.git
|
||||
> cd cmock
|
||||
> bundle install # Ensures you have all RubyGems needed
|
||||
|
||||
If you plan to help with the development of CMock (or just want to verify that it can
|
||||
perform its self tests on your system) then you can enter the test directory and then
|
||||
ask it to test:
|
||||
|
||||
> cd test
|
||||
> rake # Run all CMock self tests
|
||||
|
||||
API Documentation
|
||||
=================
|
||||
|
||||
* Not sure what you're doing?
|
||||
* [View docs/CMock_Summary.md](docs/CMock_Summary.md)
|
||||
* Interested in our MIT-style license?
|
||||
* [View docs/license.txt](docs/license.txt)
|
||||
* Are there examples?
|
||||
* They are all in [/examples](examples/)
|
||||
* Any other resources to check out?
|
||||
* Definitely! Check out our developer portal on [ThrowTheSwitch.org](http://throwtheswitch.org)
|
||||
@ -0,0 +1,12 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
# Setup our load path:
|
||||
[
|
||||
'lib'
|
||||
].each do |dir|
|
||||
$:.unshift(File.join(__dir__ + '/../', dir))
|
||||
end
|
||||
@ -0,0 +1,16 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
# Setup our load path:
|
||||
[
|
||||
'./lib',
|
||||
'./vendor/behaviors/lib',
|
||||
'./vendor/hardmock/lib',
|
||||
'./vendor/unity/auto/',
|
||||
'./test/system/'
|
||||
].each do |dir|
|
||||
$:.unshift(File.join(File.expand_path(File.dirname(__FILE__) + '/../'), dir))
|
||||
end
|
||||
@ -0,0 +1,831 @@
|
||||
CMock: A Summary
|
||||
================
|
||||
|
||||
*[ThrowTheSwitch.org](http://throwtheswitch.org)*
|
||||
|
||||
*This documentation is released under a Creative Commons 3.0 Attribution Share-Alike License*
|
||||
|
||||
|
||||
What Exactly Are We Talking About Here?
|
||||
---------------------------------------
|
||||
|
||||
CMock is a nice little tool which takes your header files and creates
|
||||
a Mock interface for it so that you can more easily unit test modules
|
||||
that touch other modules. For each function prototype in your
|
||||
header, like this one:
|
||||
|
||||
int DoesSomething(int a, int b);
|
||||
|
||||
|
||||
...you get an automatically generated DoesSomething function
|
||||
that you can link to instead of your real DoesSomething function.
|
||||
By using this Mocked version, you can then verify that it receives
|
||||
the data you want, and make it return whatever data you desire,
|
||||
make it throw errors when you want, and more... Create these for
|
||||
everything your latest real module touches, and you're suddenly
|
||||
in a position of power: You can control and verify every detail
|
||||
of your latest creation.
|
||||
|
||||
To make that easier, CMock also gives you a bunch of functions
|
||||
like the ones below, so you can tell that generated DoesSomething
|
||||
function how to behave for each test:
|
||||
|
||||
void DoesSomething_ExpectAndReturn(int a, int b, int toReturn);
|
||||
void DoesSomething_ExpectAndThrow(int a, int b, EXCEPTION_T error);
|
||||
void DoesSomething_StubWithCallback(CMOCK_DoesSomething_CALLBACK YourCallback);
|
||||
void DoesSomething_IgnoreAndReturn(int toReturn);
|
||||
|
||||
|
||||
You can pile a bunch of these back to back, and it remembers what
|
||||
you wanted to pass when, like so:
|
||||
|
||||
test_CallsDoesSomething_ShouldDoJustThat(void)
|
||||
{
|
||||
DoesSomething_ExpectAndReturn(1,2,3);
|
||||
DoesSomething_ExpectAndReturn(4,5,6);
|
||||
DoesSomething_ExpectAndThrow(7,8, STATUS_ERROR_OOPS);
|
||||
|
||||
CallsDoesSomething( );
|
||||
}
|
||||
|
||||
|
||||
This test will call CallsDoesSomething, which is the function
|
||||
we are testing. We are expecting that function to call DoesSomething
|
||||
three times. The first time, we check to make sure it's called
|
||||
as DoesSomething(1, 2) and we'll magically return a 3. The second
|
||||
time we check for DoesSomething(4, 5) and we'll return a 6. The
|
||||
third time we verify DoesSomething(7, 8) and we'll throw an error
|
||||
instead of returning anything. If CallsDoesSomething gets
|
||||
any of this wrong, it fails the test. It will fail if you didn't
|
||||
call DoesSomething enough, or too much, or with the wrong arguments,
|
||||
or in the wrong order.
|
||||
|
||||
CMock is based on Unity, which it uses for all internal testing.
|
||||
It uses Ruby to do all the main work (versions 2.0.0 and above).
|
||||
|
||||
|
||||
Installing
|
||||
==========
|
||||
|
||||
The first thing you need to do to install CMock is to get yourself
|
||||
a copy of Ruby. If you're on linux or osx, you probably already
|
||||
have it. You can prove it by typing the following:
|
||||
|
||||
ruby --version
|
||||
|
||||
|
||||
If it replied in a way that implies ignorance, then you're going to
|
||||
need to install it. You can go to [ruby-lang](https://ruby-lang.org)
|
||||
to get the latest version. You're also going to need to do that if it
|
||||
replied with a version that is older than 2.0.0. Go ahead. We'll wait.
|
||||
|
||||
Once you have Ruby, you have three options:
|
||||
|
||||
* Clone the latest [CMock repo on github](https://github.com/ThrowTheSwitch/CMock/)
|
||||
* Download the latest [CMock zip from github](https://github.com/ThrowTheSwitch/CMock/)
|
||||
* Install Ceedling (which has it built in!) through your commandline using `gem install ceedling`.
|
||||
|
||||
|
||||
Generated Mock Module Summary
|
||||
=============================
|
||||
|
||||
In addition to the mocks themselves, CMock will generate the
|
||||
following functions for use in your tests. The expect functions
|
||||
are always generated. The other functions are only generated
|
||||
if those plugins are enabled:
|
||||
|
||||
|
||||
Expect:
|
||||
-------
|
||||
|
||||
Your basic staple Expects which will be used for most of your day
|
||||
to day CMock work. By calling this, you are telling CMock that you
|
||||
expect that function to be called during your test. It also specifies
|
||||
which arguments you expect it to be called with, and what return
|
||||
value you want returned when that happens. You can call this function
|
||||
multiple times back to back in order to queue up multiple calls.
|
||||
|
||||
* `void func(void)` => `void func_Expect(void)`
|
||||
* `void func(params)` => `void func_Expect(expected_params)`
|
||||
* `retval func(void)` => `void func_ExpectAndReturn(retval_to_return)`
|
||||
* `retval func(params)` => `void func_ExpectAndReturn(expected_params, retval_to_return)`
|
||||
|
||||
|
||||
ExpectAnyArgs:
|
||||
--------------
|
||||
|
||||
This behaves just like the Expects calls, except that it doesn't really
|
||||
care what the arguments are that the mock gets called with. It still counts
|
||||
the number of times the mock is called and it still handles return values
|
||||
if there are some. Note that an ExpectAnyArgs call is not generated for
|
||||
functions that have no arguments, because it would act exactly like the existing
|
||||
Expect and ExpectAndReturn calls.
|
||||
|
||||
* `void func(params)` => `void func_ExpectAnyArgs(void)`
|
||||
* `retval func(params)` => `void func_ExpectAnyArgsAndReturn(retval_to_return)`
|
||||
|
||||
|
||||
Array:
|
||||
------
|
||||
|
||||
An ExpectWithArray is another variant of Expect. Like expect, it cares about
|
||||
the number of times a mock is called, the arguments it is called with, and the
|
||||
values it is to return. This variant has another feature, though. For anything
|
||||
that resembles a pointer or array, it breaks the argument into TWO arguments.
|
||||
The first is the original pointer. The second specify the number of elements
|
||||
it is to verify of that array. If you specify 1, it'll check one object. If 2,
|
||||
it'll assume your pointer is pointing at the first of two elements in an array.
|
||||
If you specify zero elements, it will check just the pointer if
|
||||
`:smart` mode is configured or fail if `:compare_data` is set.
|
||||
|
||||
* `void func(void)` => (nothing. In fact, an additional function is only generated if the params list contains pointers)
|
||||
* `void func(ptr * param, other)` => `void func_ExpectWithArray(ptr* param, int param_depth, other)`
|
||||
* `retval func(void)` => (nothing. In fact, an additional function is only generated if the params list contains pointers)
|
||||
* `retval func(other, ptr* param)` => `void func_ExpectWithArrayAndReturn(other, ptr* param, int param_depth, retval_to_return)`
|
||||
|
||||
|
||||
Ignore:
|
||||
-------
|
||||
|
||||
Maybe you don't care about the number of times a particular function is called or
|
||||
the actual arguments it is called with. In that case, you want to use Ignore. Ignore
|
||||
only needs to be called once per test. It will then ignore any further calls to that
|
||||
particular mock. The IgnoreAndReturn works similarly, except that it has the added
|
||||
benefit of knowing what to return when that call happens. If the mock is called more
|
||||
times than IgnoreAndReturn was called, it will keep returning the last value without
|
||||
complaint. If it's called fewer times, it will also ignore that. You SAID you didn't
|
||||
care how many times it was called, right?
|
||||
|
||||
* `void func(void)` => `void func_Ignore(void)`
|
||||
* `void func(params)` => `void func_Ignore(void)`
|
||||
* `retval func(void)` => `void func_IgnoreAndReturn(retval_to_return)`
|
||||
* `retval func(params)` => `void func_IgnoreAndReturn(retval_to_return)`
|
||||
|
||||
StopIgnore:
|
||||
-------
|
||||
|
||||
Maybe you want to ignore a particular function for part of a test but dont want to
|
||||
ignore it later on. In that case, you want to use StopIgnore which will cancel the
|
||||
previously called Ignore or IgnoreAndReturn requiring you to Expect or otherwise
|
||||
handle the call to a function.
|
||||
|
||||
* `void func(void)` => `void func_StopIgnore(void)`
|
||||
* `void func(params)` => `void func_StopIgnore(void)`
|
||||
* `retval func(void)` => `void func_StopIgnore(void)`
|
||||
* `retval func(params)` => `void func_StopIgnore(void)`
|
||||
|
||||
IgnoreStateless:
|
||||
----------------
|
||||
|
||||
This plugin is similar to the Ignore plugin, but the IgnoreAndReturn functions are
|
||||
stateless. So the Ignored function will always return the last specified return value
|
||||
and does not queue the return values as the IgnoreAndReturn of the default plugin will.
|
||||
|
||||
To stop ignoring a function you can call StopIgnore or simply overwrite the Ignore
|
||||
(resp. IgnoreAndReturn) with an Expect (resp. ExpectAndReturn). Note that calling
|
||||
Ignore (resp IgnoreAndReturn) will clear your previous called Expect
|
||||
(resp. ExpectAndReturn), so they are not restored after StopIgnore is called.
|
||||
|
||||
You can use this plugin by using `:ignore_stateless` instead of `:ignore` in your
|
||||
CMock configuration file.
|
||||
|
||||
The generated functions are the same as **Ignore** and **StopIgnore** above.
|
||||
|
||||
Ignore Arg:
|
||||
------------
|
||||
|
||||
Maybe you overall want to use Expect and its similar variations, but you don't care
|
||||
what is passed to a particular argument. This is particularly useful when that argument
|
||||
is a pointer to a value that is supposed to be filled in by the function. You don't want
|
||||
to use ExpectAnyArgs, because you still care about the other arguments. Instead, after
|
||||
an Expect call is made, you can call this function. It tells CMock to ignore
|
||||
a particular argument for the rest of this test, for this mock function. You may call
|
||||
multiple instances of this to ignore multiple arguments after each expectation if
|
||||
desired.
|
||||
|
||||
* `void func(params)` => `void func_IgnoreArg_paramName(void)`
|
||||
|
||||
|
||||
ReturnThruPtr:
|
||||
--------------
|
||||
|
||||
Another option which operates on a particular argument of a function is the ReturnThruPtr
|
||||
plugin. For every argument that resembles a pointer or reference, CMock generates an
|
||||
instance of this function. Just as the AndReturn functions support injecting one or more
|
||||
return values into a queue, this function lets you specify one or more return values which
|
||||
are queued up and copied into the space being pointed at each time the mock is called.
|
||||
|
||||
* `void func(param1)` => `void func_ReturnThruPtr_paramName(val_to_return)`
|
||||
* => `void func_ReturnArrayThruPtr_paramName(cal_to_return, len)`
|
||||
* => `void func_ReturnMemThruPtr_paramName(val_to_return, size)`
|
||||
|
||||
|
||||
Callback:
|
||||
---------
|
||||
|
||||
If all those other options don't work, and you really need to do something custom, you
|
||||
still have a choice. As soon as you stub a callback in a test, it will call the callback
|
||||
whenever the mock is encountered and return the retval returned from the callback (if any).
|
||||
|
||||
* `void func(void)` => `void func_[AddCallback,Stub](CMOCK_func_CALLBACK callback)`
|
||||
where `CMOCK_func_CALLBACK` looks like: `void func(int NumCalls)`
|
||||
* `void func(params)` => `void func_[AddCallback,Stub](CMOCK_func_CALLBACK callback)`
|
||||
where `CMOCK_func_CALLBACK` looks like: `void func(params, int NumCalls)`
|
||||
* `retval func(void)` => `void func_[AddCallback,Stub](CMOCK_func_CALLBACK callback)`
|
||||
where `CMOCK_func_CALLBACK` looks like: `retval func(int NumCalls)`
|
||||
* `retval func(params)` => `void func_[AddCallback,Stub](CMOCK_func_CALLBACK callback)`
|
||||
where `CMOCK_func_CALLBACK` looks like: `retval func(params, int NumCalls)`
|
||||
|
||||
You can choose from two options:
|
||||
|
||||
* `func_AddCallback` tells the mock to check its arguments and calling
|
||||
order (based on any Expects you've set up) before calling the callback.
|
||||
* `func_Stub` tells the mock to skip all the normal checks and jump directly
|
||||
to the callback instead. In this case, you are replacing the normal mock calls
|
||||
with your own custom stub function.
|
||||
|
||||
There is also an older name, `func_StubWithCallback`, which is just an alias
|
||||
for either `func_AddCallback` or `func_Stub` depending on setting of the
|
||||
`:callback_after_arg_check` toggle. This is deprecated and we recommend using
|
||||
the two options above.
|
||||
|
||||
|
||||
Cexception:
|
||||
-----------
|
||||
|
||||
Finally, if you are using Cexception for error handling, you can use this to throw errors
|
||||
from inside mocks. Like Expects, it remembers which call was supposed to throw the error,
|
||||
and it still checks parameters first.
|
||||
|
||||
* `void func(void)` => `void func_ExpectAndThrow(value_to_throw)`
|
||||
* `void func(params)` => `void func_ExpectAndThrow(expected_params, value_to_throw)`
|
||||
* `retval func(void)` => `void func_ExpectAndThrow(value_to_throw)`
|
||||
* `retval func(params)` => `void func_ExpectAndThrow(expected_params, value_to_throw)`
|
||||
|
||||
|
||||
|
||||
Running CMock
|
||||
=============
|
||||
|
||||
CMock is a Ruby script and class. You can therefore use it directly
|
||||
from the command line, or include it in your own scripts or rakefiles.
|
||||
|
||||
|
||||
Mocking from the Command Line
|
||||
-----------------------------
|
||||
|
||||
After unpacking CMock, you will find cmock.rb in the 'lib' directory.
|
||||
This is the file that you want to run. It takes a list of header files
|
||||
to be mocked, as well as an optional yaml file for a more detailed
|
||||
configuration (see config options below).
|
||||
|
||||
For example, this will create three mocks using the configuration
|
||||
specified in MyConfig.yml:
|
||||
|
||||
ruby cmock.rb -oMyConfig.yml super.h duper.h awesome.h
|
||||
|
||||
And this will create two mocks using the default configuration:
|
||||
|
||||
ruby cmock.rb ../mocking/stuff/is/fun.h ../try/it/yourself.h
|
||||
|
||||
|
||||
Mocking From Scripts or Rake
|
||||
----------------------------
|
||||
|
||||
CMock can be used directly from your own scripts or from a rakefile.
|
||||
Start by including cmock.rb, then create an instance of CMock.
|
||||
When you create your instance, you may initialize it in one of
|
||||
three ways.
|
||||
|
||||
You may specify nothing, allowing it to run with default settings:
|
||||
|
||||
require 'cmock.rb'
|
||||
cmock = CMock.new
|
||||
|
||||
You may specify a YAML file containing the configuration options
|
||||
you desire:
|
||||
|
||||
cmock = CMock.new('../MyConfig.yml')
|
||||
|
||||
You may specify the options explicitly:
|
||||
|
||||
cmock = Cmock.new(:plugins => [:cexception, :ignore], :mock_path => 'my/mocks/')
|
||||
|
||||
Creating Skeletons:
|
||||
-------------------
|
||||
|
||||
Not only is CMock able to generate mock files from a header file, but it is also able
|
||||
to generate (and update) skeleton C files from headers. It does this by creating a
|
||||
(mostly) empty implementation for every function that is declared in the header. If you later
|
||||
add to that header list, just run this feature again and it will add prototypes for the missing
|
||||
functions!
|
||||
|
||||
Like the normal usecase for CMock, this feature can be used from the command line
|
||||
or from within its ruby API. For example, from the command line, add `--skeleton` to
|
||||
generate a skeleton instead:
|
||||
|
||||
```
|
||||
ruby cmock.rb --skeleton ../create/c/for/this.h
|
||||
```
|
||||
|
||||
Config Options:
|
||||
---------------
|
||||
|
||||
The following configuration options can be specified in the
|
||||
yaml file or directly when instantiating.
|
||||
|
||||
Passed as Ruby, they look like this:
|
||||
|
||||
{ :attributes => [“__funky”, “__intrinsic”], :when_ptr => :compare }
|
||||
|
||||
Defined in the yaml file, they look more like this:
|
||||
|
||||
:cmock:
|
||||
:attributes:
|
||||
- __funky
|
||||
- __intrinsic
|
||||
:when_ptr: :compare
|
||||
|
||||
In all cases, you can just include the things that you want to override
|
||||
from the defaults. We've tried to specify what the defaults are below.
|
||||
|
||||
* `:attributes`:
|
||||
These are attributes that CMock should ignore for you for testing
|
||||
purposes. Custom compiler extensions and externs are handy things to
|
||||
put here. If your compiler is choking on some extended syntax, this
|
||||
is often a good place to look.
|
||||
|
||||
* defaults: ['__ramfunc', '__irq', '__fiq', 'register', 'extern']
|
||||
* **note:** this option will reinsert these attributes onto the mock's calls.
|
||||
If that isn't what you are looking for, check out :strippables.
|
||||
|
||||
* `:c_calling_conventions`:
|
||||
Similarly, CMock may need to understand which C calling conventions
|
||||
might show up in your codebase. If it encounters something it doesn't
|
||||
recognize, it's not going to mock it. We have the most common covered,
|
||||
but there are many compilers out there, and therefore many other options.
|
||||
|
||||
* defaults: ['__stdcall', '__cdecl', '__fastcall']
|
||||
* **note:** this option will reinsert these attributes onto the mock's calls.
|
||||
If that isn't what you are looking for, check out :strippables.
|
||||
|
||||
* `:callback_after_arg_check`:
|
||||
Tell `:callback` plugin to do the normal argument checking **before** it
|
||||
calls the callback function by setting this to true. When false, the
|
||||
callback function is called **instead** of the argument verification.
|
||||
|
||||
* default: false
|
||||
|
||||
* `:callback_include_count`:
|
||||
Tell `:callback` plugin to include an extra parameter to specify the
|
||||
number of times the callback has been called. If set to false, the
|
||||
callback has the same interface as the mocked function. This can be
|
||||
handy when you're wanting to use callback as a stub.
|
||||
|
||||
* default: true
|
||||
|
||||
* `:cexception_include`:
|
||||
Tell `:cexception` plugin where to find CException.h... You only need to
|
||||
define this if it's not in your build path already... which it usually
|
||||
will be for the purpose of your builds.
|
||||
|
||||
* default: *nil*
|
||||
|
||||
* `:enforce_strict_ordering`:
|
||||
CMock always enforces the order that you call a particular function,
|
||||
so if you expect GrabNabber(int size) to be called three times, it
|
||||
will verify that the sizes are in the order you specified. You might
|
||||
*also* want to make sure that all different functions are called in a
|
||||
particular order. If so, set this to true.
|
||||
|
||||
* default: false
|
||||
|
||||
* `:framework`:
|
||||
Currently the only option is `:unity.` Eventually if we support other
|
||||
unity test frameworks (or if you write one for us), they'll get added
|
||||
here.
|
||||
|
||||
: default: :unity
|
||||
|
||||
* `:includes`:
|
||||
An array of additional include files which should be added to the
|
||||
mocks. Useful for global types and definitions used in your project.
|
||||
There are more specific versions if you care WHERE in the mock files
|
||||
the includes get placed. You can define any or all of these options.
|
||||
|
||||
* `:includes`
|
||||
* `:includes_h_pre_orig_header`
|
||||
* `:includes_h_post_orig_header`
|
||||
* `:includes_c_pre_header`
|
||||
* `:includes_c_post_header`
|
||||
* default: nil #for all 5 options
|
||||
|
||||
* `:memcmp_if_unknown`:
|
||||
C developers create a lot of types, either through typedef or preprocessor
|
||||
macros. CMock isn't going to automatically know what you were thinking all
|
||||
the time (though it tries its best). If it comes across a type it doesn't
|
||||
recognize, you have a choice on how you want it to handle it. It can either
|
||||
perform a raw memory comparison and report any differences, or it can fail
|
||||
with a meaningful message. Either way, this feature will only happen after
|
||||
all other mechanisms have failed (The thing encountered isn't a standard
|
||||
type. It isn't in the :treat_as list. It isn't in a custom unity_helper).
|
||||
|
||||
* default: true
|
||||
|
||||
* `:mock_path`:
|
||||
The directory where you would like the mock files generated to be
|
||||
placed.
|
||||
|
||||
* default: mocks
|
||||
|
||||
* `:mock_prefix`:
|
||||
The prefix to prepend to your mock files. For example, if it's `Mock`, a file
|
||||
“USART.h” will get a mock called “MockUSART.c”. This CAN be used with a suffix
|
||||
at the same time.
|
||||
|
||||
* default: Mock
|
||||
|
||||
* `:mock_suffix`:
|
||||
The suffix to append to your mock files. For example, it it's `_Mock`, a file
|
||||
"USART.h" will get a mock called "USART_Mock.h". This CAN be used with a prefix
|
||||
at the same time.
|
||||
|
||||
* default: ""
|
||||
|
||||
* `:plugins`:
|
||||
An array of which plugins to enable. ':expect' is always active. Also
|
||||
available currently:
|
||||
|
||||
* `:ignore`
|
||||
* `:ignore_stateless`
|
||||
* `:ignore_arg`
|
||||
* `:expect_any_args`
|
||||
* `:array`
|
||||
* `:cexception`
|
||||
* `:callback`
|
||||
* `:return_thru_ptr`
|
||||
|
||||
* `:strippables`:
|
||||
An array containing a list of items to remove from the header
|
||||
before deciding what should be mocked. This can be something simple
|
||||
like a compiler extension CMock wouldn't recognize, or could be a
|
||||
regex to reject certain function name patterns. This is a great way to
|
||||
get rid of compiler extensions when your test compiler doesn't support
|
||||
them. For example, use `:strippables: ['(?:functionName\s*\(+.*?\)+)']`
|
||||
to prevent a function `functionName` from being mocked. By default, it
|
||||
is ignoring all gcc attribute extensions.
|
||||
|
||||
* default: `['(?:__attribute__\s*\(+.*?\)+)']`
|
||||
|
||||
* `:exclude_setjmp_h`:
|
||||
Some embedded systems don't have <setjmp.h> available. Setting this to true
|
||||
removes references to this header file and the ability to use cexception.
|
||||
|
||||
* default: false
|
||||
|
||||
|
||||
* `:subdir`:
|
||||
This is a relative subdirectory for your mocks. Set this to e.g. "sys" in
|
||||
order to create a mock for `sys/types.h` in `(:mock_path)/sys/`.
|
||||
|
||||
* default: ""
|
||||
|
||||
* `:treat_as`:
|
||||
The `:treat_as` list is a shortcut for when you have created typedefs
|
||||
of standard types. Why create a custom unity helper for UINT16 when
|
||||
the unity function TEST_ASSERT_EQUAL_HEX16 will work just perfectly?
|
||||
Just add 'UINT16' => 'HEX16' to your list (actually, don't. We already
|
||||
did that one for you). Maybe you have a type that is a pointer to an
|
||||
array of unsigned characters? No problem, just add 'UINT8_T*' =>
|
||||
'HEX8*'
|
||||
|
||||
* NOTE: unlike the other options, your specifications MERGE with the
|
||||
default list. Therefore, if you want to override something, you must
|
||||
reassign it to something else (or to *nil* if you don't want it)
|
||||
|
||||
* default:
|
||||
* 'int': 'INT'
|
||||
* 'char': 'INT8'
|
||||
* 'short': 'INT16'
|
||||
* 'long': 'INT'
|
||||
* 'int8': 'INT8'
|
||||
* 'int16': 'INT16'
|
||||
* 'int32': 'INT'
|
||||
* 'int8_t': 'INT8'
|
||||
* 'int16_t': 'INT16'
|
||||
* 'int32_t': 'INT'
|
||||
* 'INT8_T': 'INT8'
|
||||
* 'INT16_T': 'INT16'
|
||||
* 'INT32_T': 'INT'
|
||||
* 'bool': 'INT'
|
||||
* 'bool_t': 'INT'
|
||||
* 'BOOL': 'INT'
|
||||
* 'BOOL_T': 'INT'
|
||||
* 'unsigned int': 'HEX32'
|
||||
* 'unsigned long': 'HEX32'
|
||||
* 'uint32': 'HEX32'
|
||||
* 'uint32_t': 'HEX32'
|
||||
* 'UINT32': 'HEX32'
|
||||
* 'UINT32_T': 'HEX32'
|
||||
* 'void*': 'HEX8_ARRAY'
|
||||
* 'unsigned short': 'HEX16'
|
||||
* 'uint16': 'HEX16'
|
||||
* 'uint16_t': 'HEX16'
|
||||
* 'UINT16': 'HEX16'
|
||||
* 'UINT16_T': 'HEX16'
|
||||
* 'unsigned char': 'HEX8'
|
||||
* 'uint8': 'HEX8'
|
||||
* 'uint8_t': 'HEX8'
|
||||
* 'UINT8': 'HEX8'
|
||||
* 'UINT8_T': 'HEX8'
|
||||
* 'char*': 'STRING'
|
||||
* 'pCHAR': 'STRING'
|
||||
* 'cstring': 'STRING'
|
||||
* 'CSTRING': 'STRING'
|
||||
* 'float': 'FLOAT'
|
||||
* 'double': 'FLOAT'
|
||||
|
||||
* `:treat_as_array`:
|
||||
A specialized sort of `:treat_as` to be used when you've created a
|
||||
typedef of an array type, such as `typedef int TenIntegers[10];`. This
|
||||
is a hash of typedef name to element type. For example:
|
||||
|
||||
{ "TenIntegers" => "int",
|
||||
"ArrayOfFloat" => "float" }
|
||||
|
||||
Telling CMock about these typedefs allows it to be more intelligent
|
||||
about parameters of such types, so that you can use features like
|
||||
ExpectWithArray and ReturnArrayThruPtr with them.
|
||||
|
||||
* `:treat_as_void`:
|
||||
We've seen "fun" legacy systems typedef 'void' with a custom type,
|
||||
like MY_VOID. Add any instances of those to this list to help CMock
|
||||
understand how to deal with your code.
|
||||
|
||||
* default: []
|
||||
|
||||
* `:treat_externs`:
|
||||
This specifies how you want CMock to handle functions that have been
|
||||
marked as extern in the header file. Should it mock them?
|
||||
|
||||
* `:include` will mock externed functions
|
||||
* `:exclude` will ignore externed functions (default).
|
||||
|
||||
* `:treat_inlines`:
|
||||
This specifies how you want CMock to handle functions that have been
|
||||
marked as inline in the header file. Should it mock them?
|
||||
|
||||
* `:include` will mock inlined functions
|
||||
* `:exclude` will ignore inlined functions (default).
|
||||
|
||||
CMock will look for the following default patterns (simplified from the actual regex):
|
||||
- "static inline"
|
||||
- "inline static"
|
||||
- "inline"
|
||||
- "static"
|
||||
You can override these patterns, check out :inline_function_patterns.
|
||||
|
||||
Enabling this feature does require a change in the build system that
|
||||
is using CMock. To understand why, we need to give some more info
|
||||
on how we are handling inline functions internally.
|
||||
Let's say we want to mock a header called example.h. example.h
|
||||
contains inline functions, we cannot include this header in the
|
||||
mocks or test code if we want to mock the inline functions simply
|
||||
because the inline functions contain an implementation that we want
|
||||
to override in our mocks!
|
||||
So, to circumvent this, we generate a new header, also named
|
||||
example.h, in the same directory as mock_example.h/c . This newly
|
||||
generated header should/is exactly the same as the original header,
|
||||
only difference is the inline functions are transformed to 'normal'
|
||||
functions declarations. Placing the new header in the same
|
||||
directory as mock_example.h/c ensures that they will include the new
|
||||
header and not the old one.
|
||||
However, CMock has no control in how the build system is configured
|
||||
and which include paths the test code is compiled with. In order
|
||||
for the test code to also see the newly generated header ,and not
|
||||
the old header with inline functions, the build system has to add
|
||||
the mock folder to the include paths.
|
||||
Furthermore, we need to keep the order of include paths in mind. We
|
||||
have to set the mock folder before the other includes to avoid the
|
||||
test code including the original header instead of the newly
|
||||
generated header (without inline functions).
|
||||
|
||||
* `:unity_helper_path`:
|
||||
If you have created a header with your own extensions to unity to
|
||||
handle your own types, you can set this argument to that path. CMock
|
||||
will then automagically pull in your helpers and use them. The only
|
||||
trick is that you make sure you follow the naming convention:
|
||||
`UNITY_TEST_ASSERT_EQUAL_YourType`. If it finds macros of the right
|
||||
shape that match that pattern, it'll use them.
|
||||
|
||||
* default: []
|
||||
|
||||
* `:verbosity`:
|
||||
How loud should CMock be?
|
||||
|
||||
* 0 for errors only
|
||||
* 1 for errors and warnings
|
||||
* 2 for normal (default)
|
||||
* 3 for verbose
|
||||
|
||||
* `:weak`:
|
||||
When set this to some value, the generated mocks are defined as weak
|
||||
symbols using the configured format. This allows them to be overridden
|
||||
in particular tests.
|
||||
|
||||
* Set to '__attribute ((weak))' for weak mocks when using GCC.
|
||||
* Set to any non-empty string for weak mocks when using IAR.
|
||||
* default: ""
|
||||
|
||||
* `:when_no_prototypes`:
|
||||
When you give CMock a header file and ask it to create a mock out of
|
||||
it, it usually contains function prototypes (otherwise what was the
|
||||
point?). You can control what happens when this isn't true. You can
|
||||
set this to `:warn,` `:ignore,` or `:error`
|
||||
|
||||
* default: :warn
|
||||
|
||||
* `:when_ptr`:
|
||||
You can customize how CMock deals with pointers (c strings result in
|
||||
string comparisons... we're talking about **other** pointers here). Your
|
||||
options are `:compare_ptr` to just verify the pointers are the same,
|
||||
`:compare_data` or `:smart` to verify that the data is the same.
|
||||
`:compare_data` and `:smart` behaviors will change slightly based on
|
||||
if you have the array plugin enabled. By default, they compare a
|
||||
single element of what is being pointed to. So if you have a pointer
|
||||
to a struct called ORGAN_T, it will compare one ORGAN_T (whatever that
|
||||
is).
|
||||
|
||||
* default: :smart
|
||||
|
||||
* `:array_size_type`:
|
||||
* `:array_size_name`:
|
||||
When the `:array` plugin is disabled, these options do nothing.
|
||||
|
||||
When the `:array` plugin is enabled, these options allow CMock to recognize
|
||||
functions with parameters that might refer to an array, like the following,
|
||||
and treat them more intelligently:
|
||||
|
||||
* `void GoBananas(Banana * bananas, int num_bananas)`
|
||||
* `int write_data(int fd, const uint8_t * data, uint32_t size)`
|
||||
|
||||
To recognize functions like these, CMock looks for a parameter list
|
||||
containing a pointer (which could be an array) followed by something that
|
||||
could be an array size. "Something", by default, means an `int` or `size_t`
|
||||
parameter with a name containing "size" or "len".
|
||||
|
||||
`:array_size_type` is a list of additional types (besides `int` and `size_t`)
|
||||
that could be used for an array size parameter. For example, to get CMock to
|
||||
recognize that `uint32_t size` is an array size, you'd need to say:
|
||||
|
||||
cfg[:array_size_type] = ['uint32_t']
|
||||
|
||||
`:array_size_name` is a regular expression used to match an array size
|
||||
parameter by name. By default, it's 'size|len'. To get CMock to recognize a
|
||||
name like `num_bananas`, you could tell it to also accept names containing
|
||||
'num_' like this:
|
||||
|
||||
cfg[:array_size_name] = 'size|len|num_'
|
||||
|
||||
Parameters must match *both* `:array_size_type` and `:array_size_name` (and
|
||||
must come right after a pointer parameter) to be treated as an array size.
|
||||
|
||||
Once you've told it how to recognize your arrays, CMock will give you `_Expect`
|
||||
calls that work more like `_ExpectWithArray`, and compare an array of objects
|
||||
rather than just a single object.
|
||||
|
||||
For example, if you write the following, CMock will check that GoBananas is
|
||||
called and passed an array containing a green banana followed by a yellow
|
||||
banana:
|
||||
|
||||
Banana b[2] = {GreenBanana, YellowBanana};
|
||||
GoBananas_Expect(b, 2);
|
||||
|
||||
In other words, `GoBananas_Expect(b, 2)` now works just the same as:
|
||||
|
||||
GoBananas_ExpectWithArray(b, 2, 2);
|
||||
|
||||
* `:fail_on_unexpected_calls`:
|
||||
By default, CMock will fail a test if a mock is called without `_Expect` and `_Ignore`
|
||||
called first. While this forces test writers to be more explicit in their expectations,
|
||||
it can clutter tests with `_Expect` or `_Ignore` calls for functions which are not the focus
|
||||
of the test. While this is a good indicator that this module should be refactored, some
|
||||
users are not fans of the additional noise.
|
||||
|
||||
Therefore, :fail_on_unexpected_calls can be set to false to force all mocks to start with
|
||||
the assumption that they are operating as `_Ignore` unless otherwise specified.
|
||||
|
||||
* default: true
|
||||
* **note:**
|
||||
If this option is disabled, the mocked functions will return
|
||||
a default value (0) when called (and only if they have to return something of course).
|
||||
|
||||
* `:inline_function_patterns`:
|
||||
An array containing a list of strings to detect inline functions.
|
||||
This option is only taken into account if you enable :treat_inlines.
|
||||
These strings are interpreted as regex patterns so be sure to escape
|
||||
certain characters. For example, use `:inline_function_patterns: ['static inline __attribute__ \(\(always_inline\)\)']`
|
||||
to recognize `static inline __attribute__ ((always_inline)) int my_func(void)`
|
||||
as an inline function.
|
||||
The default patterns are are:
|
||||
|
||||
* default: ['(static\s+inline|inline\s+static)\s*', '(\bstatic\b|\binline\b)\s*']
|
||||
* **note:**
|
||||
The order of patterns is important here!
|
||||
We go from specific patterns ('static inline') to general patterns ('inline'),
|
||||
otherwise we would miss functions that use 'static inline' iso 'inline'.
|
||||
|
||||
|
||||
Compiled Options:
|
||||
-----------------
|
||||
|
||||
A number of #defines also exist for customizing the cmock experience.
|
||||
Feel free to pass these into your compiler or whatever is most
|
||||
convenient. CMock will otherwise do its best to guess what you want
|
||||
based on other settings, particularly Unity's settings.
|
||||
|
||||
* `CMOCK_MEM_STATIC` or `CMOCK_MEM_DYNAMIC`
|
||||
Define one of these to determine if you want to dynamically add
|
||||
memory during tests as required from the heap. If static, you
|
||||
can control the total footprint of Cmock. If dynamic, you will
|
||||
need to make sure you make some heap space available for Cmock.
|
||||
|
||||
* `CMOCK_MEM_SIZE`
|
||||
In static mode this is the total amount of memory you are allocating
|
||||
to Cmock. In Dynamic mode this is the size of each chunk allocated
|
||||
at once (larger numbers grab more memory but require fewer mallocs).
|
||||
|
||||
* `CMOCK_MEM_ALIGN`
|
||||
The way to align your data to. Not everything is as flexible as
|
||||
a PC, as most embedded designers know. This defaults to 2, meaning
|
||||
align to the closest 2^2 -> 4 bytes (32 bits). You can turn off alignment
|
||||
by setting 0, force alignment to the closest uint16 with 1 or even
|
||||
to the closest uint64 with 3.
|
||||
|
||||
* `CMOCK_MEM_PTR_AS_INT`
|
||||
This is used internally to hold pointers... it needs to be big
|
||||
enough. On most processors a pointer is the same as an unsigned
|
||||
long... but maybe that's not true for yours?
|
||||
|
||||
* `CMOCK_MEM_INDEX_TYPE`
|
||||
This needs to be something big enough to point anywhere in Cmock's
|
||||
memory space... usually it's a size_t.
|
||||
|
||||
Other Tips
|
||||
==========
|
||||
|
||||
resetTest
|
||||
---------
|
||||
|
||||
While this isn't strictly a CMock feature, often users of CMock are using
|
||||
either the test runner generator scripts in Unity or using Ceedling. In
|
||||
either case, there is a handy function called `resetTest` which gets
|
||||
generated with your runner. You can then use this handy function in your tests
|
||||
themselves. Call it during a test to have CMock validate everything to this point
|
||||
and start over clean. This is really useful when wanting to test a function in
|
||||
an iterative manner with different arguments.
|
||||
|
||||
C++ Support
|
||||
---------
|
||||
C++ unit test/mocking frameworks often use a completely different approach (vs.
|
||||
CMock) that relies on overloading virtual class members and does not support
|
||||
directly mocking static class member methods or free functions (i.e., functions
|
||||
in plain C). One workaround is to wrap the non-virtual functions in an object
|
||||
that exposes them as virtual methods and modify your code to inject mocks at
|
||||
run-time... but there is another way!
|
||||
|
||||
Simply use CMock to mock the static member methods and a C++ mocking framework
|
||||
to handle the virtual methods. (Yes, you can mix mocks from CMock and a C++
|
||||
mocking framework together in the same test!)
|
||||
|
||||
Keep in mind that since C++ mocking frameworks often link the real object to the
|
||||
unit test too, we need to resolve multiple definition errors with something like
|
||||
the following in the source of the real implementation for any functions that
|
||||
CMock mocks:
|
||||
|
||||
#if defined(TEST)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
|
||||
To address potential issues with re-using the same function name in different
|
||||
namespaces/classes, the generated function names include the namespace(s) and
|
||||
class. For example:
|
||||
|
||||
namespace MyNamespace {
|
||||
class MyClass {
|
||||
static int DoesSomething(int a, int b);
|
||||
};
|
||||
}
|
||||
|
||||
Will generate functions like
|
||||
|
||||
void MyNamespace_MyClass_DoesSomething_ExpectAndReturn(int a, int b, int toReturn);
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
You can look in the [examples directory](/examples/) for a couple of examples on how
|
||||
you might tool CMock into your build process. You may also want to consider
|
||||
using [Ceedling](https://throwtheswitch.org/ceedling). Please note that
|
||||
these examples are meant to show how the build process works. They have
|
||||
failing tests ON PURPOSE to show what that would look like. Don't be alarmed. ;)
|
||||
@ -0,0 +1,207 @@
|
||||
# ThrowTheSwitch.org Coding Standard
|
||||
|
||||
Hi. Welcome to the coding standard for ThrowTheSwitch.org. For the most part,
|
||||
we try to follow these standards to unify our contributors' code into a cohesive
|
||||
unit (puns intended). You might find places where these standards aren't
|
||||
followed. We're not perfect. Please be polite where you notice these discrepancies
|
||||
and we'll try to be polite when we notice yours.
|
||||
|
||||
;)
|
||||
|
||||
|
||||
## Why Have A Coding Standard?
|
||||
|
||||
Being consistent makes code easier to understand. We've made an attempt to keep
|
||||
our standard simple because we also believe that we can only expect someone to
|
||||
follow something that is understandable. Please do your best.
|
||||
|
||||
|
||||
## Our Philosophy
|
||||
|
||||
Before we get into details on syntax, let's take a moment to talk about our
|
||||
vision for these tools. We're C developers and embedded software developers.
|
||||
These tools are great to test any C code, but catering to embedded software has
|
||||
made us more tolerant of compiler quirks. There are a LOT of quirky compilers
|
||||
out there. By quirky I mean "doesn't follow standards because they feel like
|
||||
they have a license to do as they wish."
|
||||
|
||||
Our philosophy is "support every compiler we can". Most often, this means that
|
||||
we aim for writing C code that is standards compliant (often C89... that seems
|
||||
to be a sweet spot that is almost always compatible). But it also means these
|
||||
tools are tolerant of things that aren't common. Some that aren't even
|
||||
compliant. There are configuration options to override the size of standard
|
||||
types. There are configuration options to force Unity to not use certain
|
||||
standard library functions. A lot of Unity is configurable and we have worked
|
||||
hard to make it not TOO ugly in the process.
|
||||
|
||||
Similarly, our tools that parse C do their best. They aren't full C parsers
|
||||
(yet) and, even if they were, they would still have to accept non-standard
|
||||
additions like gcc extensions or specifying `@0x1000` to force a variable to
|
||||
compile to a particular location. It's just what we do, because we like
|
||||
everything to Just Work™.
|
||||
|
||||
Speaking of having things Just Work™, that's our second philosophy. By that, we
|
||||
mean that we do our best to have EVERY configuration option have a logical
|
||||
default. We believe that if you're working with a simple compiler and target,
|
||||
you shouldn't need to configure very much... we try to make the tools guess as
|
||||
much as they can, but give the user the power to override it when it's wrong.
|
||||
|
||||
|
||||
## Naming Things
|
||||
|
||||
Let's talk about naming things. Programming is all about naming things. We name
|
||||
files, functions, variables, and so much more. While we're not always going to
|
||||
find the best name for something, we actually put quite a bit of effort into
|
||||
finding *What Something WANTS to be Called*™.
|
||||
|
||||
When naming things, we more or less follow this hierarchy, the first being the
|
||||
most important to us (but we do all four whenever possible):
|
||||
1. Readable
|
||||
2. Descriptive
|
||||
3. Consistent
|
||||
4. Memorable
|
||||
|
||||
|
||||
#### Readable
|
||||
|
||||
We want to read our code. This means we like names and flow that are more
|
||||
naturally read. We try to avoid double negatives. We try to avoid cryptic
|
||||
abbreviations (sticking to ones we feel are common).
|
||||
|
||||
|
||||
#### Descriptive
|
||||
|
||||
We like descriptive names for things, especially functions and variables.
|
||||
Finding the right name for something is an important endeavor. You might notice
|
||||
from poking around our code that this often results in names that are a little
|
||||
longer than the average. Guilty. We're okay with a tiny bit more typing if it
|
||||
means our code is easier to understand.
|
||||
|
||||
There are two exceptions to this rule that we also stick to as religiously as
|
||||
possible:
|
||||
|
||||
First, while we realize hungarian notation (and similar systems for encoding
|
||||
type information into variable names) is providing a more descriptive name, we
|
||||
feel that (for the average developer) it takes away from readability and
|
||||
therefore is to be avoided.
|
||||
|
||||
Second, loop counters and other local throw-away variables often have a purpose
|
||||
which is obvious. There's no need, therefore, to get carried away with complex
|
||||
naming. We find i, j, and k are better loop counters than loopCounterVar or
|
||||
whatnot. We only break this rule when we see that more description could improve
|
||||
understanding of an algorithm.
|
||||
|
||||
|
||||
#### Consistent
|
||||
|
||||
We like consistency, but we're not really obsessed with it. We try to name our
|
||||
configuration macros in a consistent fashion... you'll notice a repeated use of
|
||||
UNITY_EXCLUDE_BLAH or UNITY_USES_BLAH macros. This helps users avoid having to
|
||||
remember each macro's details.
|
||||
|
||||
|
||||
#### Memorable
|
||||
|
||||
Where ever it doesn't violate the above principles, we try to apply memorable
|
||||
names. Sometimes this means using something that is simply descriptive, but
|
||||
often we strive for descriptive AND unique... we like quirky names that stand
|
||||
out in our memory and are easier to search for. Take a look through the file
|
||||
names in Ceedling and you'll get a good idea of what we are talking about here.
|
||||
Why use preprocess when you can use preprocessinator? Or what better describes a
|
||||
module in charge of invoking tasks during releases than release_invoker? Don't
|
||||
get carried away. The names are still descriptive and fulfill the above
|
||||
requirements, but they don't feel stale.
|
||||
|
||||
|
||||
## C and C++ Details
|
||||
|
||||
We don't really want to add to the style battles out there. Tabs or spaces?
|
||||
How many spaces? Where do the braces go? These are age-old questions that will
|
||||
never be answered... or at least not answered in a way that will make everyone
|
||||
happy.
|
||||
|
||||
We've decided on our own style preferences. If you'd like to contribute to these
|
||||
projects (and we hope that you do), then we ask if you do your best to follow
|
||||
the same. It will only hurt a little. We promise.
|
||||
|
||||
|
||||
#### Whitespace
|
||||
|
||||
Our C-style is to use spaces and to use 4 of them per indent level. It's a nice
|
||||
power-of-2 number that looks decent on a wide screen. We have no more reason
|
||||
than that. We break that rule when we have lines that wrap (macros or function
|
||||
arguments or whatnot). When that happens, we like to indent further to line
|
||||
things up in nice tidy columns.
|
||||
|
||||
```C
|
||||
if (stuff_happened)
|
||||
{
|
||||
do_something();
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### Case
|
||||
|
||||
- Files - all lower case with underscores.
|
||||
- Variables - all lower case with underscores
|
||||
- Macros - all caps with underscores.
|
||||
- Typedefs - all caps with underscores. (also ends with _T).
|
||||
- Functions - camel cased. Usually named ModuleName_FuncName
|
||||
- Constants and Globals - camel cased.
|
||||
|
||||
|
||||
#### Braces
|
||||
|
||||
The left brace is on the next line after the declaration. The right brace is
|
||||
directly below that. Everything in between in indented one level. If you're
|
||||
catching an error and you have a one-line, go ahead and to it on the same line.
|
||||
|
||||
```C
|
||||
while (blah)
|
||||
{
|
||||
//Like so. Even if only one line, we use braces.
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### Comments
|
||||
|
||||
Do you know what we hate? Old-school C block comments. BUT, we're using them
|
||||
anyway. As we mentioned, our goal is to support every compiler we can,
|
||||
especially embedded compilers. There are STILL C compilers out there that only
|
||||
support old-school block comments. So that is what we're using. We apologize. We
|
||||
think they are ugly too.
|
||||
|
||||
|
||||
## Ruby Details
|
||||
|
||||
Is there really such thing as a Ruby coding standard? Ruby is such a free form
|
||||
language, it seems almost sacrilegious to suggest that people should comply to
|
||||
one method! We'll keep it really brief!
|
||||
|
||||
|
||||
#### Whitespace
|
||||
|
||||
Our Ruby style is to use spaces and to use 2 of them per indent level. It's a
|
||||
nice power-of-2 number that really grooves with Ruby's compact style. We have no
|
||||
more reason than that. We break that rule when we have lines that wrap. When
|
||||
that happens, we like to indent further to line things up in nice tidy columns.
|
||||
|
||||
|
||||
#### Case
|
||||
|
||||
- Files - all lower case with underscores.
|
||||
- Variables - all lower case with underscores
|
||||
- Classes, Modules, etc - Camel cased.
|
||||
- Functions - all lower case with underscores
|
||||
- Constants - all upper case with underscores
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
Egad. Really? We use markdown and we like pdf files because they can be made to
|
||||
look nice while still being portable. Good enough?
|
||||
|
||||
|
||||
*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)*
|
||||
@ -0,0 +1,30 @@
|
||||
CC ?= gcc
|
||||
export BUILD_DIR ?= ./build
|
||||
export SRC_DIR ?= ./src
|
||||
export TEST_DIR ?= ./test
|
||||
export TEST_BUILD_DIR ?= ${BUILD_DIR}/test
|
||||
TEST_MAKEFILE = ${TEST_BUILD_DIR}/MakefileTestSupport
|
||||
OBJ ?= ${BUILD_DIR}/obj
|
||||
OBJ_DIR = ${OBJ}
|
||||
|
||||
default: all
|
||||
|
||||
all: setup test ${BUILD_DIR}/main run
|
||||
|
||||
setup:
|
||||
mkdir -p ${BUILD_DIR}
|
||||
mkdir -p ${OBJ}
|
||||
ruby ../../scripts/create_makefile.rb --silent
|
||||
|
||||
clean:
|
||||
rm -rf ${BUILD_DIR}
|
||||
|
||||
${BUILD_DIR}/main: ${SRC_DIR}/main.c ${SRC_DIR}/foo.c
|
||||
${CC} $< -o $@
|
||||
|
||||
run:
|
||||
./build/main || true
|
||||
|
||||
test: setup
|
||||
|
||||
-include ${TEST_MAKEFILE}
|
||||
@ -0,0 +1,5 @@
|
||||
#include "foo.h"
|
||||
|
||||
void foo_init(void)
|
||||
{
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
#ifndef _foo_h
|
||||
|
||||
void foo_init(void);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
#include "foo.h"
|
||||
|
||||
int real_main(int argc, char ** argv)
|
||||
{
|
||||
printf("Hello world!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef TEST
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
return real_main(argc, argv);
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,17 @@
|
||||
#include "unity.h"
|
||||
#include "foo.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void test_foo_init_should_initialize_multiplier()
|
||||
{
|
||||
foo_init();
|
||||
|
||||
TEST_ASSERT_FALSE(1);
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
#include "unity.h"
|
||||
#include "mock_foo.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void test_main_should_initialize_foo(void)
|
||||
{
|
||||
TEST_IGNORE_MESSAGE("TODO: Implement main!");
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
compiler:
|
||||
path: gcc
|
||||
source_path: 'src/'
|
||||
unit_tests_path: &unit_tests_path 'test/'
|
||||
build_path: &build_path 'build/'
|
||||
options:
|
||||
- -c
|
||||
includes:
|
||||
prefix: '-I'
|
||||
items:
|
||||
- 'src/'
|
||||
- '../../src/'
|
||||
- '../../vendor/unity/src/'
|
||||
- '../../vendor/unity/examples/example_3/helper/'
|
||||
- './build/mocks/'
|
||||
- *unit_tests_path
|
||||
defines:
|
||||
prefix: '-D'
|
||||
items:
|
||||
- __monitor
|
||||
object_files:
|
||||
prefix: '-o'
|
||||
extension: '.o'
|
||||
destination: *build_path
|
||||
linker:
|
||||
path: gcc
|
||||
options:
|
||||
- -lm
|
||||
includes:
|
||||
prefix: '-I'
|
||||
object_files:
|
||||
path: *build_path
|
||||
extension: '.o'
|
||||
bin_files:
|
||||
prefix: '-o'
|
||||
extension: '.exe'
|
||||
destination: *build_path
|
||||
:cmock:
|
||||
:plugins: []
|
||||
:includes:
|
||||
- Types.h
|
||||
:mock_path: ./build/mocks
|
||||
|
||||
colour: true
|
||||
@ -0,0 +1,92 @@
|
||||
tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\'
|
||||
compiler:
|
||||
path: [*tools_root, 'arm\bin\iccarm.exe']
|
||||
source_path: 'src\'
|
||||
unit_tests_path: &unit_tests_path 'test\'
|
||||
build_path: &build_path 'build\'
|
||||
options:
|
||||
- --dlib_config
|
||||
- [*tools_root, 'arm\lib\dl4tptinl8n.h']
|
||||
- -z3
|
||||
- --no_cse
|
||||
- --no_unroll
|
||||
- --no_inline
|
||||
- --no_code_motion
|
||||
- --no_tbaa
|
||||
- --no_clustering
|
||||
- --no_scheduling
|
||||
- --debug
|
||||
- --cpu_mode thumb
|
||||
- --endian little
|
||||
- --cpu ARM7TDMI
|
||||
- --stack_align 4
|
||||
- --interwork
|
||||
- -e
|
||||
- --silent
|
||||
- --warnings_are_errors
|
||||
- --fpu None
|
||||
- --diag_suppress Pa050
|
||||
includes:
|
||||
prefix: '-I'
|
||||
items:
|
||||
- 'src/'
|
||||
- '../../src/'
|
||||
- '../../vendor/unity/src/'
|
||||
- '../../vendor/unity/examples/example_3/helper/'
|
||||
- './build/mocks/'
|
||||
- [*tools_root, 'arm\inc\']
|
||||
- *unit_tests_path
|
||||
defines:
|
||||
prefix: '-D'
|
||||
items:
|
||||
object_files:
|
||||
prefix: '-o'
|
||||
extension: '.r79'
|
||||
destination: *build_path
|
||||
linker:
|
||||
path: [*tools_root, 'common\bin\xlink.exe']
|
||||
options:
|
||||
- -rt
|
||||
- [*tools_root, 'arm\lib\dl4tptinl8n.r79']
|
||||
- -D_L_EXTMEM_START=0
|
||||
- -D_L_EXTMEM_SIZE=0
|
||||
- -D_L_HEAP_SIZE=120
|
||||
- -D_L_STACK_SIZE=32
|
||||
- -e_small_write=_formatted_write
|
||||
- -s
|
||||
- __program_start
|
||||
- -f
|
||||
- [*tools_root, '\arm\config\lnkarm.xcl']
|
||||
includes:
|
||||
prefix: '-I'
|
||||
items:
|
||||
- [*tools_root, 'arm\config\']
|
||||
- [*tools_root, 'arm\lib\']
|
||||
object_files:
|
||||
path: *build_path
|
||||
extension: '.r79'
|
||||
bin_files:
|
||||
prefix: '-o'
|
||||
extension: '.d79'
|
||||
destination: *build_path
|
||||
simulator:
|
||||
path: [*tools_root, 'common\bin\CSpyBat.exe']
|
||||
pre_support:
|
||||
- --silent
|
||||
- [*tools_root, 'arm\bin\armproc.dll']
|
||||
- [*tools_root, 'arm\bin\armsim.dll']
|
||||
post_support:
|
||||
- --plugin
|
||||
- [*tools_root, 'arm\bin\armbat.dll']
|
||||
- --backend
|
||||
- -B
|
||||
- -p
|
||||
- [*tools_root, 'arm\config\ioat91sam7X256.ddf']
|
||||
- -d
|
||||
- sim
|
||||
:cmock:
|
||||
:plugins: []
|
||||
:includes:
|
||||
- Types.h
|
||||
:mock_path: ./build/mocks
|
||||
|
||||
@ -0,0 +1,81 @@
|
||||
tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 5.3\'
|
||||
compiler:
|
||||
path: [*tools_root, 'arm\bin\iccarm.exe']
|
||||
source_path: 'src\'
|
||||
unit_tests_path: &unit_tests_path 'test\'
|
||||
build_path: &build_path 'build\'
|
||||
options:
|
||||
- --dlib_config
|
||||
- [*tools_root, 'arm\inc\DLib_Config_Normal.h']
|
||||
- --no_cse
|
||||
- --no_unroll
|
||||
- --no_inline
|
||||
- --no_code_motion
|
||||
- --no_tbaa
|
||||
- --no_clustering
|
||||
- --no_scheduling
|
||||
- --debug
|
||||
- --cpu_mode thumb
|
||||
- --endian=little
|
||||
- --cpu=ARM7TDMI
|
||||
- --interwork
|
||||
- --warnings_are_errors
|
||||
- --fpu=None
|
||||
- --diag_suppress=Pa050
|
||||
- --diag_suppress=Pe111
|
||||
- -e
|
||||
- -On
|
||||
includes:
|
||||
prefix: '-I'
|
||||
items:
|
||||
- 'src/'
|
||||
- '../../src/'
|
||||
- '../../vendor/unity/src/'
|
||||
- '../../vendor/unity/examples/example_3/helper/'
|
||||
- './build/mocks/'
|
||||
- [*tools_root, 'arm\inc\']
|
||||
- *unit_tests_path
|
||||
defines:
|
||||
prefix: '-D'
|
||||
items:
|
||||
object_files:
|
||||
prefix: '-o'
|
||||
extension: '.r79'
|
||||
destination: *build_path
|
||||
linker:
|
||||
path: [*tools_root, 'arm\bin\ilinkarm.exe']
|
||||
options:
|
||||
- --redirect _Printf=_PrintfLarge
|
||||
- --redirect _Scanf=_ScanfSmall
|
||||
- --semihosting
|
||||
- --entry __iar_program_start
|
||||
- --config
|
||||
- [*tools_root, 'arm\config\generic.icf']
|
||||
object_files:
|
||||
path: *build_path
|
||||
extension: '.o'
|
||||
bin_files:
|
||||
prefix: '-o'
|
||||
extension: '.out'
|
||||
destination: *build_path
|
||||
simulator:
|
||||
path: [*tools_root, 'common\bin\CSpyBat.exe']
|
||||
pre_support:
|
||||
- --silent
|
||||
- [*tools_root, 'arm\bin\armproc.dll']
|
||||
- [*tools_root, 'arm\bin\armsim.dll']
|
||||
post_support:
|
||||
- --plugin
|
||||
- [*tools_root, 'arm\bin\armbat.dll']
|
||||
- --backend
|
||||
- -B
|
||||
- -p
|
||||
- [*tools_root, 'arm\config\debugger\atmel\ioat91sam7X256.ddf']
|
||||
- -d
|
||||
- sim
|
||||
:cmock:
|
||||
:plugins: []
|
||||
:includes:
|
||||
- Types.h
|
||||
:mock_path: ./build/mocks
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
HERE = __dir__ + '/'
|
||||
|
||||
require 'rake'
|
||||
require 'rake/clean'
|
||||
require 'rake/testtask'
|
||||
require './rakefile_helper'
|
||||
|
||||
include RakefileHelpers
|
||||
|
||||
REQUIRED_DIRS = ['./build', './build/mocks'].freeze
|
||||
REQUIRED_DIRS.each do |v|
|
||||
directory v
|
||||
end
|
||||
|
||||
# Load default configuration, for now
|
||||
DEFAULT_CONFIG_FILE = 'gcc.yml'.freeze
|
||||
configure_toolchain(DEFAULT_CONFIG_FILE)
|
||||
|
||||
task :unit do
|
||||
run_tests(unit_test_files)
|
||||
end
|
||||
|
||||
desc 'Generate test summary'
|
||||
task :summary do
|
||||
report_summary
|
||||
end
|
||||
|
||||
desc 'Build and test Unity'
|
||||
task :all => %i[clean unit summary]
|
||||
task :default => REQUIRED_DIRS + %i[clobber all]
|
||||
task :ci => [:default]
|
||||
task :cruise => [:default]
|
||||
|
||||
desc 'Load configuration'
|
||||
task :config, :config_file do |_t, args|
|
||||
configure_toolchain(args[:config_file])
|
||||
end
|
||||
|
||||
desc 'Return error on Failures'
|
||||
task :strict do
|
||||
$return_error_on_failures = true
|
||||
end
|
||||
@ -0,0 +1,268 @@
|
||||
require 'yaml'
|
||||
require 'fileutils'
|
||||
require '../../vendor/unity/auto/unity_test_summary'
|
||||
require '../../vendor/unity/auto/generate_test_runner'
|
||||
require '../../vendor/unity/auto/colour_reporter'
|
||||
|
||||
module RakefileHelpers
|
||||
$return_error_on_failures = false
|
||||
|
||||
C_EXTENSION = '.c'.freeze
|
||||
|
||||
def load_configuration(config_file)
|
||||
$cfg_file = config_file
|
||||
$cfg = YAML.load(File.read($cfg_file))
|
||||
$colour_output = false unless $cfg['colour']
|
||||
end
|
||||
|
||||
def configure_clean
|
||||
CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil?
|
||||
end
|
||||
|
||||
def configure_toolchain(config_file = DEFAULT_CONFIG_FILE)
|
||||
config_file += '.yml' unless config_file =~ /\.yml$/
|
||||
load_configuration(config_file)
|
||||
configure_clean
|
||||
end
|
||||
|
||||
def unit_test_files
|
||||
path = $cfg['compiler']['unit_tests_path'] + 'Test*' + C_EXTENSION
|
||||
path.tr!('\\', '/')
|
||||
FileList.new(path)
|
||||
end
|
||||
|
||||
def local_include_dirs
|
||||
include_dirs = $cfg['compiler']['includes']['items'].dup
|
||||
include_dirs.delete_if { |dir| dir.is_a?(Array) }
|
||||
include_dirs
|
||||
end
|
||||
|
||||
def extract_headers(filename)
|
||||
includes = []
|
||||
lines = File.readlines(filename)
|
||||
lines.each do |line|
|
||||
m = line.match(/^\s*#include\s+\"\s*(.+\.[hH])\s*\"/)
|
||||
unless m.nil?
|
||||
includes << m[1]
|
||||
end
|
||||
end
|
||||
includes
|
||||
end
|
||||
|
||||
def find_source_file(header, paths)
|
||||
paths.each do |dir|
|
||||
src_file = dir + header.ext(C_EXTENSION)
|
||||
if File.exist?(src_file)
|
||||
return src_file
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def tackit(strings)
|
||||
case strings
|
||||
when Array
|
||||
"\"#{strings.join}\""
|
||||
when /^-/
|
||||
strings
|
||||
when /\s/
|
||||
"\"#{strings}\""
|
||||
else
|
||||
strings
|
||||
end
|
||||
end
|
||||
|
||||
def squash(prefix, items)
|
||||
result = ''
|
||||
items.each { |item| result += " #{prefix}#{tackit(item)}" }
|
||||
result
|
||||
end
|
||||
|
||||
def build_compiler_fields
|
||||
command = tackit($cfg['compiler']['path'])
|
||||
defines = if $cfg['compiler']['defines']['items'].nil?
|
||||
''
|
||||
else
|
||||
squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'])
|
||||
end
|
||||
options = squash('', $cfg['compiler']['options'])
|
||||
includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items'])
|
||||
includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
|
||||
{ :command => command, :defines => defines, :options => options, :includes => includes }
|
||||
end
|
||||
|
||||
def compile(file, _defines = [])
|
||||
compiler = build_compiler_fields
|
||||
cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " \
|
||||
"#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}"
|
||||
obj_file = "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}"
|
||||
execute(cmd_str + obj_file)
|
||||
obj_file
|
||||
end
|
||||
|
||||
def build_linker_fields
|
||||
command = tackit($cfg['linker']['path'])
|
||||
options = if $cfg['linker']['options'].nil?
|
||||
''
|
||||
else
|
||||
squash('', $cfg['linker']['options'])
|
||||
end
|
||||
includes = if $cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil?
|
||||
''
|
||||
else
|
||||
squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items'])
|
||||
end
|
||||
includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
|
||||
{ :command => command, :options => options, :includes => includes }
|
||||
end
|
||||
|
||||
def link_it(exe_name, obj_list)
|
||||
linker = build_linker_fields
|
||||
cmd_str = "#{linker[:command]}#{linker[:includes]} " +
|
||||
(obj_list.map { |obj| "#{$cfg['linker']['object_files']['path']}#{obj} " }).join +
|
||||
$cfg['linker']['bin_files']['prefix'] + ' ' +
|
||||
$cfg['linker']['bin_files']['destination'] +
|
||||
exe_name + $cfg['linker']['bin_files']['extension'] + " #{linker[:options]}"
|
||||
execute(cmd_str)
|
||||
end
|
||||
|
||||
def build_simulator_fields
|
||||
return nil if $cfg['simulator'].nil?
|
||||
|
||||
command = if $cfg['simulator']['path'].nil?
|
||||
''
|
||||
else
|
||||
(tackit($cfg['simulator']['path']) + ' ')
|
||||
end
|
||||
pre_support = if $cfg['simulator']['pre_support'].nil?
|
||||
''
|
||||
else
|
||||
squash('', $cfg['simulator']['pre_support'])
|
||||
end
|
||||
post_support = if $cfg['simulator']['post_support'].nil?
|
||||
''
|
||||
else
|
||||
squash('', $cfg['simulator']['post_support'])
|
||||
end
|
||||
{ :command => command, :pre_support => pre_support, :post_support => post_support }
|
||||
end
|
||||
|
||||
def execute(command_string, verbose = true, ok_to_fail = false)
|
||||
report command_string
|
||||
output = `#{command_string}`.chomp
|
||||
report(output) if verbose && !output.nil? && !output.empty?
|
||||
unless (!$?.nil? && $?.exitstatus.zero?) || ok_to_fail
|
||||
raise "Command failed. (Returned #{$?.exitstatus})"
|
||||
end
|
||||
|
||||
output
|
||||
end
|
||||
|
||||
def report_summary
|
||||
summary = UnityTestSummary.new
|
||||
summary.root = HERE
|
||||
results_glob = "#{$cfg['compiler']['build_path']}*.test*"
|
||||
results_glob.tr!('\\', '/')
|
||||
results = Dir[results_glob]
|
||||
summary.targets = results
|
||||
report summary.run
|
||||
raise 'There were failures' if (summary.failures > 0) && $return_error_on_failures
|
||||
end
|
||||
|
||||
def run_tests(test_files)
|
||||
report 'Running system tests...'
|
||||
|
||||
# Tack on TEST define for compiling unit tests
|
||||
load_configuration($cfg_file)
|
||||
test_defines = ['TEST']
|
||||
$cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil?
|
||||
$cfg['compiler']['defines']['items'] << 'TEST'
|
||||
|
||||
include_dirs = local_include_dirs
|
||||
|
||||
# Build and execute each unit test
|
||||
test_files.each do |test|
|
||||
obj_list = []
|
||||
|
||||
# Detect dependencies and build required required modules
|
||||
header_list = (extract_headers(test) + ['cmock.h'] + [$cfg[:cmock][:unity_helper_path]]).compact.uniq
|
||||
header_list.each do |header|
|
||||
# create mocks if needed
|
||||
next unless header =~ /Mock/
|
||||
|
||||
require '../../lib/cmock.rb'
|
||||
@cmock ||= CMock.new($cfg_file)
|
||||
@cmock.setup_mocks([$cfg['compiler']['source_path'] + header.gsub('Mock', '')])
|
||||
end
|
||||
|
||||
# compile all mocks
|
||||
header_list.each do |header|
|
||||
# compile source file header if it exists
|
||||
src_file = find_source_file(header, include_dirs)
|
||||
unless src_file.nil?
|
||||
obj_list << compile(src_file, test_defines)
|
||||
end
|
||||
end
|
||||
|
||||
# Build the test runner (generate if configured to do so)
|
||||
test_base = File.basename(test, C_EXTENSION)
|
||||
runner_name = test_base + '_Runner.c'
|
||||
if $cfg['compiler']['runner_path'].nil?
|
||||
runner_path = $cfg['compiler']['build_path'] + runner_name
|
||||
test_gen = UnityTestRunnerGenerator.new($cfg_file)
|
||||
test_gen.run(test, runner_path)
|
||||
else
|
||||
runner_path = $cfg['compiler']['runner_path'] + runner_name
|
||||
end
|
||||
|
||||
obj_list << compile(runner_path, test_defines)
|
||||
|
||||
# Build the test module
|
||||
obj_list << compile(test, test_defines)
|
||||
|
||||
# Link the test executable
|
||||
link_it(test_base, obj_list)
|
||||
|
||||
# Execute unit test and generate results file
|
||||
simulator = build_simulator_fields
|
||||
executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension']
|
||||
cmd_str = if simulator.nil?
|
||||
executable
|
||||
else
|
||||
"#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}"
|
||||
end
|
||||
output = execute(cmd_str, true, true)
|
||||
test_results = $cfg['compiler']['build_path'] + test_base
|
||||
test_results += if output.match(/OK$/m).nil?
|
||||
'.testfail'
|
||||
else
|
||||
'.testpass'
|
||||
end
|
||||
File.open(test_results, 'w') { |f| f.print output }
|
||||
end
|
||||
end
|
||||
|
||||
def build_application(main)
|
||||
report 'Building application...'
|
||||
|
||||
obj_list = []
|
||||
load_configuration($cfg_file)
|
||||
main_path = $cfg['compiler']['source_path'] + main + C_EXTENSION
|
||||
|
||||
# Detect dependencies and build required required modules
|
||||
include_dirs = local_include_dirs
|
||||
extract_headers(main_path).each do |header|
|
||||
src_file = find_source_file(header, include_dirs)
|
||||
unless src_file.nil?
|
||||
obj_list << compile(src_file)
|
||||
end
|
||||
end
|
||||
|
||||
# Build the main source file
|
||||
main_base = File.basename(main_path, C_EXTENSION)
|
||||
obj_list << compile(main_path)
|
||||
|
||||
# Create the executable
|
||||
link_it(main_base, obj_list)
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,42 @@
|
||||
#include "Types.h"
|
||||
#include "AdcConductor.h"
|
||||
#include "AdcModel.h"
|
||||
#include "AdcHardware.h"
|
||||
|
||||
void AdcConductor_Init(void)
|
||||
{
|
||||
AdcHardware_Init();
|
||||
}
|
||||
|
||||
void AdcConductor_Run(void)
|
||||
{
|
||||
if (AdcModel_DoGetSample() && AdcHardware_GetSampleComplete())
|
||||
{
|
||||
AdcModel_ProcessInput(AdcHardware_GetSample());
|
||||
AdcHardware_StartConversion();
|
||||
}
|
||||
}
|
||||
|
||||
bool AdcConductor_JustHereToTest(void)
|
||||
{
|
||||
EXAMPLE_STRUCT_T ExampleStruct;
|
||||
ExampleStruct.x = 5;
|
||||
ExampleStruct.y = 7;
|
||||
|
||||
return AdcModel_DoNothingExceptTestASpecialType(ExampleStruct);
|
||||
}
|
||||
|
||||
bool AdcConductor_AlsoHereToTest(void)
|
||||
{
|
||||
EXAMPLE_STRUCT_T example = AdcModel_DoNothingExceptReturnASpecialType();
|
||||
|
||||
return ((example.x == 99) && (example.y == 1));
|
||||
}
|
||||
|
||||
bool AdcConductor_YetAnotherTest(void)
|
||||
{
|
||||
uint32 example = 3;
|
||||
|
||||
return AdModel_DoNothingExceptTestPointers(&example);
|
||||
}
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
#ifndef _ADCCONDUCTOR_H
|
||||
#define _ADCCONDUCTOR_H
|
||||
|
||||
void AdcConductor_Init(void);
|
||||
void AdcConductor_Run(void);
|
||||
|
||||
bool AdcConductor_JustHereToTest(void);
|
||||
bool AdcConductor_AlsoHereToTest(void);
|
||||
bool AdcConductor_YetAnotherTest(void);
|
||||
|
||||
#endif // _ADCCONDUCTOR_H
|
||||
@ -0,0 +1,27 @@
|
||||
#include "Types.h"
|
||||
#include "AdcHardware.h"
|
||||
#include "AdcHardwareConfigurator.h"
|
||||
#include "AdcTemperatureSensor.h"
|
||||
|
||||
void AdcHardware_Init(void)
|
||||
{
|
||||
Adc_Reset();
|
||||
Adc_ConfigureMode();
|
||||
Adc_EnableTemperatureChannel();
|
||||
Adc_StartTemperatureSensorConversion();
|
||||
}
|
||||
|
||||
void AdcHardware_StartConversion(void)
|
||||
{
|
||||
Adc_StartTemperatureSensorConversion();
|
||||
}
|
||||
|
||||
bool AdcHardware_GetSampleComplete(void)
|
||||
{
|
||||
return Adc_TemperatureSensorSampleReady();
|
||||
}
|
||||
|
||||
uint16 AdcHardware_GetSample(void)
|
||||
{
|
||||
return Adc_ReadTemperatureSensor();
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
#ifndef _ADCHARDWARE_H
|
||||
#define _ADCHARDWARE_H
|
||||
|
||||
void AdcHardware_Init(void);
|
||||
void AdcHardware_StartConversion(void);
|
||||
bool AdcHardware_GetSampleComplete(void);
|
||||
uint16 AdcHardware_GetSample(void);
|
||||
|
||||
#endif // _ADCHARDWARE_H
|
||||
@ -0,0 +1,18 @@
|
||||
#include "Types.h"
|
||||
#include "AdcHardwareConfigurator.h"
|
||||
#include "ModelConfig.h"
|
||||
|
||||
void Adc_Reset(void)
|
||||
{
|
||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
|
||||
}
|
||||
|
||||
void Adc_ConfigureMode(void)
|
||||
{
|
||||
AT91C_BASE_ADC->ADC_MR = (((uint32)11) << 8) | (((uint32)4) << 16);
|
||||
}
|
||||
|
||||
void Adc_EnableTemperatureChannel(void)
|
||||
{
|
||||
AT91C_BASE_ADC->ADC_CHER = 0x10;
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
#ifndef _ADCHARDWARECONFIGURATOR_H
|
||||
#define _ADCHARDWARECONFIGURATOR_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
void Adc_Reset(void);
|
||||
void Adc_ConfigureMode(void);
|
||||
void Adc_EnableTemperatureChannel(void);
|
||||
|
||||
#endif // _ADCHARDWARECONFIGURATOR_H
|
||||
@ -0,0 +1,33 @@
|
||||
#include "AdcModel.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "TemperatureCalculator.h"
|
||||
#include "TemperatureFilter.h"
|
||||
|
||||
bool AdcModel_DoGetSample(void)
|
||||
{
|
||||
return TaskScheduler_DoAdc();
|
||||
}
|
||||
|
||||
void AdcModel_ProcessInput(uint16 millivolts)
|
||||
{
|
||||
TemperatureFilter_ProcessInput(TemperatureCalculator_Calculate(millivolts));
|
||||
}
|
||||
|
||||
bool AdcModel_DoNothingExceptTestASpecialType(EXAMPLE_STRUCT_T ExampleStruct)
|
||||
{
|
||||
//This doesn't really do anything. it's only here to make sure I can compare a struct.
|
||||
return FALSE;
|
||||
}
|
||||
bool AdModel_DoNothingExceptTestPointers(uint32* pExample)
|
||||
{
|
||||
//This doesn't really do anything. it's only here to make sure I can compare a pointer value.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
EXAMPLE_STRUCT_T AdcModel_DoNothingExceptReturnASpecialType(void)
|
||||
{
|
||||
EXAMPLE_STRUCT_T example; //again, this just is here to test that I can return a struct
|
||||
example.x = 99;
|
||||
example.y = 1;
|
||||
return example;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
#ifndef _ADCMODEL_H
|
||||
#define _ADCMODEL_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
bool AdcModel_DoGetSample(void);
|
||||
void AdcModel_ProcessInput(uint16 millivolts);
|
||||
|
||||
bool AdcModel_DoNothingExceptTestASpecialType(EXAMPLE_STRUCT_T ExampleStruct);
|
||||
bool AdModel_DoNothingExceptTestPointers(uint32* pExample);
|
||||
EXAMPLE_STRUCT_T AdcModel_DoNothingExceptReturnASpecialType(void);
|
||||
|
||||
#endif // _ADCMODEL_H
|
||||
@ -0,0 +1,51 @@
|
||||
#include "Types.h"
|
||||
#include "AdcTemperatureSensor.h"
|
||||
|
||||
static inline uint32 ConvertAdcCountsToPicovolts(uint32 counts);
|
||||
static inline uint16 ConvertPicovoltsToMillivolts(uint32 picovolts);
|
||||
|
||||
//
|
||||
// PUBLIC METHODS
|
||||
//
|
||||
|
||||
void Adc_StartTemperatureSensorConversion(void)
|
||||
{
|
||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
||||
}
|
||||
|
||||
bool Adc_TemperatureSensorSampleReady(void)
|
||||
{
|
||||
return ((AT91C_BASE_ADC->ADC_SR & AT91C_ADC_EOC4) == AT91C_ADC_EOC4);
|
||||
}
|
||||
|
||||
uint16 Adc_ReadTemperatureSensor(void)
|
||||
{
|
||||
uint32 picovolts = ConvertAdcCountsToPicovolts(AT91C_BASE_ADC->ADC_CDR4);
|
||||
return ConvertPicovoltsToMillivolts(picovolts);
|
||||
}
|
||||
|
||||
//
|
||||
// PRIVATE HELPERS
|
||||
//
|
||||
|
||||
static inline uint32 ConvertAdcCountsToPicovolts(uint32 counts)
|
||||
{
|
||||
// ADC bit weight at 10-bit resolution with 3.0V reference = 2.9296875 mV/LSB
|
||||
uint32 picovoltsPerAdcCount = 2929688;
|
||||
|
||||
// Shift decimal point by 6 places to preserve accuracy in fixed-point math
|
||||
return counts * picovoltsPerAdcCount;
|
||||
}
|
||||
|
||||
static inline uint16 ConvertPicovoltsToMillivolts(uint32 picovolts)
|
||||
{
|
||||
const uint32 halfMillivoltInPicovolts = 500000;
|
||||
const uint32 picovoltsPerMillivolt = 1000000;
|
||||
|
||||
// Add 0.5 mV to result so that truncation yields properly rounded result
|
||||
picovolts += halfMillivoltInPicovolts;
|
||||
|
||||
// Divide appropriately to convert to millivolts
|
||||
return (uint16)(picovolts / picovoltsPerMillivolt);
|
||||
}
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
#ifndef _ADCTEMPERATURESENSOR_H
|
||||
#define _ADCTEMPERATURESENSOR_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
void Adc_StartTemperatureSensorConversion(void);
|
||||
bool Adc_TemperatureSensorSampleReady(void);
|
||||
uint16 Adc_ReadTemperatureSensor(void);
|
||||
|
||||
#endif // _ADCTEMPERATURESENSOR_H
|
||||
@ -0,0 +1,25 @@
|
||||
#include "Types.h"
|
||||
#include "Executor.h"
|
||||
#include "Model.h"
|
||||
#include "UsartConductor.h"
|
||||
#include "TimerConductor.h"
|
||||
#include "AdcConductor.h"
|
||||
#include "IntrinsicsWrapper.h"
|
||||
|
||||
|
||||
void Executor_Init(void)
|
||||
{
|
||||
Model_Init();
|
||||
UsartConductor_Init();
|
||||
AdcConductor_Init();
|
||||
TimerConductor_Init();
|
||||
Interrupt_Enable();
|
||||
}
|
||||
|
||||
bool Executor_Run(void)
|
||||
{
|
||||
UsartConductor_Run();
|
||||
TimerConductor_Run();
|
||||
AdcConductor_Run();
|
||||
return TRUE;
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
#ifndef _EXECUTOR_H
|
||||
#define _EXECUTOR_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
void Executor_Init(void);
|
||||
bool Executor_Run(void);
|
||||
|
||||
#endif // _EXECUTOR_H
|
||||
@ -0,0 +1,18 @@
|
||||
#include "IntrinsicsWrapper.h"
|
||||
#ifdef __ICCARM__
|
||||
#include <intrinsics.h>
|
||||
#endif
|
||||
|
||||
void Interrupt_Enable(void)
|
||||
{
|
||||
#ifdef __ICCARM__
|
||||
__enable_interrupt();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Interrupt_Disable(void)
|
||||
{
|
||||
#ifdef __ICCARM__
|
||||
__disable_interrupt();
|
||||
#endif
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
#ifndef _INTRINSICS_WRAPPER_H
|
||||
#define _INTRINSICS_WRAPPER_H
|
||||
|
||||
void Interrupt_Enable(void);
|
||||
void Interrupt_Disable(void);
|
||||
|
||||
#endif // _INTRINSICS_WRAPPER_H
|
||||
@ -0,0 +1,46 @@
|
||||
#include "Types.h"
|
||||
|
||||
#include "IntrinsicsWrapper.h"
|
||||
#include "Executor.h"
|
||||
|
||||
#include "Model.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "TemperatureCalculator.h"
|
||||
#include "TemperatureFilter.h"
|
||||
|
||||
#include "UsartConductor.h"
|
||||
#include "UsartHardware.h"
|
||||
#include "UsartConfigurator.h"
|
||||
#include "UsartPutChar.h"
|
||||
#include "UsartModel.h"
|
||||
#include "UsartBaudRateRegisterCalculator.h"
|
||||
#include "UsartTransmitBufferStatus.h"
|
||||
|
||||
#include "TimerConductor.h"
|
||||
#include "TimerHardware.h"
|
||||
#include "TimerConfigurator.h"
|
||||
#include "TimerInterruptConfigurator.h"
|
||||
#include "TimerInterruptHandler.h"
|
||||
#include "TimerModel.h"
|
||||
|
||||
#include "AdcConductor.h"
|
||||
#include "AdcHardware.h"
|
||||
#include "AdcHardwareConfigurator.h"
|
||||
#include "AdcTemperatureSensor.h"
|
||||
#include "AdcModel.h"
|
||||
|
||||
int AppMain(void)
|
||||
{
|
||||
Executor_Init();
|
||||
|
||||
while(Executor_Run());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef TEST
|
||||
int main(void)
|
||||
{
|
||||
return AppMain();
|
||||
}
|
||||
#endif // TEST
|
||||
@ -0,0 +1,7 @@
|
||||
#ifndef _MAIN_H_
|
||||
#define _MAIN_H_
|
||||
|
||||
int AppMain(void);
|
||||
int main(void);
|
||||
|
||||
#endif // _MAIN_H_
|
||||
@ -0,0 +1,10 @@
|
||||
#include "Model.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "TemperatureFilter.h"
|
||||
|
||||
void Model_Init(void)
|
||||
{
|
||||
TaskScheduler_Init();
|
||||
TemperatureFilter_Init();
|
||||
}
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
#ifndef _MODEL_H
|
||||
#define _MODEL_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
void Model_Init(void);
|
||||
|
||||
#endif // _MODEL_H
|
||||
@ -0,0 +1,7 @@
|
||||
#ifndef _MODELCONFIG_H
|
||||
#define _MODELCONFIG_H
|
||||
|
||||
#define MASTER_CLOCK 48054857 // Master Clock
|
||||
#define USART0_BAUDRATE 115200 // USART Baudrate
|
||||
|
||||
#endif // _MODELCONFIG_H
|
||||
@ -0,0 +1,72 @@
|
||||
#include "Types.h"
|
||||
#include "TaskScheduler.h"
|
||||
|
||||
typedef struct _Task
|
||||
{
|
||||
bool doIt;
|
||||
uint32 period;
|
||||
uint32 startTime;
|
||||
} Task;
|
||||
|
||||
typedef struct _TaskSchedulerInstance
|
||||
{
|
||||
Task usart;
|
||||
Task adc;
|
||||
} TaskSchedulerInstance;
|
||||
|
||||
static TaskSchedulerInstance this;
|
||||
|
||||
void TaskScheduler_Init(void)
|
||||
{
|
||||
this.usart.doIt = FALSE;
|
||||
this.usart.startTime = 0;
|
||||
|
||||
//The correct period
|
||||
this.usart.period = 1000;
|
||||
|
||||
this.adc.doIt = FALSE;
|
||||
this.adc.startTime = 0;
|
||||
this.adc.period = 100;
|
||||
}
|
||||
|
||||
void TaskScheduler_Update(uint32 time)
|
||||
{
|
||||
if ((time - this.usart.startTime) >= this.usart.period)
|
||||
{
|
||||
this.usart.doIt = TRUE;
|
||||
this.usart.startTime = time - (time % this.usart.period);
|
||||
}
|
||||
|
||||
if ((time - this.adc.startTime) >= this.adc.period)
|
||||
{
|
||||
this.adc.doIt = TRUE;
|
||||
this.adc.startTime = time - (time % this.adc.period);
|
||||
}
|
||||
}
|
||||
|
||||
bool TaskScheduler_DoUsart(void)
|
||||
{
|
||||
bool doIt = FALSE;
|
||||
|
||||
if (this.usart.doIt)
|
||||
{
|
||||
doIt = TRUE;
|
||||
this.usart.doIt = FALSE;
|
||||
}
|
||||
|
||||
return doIt;
|
||||
}
|
||||
|
||||
bool TaskScheduler_DoAdc(void)
|
||||
{
|
||||
bool doIt = FALSE;
|
||||
|
||||
if (this.adc.doIt)
|
||||
{
|
||||
doIt = TRUE;
|
||||
this.adc.doIt = FALSE;
|
||||
}
|
||||
|
||||
return doIt;
|
||||
}
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
#ifndef _TASKSCHEDULER_H
|
||||
#define _TASKSCHEDULER_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
void TaskScheduler_Init(void);
|
||||
void TaskScheduler_Update(uint32 time);
|
||||
bool TaskScheduler_DoUsart(void);
|
||||
bool TaskScheduler_DoAdc(void);
|
||||
|
||||
#endif // _TASKSCHEDULER_H
|
||||
@ -0,0 +1,27 @@
|
||||
#include "Types.h"
|
||||
#include "TemperatureCalculator.h"
|
||||
#include <math.h>
|
||||
|
||||
#ifndef logl
|
||||
#define logl log
|
||||
#endif
|
||||
|
||||
float TemperatureCalculator_Calculate(uint16 millivolts)
|
||||
{
|
||||
const double supply_voltage = 3.0;
|
||||
const double series_resistance = 5000;
|
||||
const double coefficient_A = 316589.698;
|
||||
const double coefficient_B = -0.1382009;
|
||||
double sensor_voltage = ((double)millivolts / 1000);
|
||||
double resistance;
|
||||
|
||||
if (millivolts == 0)
|
||||
{
|
||||
return -INFINITY;
|
||||
}
|
||||
|
||||
// Series resistor is 5k Ohms; Reference voltage is 3.0V
|
||||
// R(t) = A * e^(B*t); R is resistance of thermisor; t is temperature in C
|
||||
resistance = ((supply_voltage * series_resistance) / sensor_voltage) - series_resistance;
|
||||
return (float)(logl(resistance / coefficient_A) / coefficient_B);
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
#ifndef _TEMPERATURECALCULATOR_H
|
||||
#define _TEMPERATURECALCULATOR_H
|
||||
|
||||
float TemperatureCalculator_Calculate(uint16 millivolts);
|
||||
|
||||
#endif // _TEMPERATURECALCULATOR_H
|
||||
@ -0,0 +1,39 @@
|
||||
#include "Types.h"
|
||||
#include "TemperatureFilter.h"
|
||||
#include <math.h>
|
||||
|
||||
static bool initialized;
|
||||
static float temperatureInCelcius;
|
||||
|
||||
void TemperatureFilter_Init(void)
|
||||
{
|
||||
initialized = FALSE;
|
||||
temperatureInCelcius = -INFINITY;
|
||||
}
|
||||
|
||||
float TemperatureFilter_GetTemperatureInCelcius(void)
|
||||
{
|
||||
return temperatureInCelcius;
|
||||
}
|
||||
|
||||
void TemperatureFilter_ProcessInput(float temperature)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
temperatureInCelcius = temperature;
|
||||
initialized = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (temperature == +INFINITY ||
|
||||
temperature == -INFINITY ||
|
||||
temperature == +NAN ||
|
||||
temperature == -NAN)
|
||||
{
|
||||
initialized = FALSE;
|
||||
temperature = -INFINITY;
|
||||
}
|
||||
|
||||
temperatureInCelcius = (temperatureInCelcius * 0.75f) + (temperature * 0.25);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
#ifndef _TEMPERATUREFILTER_H
|
||||
#define _TEMPERATUREFILTER_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
void TemperatureFilter_Init(void);
|
||||
float TemperatureFilter_GetTemperatureInCelcius(void);
|
||||
void TemperatureFilter_ProcessInput(float temperature);
|
||||
|
||||
#endif // _TEMPERATUREFILTER_H
|
||||
@ -0,0 +1,15 @@
|
||||
#include "Types.h"
|
||||
#include "TimerConductor.h"
|
||||
#include "TimerModel.h"
|
||||
#include "TimerHardware.h"
|
||||
#include "TimerInterruptHandler.h"
|
||||
|
||||
void TimerConductor_Init(void)
|
||||
{
|
||||
TimerHardware_Init();
|
||||
}
|
||||
|
||||
void TimerConductor_Run(void)
|
||||
{
|
||||
TimerModel_UpdateTime(Timer_GetSystemTime());
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
#ifndef _TIMERCONDUCTOR_H
|
||||
#define _TIMERCONDUCTOR_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
void TimerConductor_Init(void);
|
||||
void TimerConductor_Run(void);
|
||||
|
||||
#endif // _TIMERCONDUCTOR_H
|
||||
@ -0,0 +1,51 @@
|
||||
#include "Types.h"
|
||||
#include "TimerConfigurator.h"
|
||||
#include "TimerInterruptConfigurator.h"
|
||||
|
||||
void Timer_EnablePeripheralClocks(void)
|
||||
{
|
||||
AT91C_BASE_PMC->PMC_PCER = TIMER0_CLOCK_ENABLE | PIOB_CLOCK_ENABLE;
|
||||
}
|
||||
|
||||
void Timer_Reset(void)
|
||||
{
|
||||
uint32 dummy;
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91C_BASE_TC0->TC_IDR = 0xffffffff;
|
||||
dummy = AT91C_BASE_TC0->TC_SR;
|
||||
dummy = dummy;
|
||||
}
|
||||
|
||||
void Timer_ConfigureMode(void)
|
||||
{
|
||||
AT91C_BASE_TC0->TC_CMR = 0x000CC004; // ACPC=toggle TIOA on RC compare; mode=WAVE; WAVE_SEL=UP w/auto-trigger on RC compare; clock=MCK/1024
|
||||
}
|
||||
|
||||
void Timer_ConfigurePeriod(void)
|
||||
{
|
||||
AT91C_BASE_TC0->TC_RC = 469; // 10ms period for timer clock source of MCK/1024 with MCK=48054857
|
||||
}
|
||||
|
||||
void Timer_EnableOutputPin(void)
|
||||
{
|
||||
AT91C_BASE_PIOB->PIO_PDR = TIOA0_PIN_MASK;
|
||||
}
|
||||
|
||||
void Timer_Enable(void)
|
||||
{
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN;
|
||||
}
|
||||
|
||||
void Timer_ConfigureInterruptHandler(void)
|
||||
{
|
||||
Timer_DisableInterrupt();
|
||||
Timer_ResetSystemTime();
|
||||
Timer_ConfigureInterrupt();
|
||||
Timer_EnableInterrupt();
|
||||
}
|
||||
|
||||
void Timer_Start(void)
|
||||
{
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||
}
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
#ifndef _TIMERCONFIGURATOR_H
|
||||
#define _TIMERCONFIGURATOR_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
void Timer_EnablePeripheralClocks(void);
|
||||
void Timer_Reset(void);
|
||||
void Timer_ConfigureMode(void);
|
||||
void Timer_ConfigurePeriod(void);
|
||||
void Timer_EnableOutputPin(void);
|
||||
void Timer_Enable(void);
|
||||
void Timer_ConfigureInterruptHandler(void);
|
||||
void Timer_Start(void);
|
||||
|
||||
#endif // _TIMERCONFIGURATOR_H
|
||||
@ -0,0 +1,15 @@
|
||||
#include "Types.h"
|
||||
#include "TimerHardware.h"
|
||||
#include "TimerConfigurator.h"
|
||||
|
||||
void TimerHardware_Init(void)
|
||||
{
|
||||
Timer_EnablePeripheralClocks();
|
||||
Timer_Reset();
|
||||
Timer_ConfigureMode();
|
||||
Timer_ConfigurePeriod();
|
||||
Timer_EnableOutputPin();
|
||||
Timer_Enable();
|
||||
Timer_ConfigureInterruptHandler();
|
||||
Timer_Start();
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
#ifndef _TIMERHARDWARE_H
|
||||
#define _TIMERHARDWARE_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
void TimerHardware_Init(void);
|
||||
|
||||
#endif // _TIMERHARDWARE_H
|
||||
@ -0,0 +1,55 @@
|
||||
#include "Types.h"
|
||||
#include "TimerInterruptConfigurator.h"
|
||||
#include "TimerInterruptHandler.h"
|
||||
|
||||
static inline void SetInterruptHandler(void);
|
||||
static inline void ConfigureInterruptSourceModeRegister(void);
|
||||
static inline void ClearInterrupt(void);
|
||||
static inline void EnableCompareInterruptForRegisterC(void);
|
||||
|
||||
void Timer_DisableInterrupt(void)
|
||||
{
|
||||
AT91C_BASE_AIC->AIC_IDCR = TIMER0_ID_MASK;
|
||||
}
|
||||
|
||||
void Timer_ResetSystemTime(void)
|
||||
{
|
||||
Timer_SetSystemTime(0);
|
||||
}
|
||||
|
||||
void Timer_ConfigureInterrupt(void)
|
||||
{
|
||||
SetInterruptHandler();
|
||||
ConfigureInterruptSourceModeRegister();
|
||||
ClearInterrupt();
|
||||
EnableCompareInterruptForRegisterC();
|
||||
}
|
||||
|
||||
void Timer_EnableInterrupt(void)
|
||||
{
|
||||
AT91C_BASE_AIC->AIC_IECR = TIMER0_ID_MASK;
|
||||
}
|
||||
|
||||
//
|
||||
// Helpers
|
||||
//
|
||||
|
||||
static inline void SetInterruptHandler(void)
|
||||
{
|
||||
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC0] = (uint32)Timer_InterruptHandler;
|
||||
}
|
||||
|
||||
static inline void ConfigureInterruptSourceModeRegister(void)
|
||||
{
|
||||
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] = 1;
|
||||
}
|
||||
|
||||
static inline void ClearInterrupt(void)
|
||||
{
|
||||
AT91C_BASE_AIC->AIC_ICCR = TIMER0_ID_MASK;
|
||||
}
|
||||
|
||||
static inline void EnableCompareInterruptForRegisterC(void)
|
||||
{
|
||||
AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
#ifndef _TIMERINTERRUPTCONFIGURATOR_H
|
||||
#define _TIMERINTERRUPTCONFIGURATOR_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#define TIMER0_ID_MASK (((uint32)0x1) << AT91C_ID_TC0)
|
||||
|
||||
void Timer_DisableInterrupt(void);
|
||||
void Timer_ResetSystemTime(void);
|
||||
void Timer_ConfigureInterrupt(void);
|
||||
void Timer_EnableInterrupt(void);
|
||||
|
||||
#endif // _TIMERINTERRUPTCONFIGURATOR_H
|
||||
@ -0,0 +1,25 @@
|
||||
#include "Types.h"
|
||||
#include "TimerInterruptHandler.h"
|
||||
#include "TimerInterruptConfigurator.h"
|
||||
|
||||
static uint32 systemTime;
|
||||
|
||||
void Timer_SetSystemTime(uint32 time)
|
||||
{
|
||||
systemTime = time;
|
||||
}
|
||||
|
||||
uint32 Timer_GetSystemTime(void)
|
||||
{
|
||||
return systemTime;
|
||||
}
|
||||
|
||||
void Timer_InterruptHandler(void)
|
||||
{
|
||||
uint32 status = AT91C_BASE_TC0->TC_SR;
|
||||
if (status & AT91C_TC_CPCS)
|
||||
{
|
||||
systemTime += 10;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
#ifndef _TIMERINTERRUPTHANDLER_H
|
||||
#define _TIMERINTERRUPTHANDLER_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
void Timer_SetSystemTime(uint32 time);
|
||||
uint32 Timer_GetSystemTime(void);
|
||||
void Timer_InterruptHandler(void);
|
||||
|
||||
#endif // _TIMERINTERRUPTHANDLER_H
|
||||
@ -0,0 +1,9 @@
|
||||
#include "Types.h"
|
||||
#include "TimerModel.h"
|
||||
#include "TaskScheduler.h"
|
||||
|
||||
void TimerModel_UpdateTime(uint32 systemTime)
|
||||
{
|
||||
TaskScheduler_Update(systemTime);
|
||||
}
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
#ifndef _TIMERMODEL_H
|
||||
#define _TIMERMODEL_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
void TimerModel_UpdateTime(uint32 systemTime);
|
||||
|
||||
#endif // _TIMERMODEL_H
|
||||
@ -0,0 +1,103 @@
|
||||
#ifndef _MYTYPES_H_
|
||||
#define _MYTYPES_H_
|
||||
|
||||
#include "AT91SAM7X256.h"
|
||||
#include <math.h>
|
||||
|
||||
#ifndef __monitor
|
||||
#define __monitor
|
||||
#endif
|
||||
|
||||
// Peripheral Helper Definitions
|
||||
#define USART0_CLOCK_ENABLE (AT91C_ID_US0)
|
||||
#define USART0_TX_PIN (AT91C_PA1_TXD0)
|
||||
#define TIMER0_CLOCK_ENABLE (((uint32)0x1) << AT91C_ID_TC0)
|
||||
#define PIOA_CLOCK_ENABLE (((uint32)0x1) << AT91C_ID_PIOA)
|
||||
#define PIOB_CLOCK_ENABLE (((uint32)0x1) << AT91C_ID_PIOB)
|
||||
#define TIOA0_PIN_MASK (((uint32)0x1) << 23) // Timer/Counter Output Pin
|
||||
|
||||
// Application Type Definitions
|
||||
typedef unsigned int uint32;
|
||||
typedef int int32;
|
||||
typedef unsigned short uint16;
|
||||
typedef short int16;
|
||||
typedef unsigned char uint8;
|
||||
typedef char int8;
|
||||
typedef char bool;
|
||||
|
||||
// Application Special Value Definitions
|
||||
#ifndef TRUE
|
||||
#define TRUE (1)
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
#ifndef NULL
|
||||
#define NULL (0)
|
||||
#endif // NULL
|
||||
#define DONT_CARE (0)
|
||||
|
||||
#ifndef INFINITY
|
||||
#define INFINITY (1.0 / 0.0)
|
||||
#endif
|
||||
|
||||
#ifndef NAN
|
||||
#define NAN (0.0 / 0.0)
|
||||
#endif
|
||||
|
||||
// MIN/MAX Definitions for Standard Types
|
||||
#ifndef INT8_MAX
|
||||
#define INT8_MAX 127
|
||||
#endif
|
||||
|
||||
#ifndef INT8_MIN
|
||||
#define INT8_MIN (-128)
|
||||
#endif
|
||||
|
||||
#ifndef UINT8_MAX
|
||||
#define UINT8_MAX 0xFFU
|
||||
#endif
|
||||
|
||||
#ifndef UINT8_MIN
|
||||
#define UINT8_MIN 0x00U
|
||||
#endif
|
||||
|
||||
#ifndef INT16_MAX
|
||||
#define INT16_MAX 32767
|
||||
#endif
|
||||
|
||||
#ifndef INT16_MIN
|
||||
#define INT16_MIN (-32768)
|
||||
#endif
|
||||
|
||||
#ifndef UINT16_MAX
|
||||
#define UINT16_MAX 0xFFFFU
|
||||
#endif
|
||||
|
||||
#ifndef UINT16_MIN
|
||||
#define UINT16_MIN 0x0000U
|
||||
#endif
|
||||
|
||||
#ifndef INT32_MAX
|
||||
#define INT32_MAX 0x7FFFFFFF
|
||||
#endif
|
||||
|
||||
#ifndef INT32_MIN
|
||||
#define INT32_MIN (-INT32_MAX - 1)
|
||||
#endif
|
||||
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX 0xFFFFFFFFU
|
||||
#endif
|
||||
|
||||
#ifndef UINT32_MIN
|
||||
#define UINT32_MIN 0x00000000U
|
||||
#endif
|
||||
|
||||
typedef struct _EXAMPLE_STRUCT_T
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
} EXAMPLE_STRUCT_T;
|
||||
|
||||
#endif // _MYTYPES_H_
|
||||
@ -0,0 +1,18 @@
|
||||
#include "Types.h"
|
||||
#include "UsartBaudRateRegisterCalculator.h"
|
||||
|
||||
uint8 UsartModel_CalculateBaudRateRegisterSetting(uint32 masterClock, uint32 baudRate)
|
||||
{
|
||||
uint32 registerSetting = ((masterClock * 10) / (baudRate * 16));
|
||||
|
||||
if ((registerSetting % 10) >= 5)
|
||||
{
|
||||
registerSetting = (registerSetting / 10) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
registerSetting /= 10;
|
||||
}
|
||||
|
||||
return (uint8)registerSetting;
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
#ifndef _USARTBAUDRATEREGISTERCALCULATOR_H
|
||||
#define _USARTBAUDRATEREGISTERCALCULATOR_H
|
||||
|
||||
uint8 UsartModel_CalculateBaudRateRegisterSetting(uint32 masterClock, uint32 baudRate);
|
||||
|
||||
#endif // _USARTBAUDRATEREGISTERCALCULATOR_H
|
||||
@ -0,0 +1,21 @@
|
||||
#include "Types.h"
|
||||
#include "UsartConductor.h"
|
||||
#include "UsartHardware.h"
|
||||
#include "UsartModel.h"
|
||||
#include "TaskScheduler.h"
|
||||
|
||||
void UsartConductor_Init(void)
|
||||
{
|
||||
UsartHardware_Init(UsartModel_GetBaudRateRegisterSetting());
|
||||
UsartHardware_TransmitString(UsartModel_GetWakeupMessage());
|
||||
}
|
||||
|
||||
void UsartConductor_Run(void)
|
||||
{
|
||||
char* temp;
|
||||
if (TaskScheduler_DoUsart())
|
||||
{
|
||||
temp = UsartModel_GetFormattedTemperature();
|
||||
UsartHardware_TransmitString(temp);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
#ifndef _USARTCONDUCTOR_H
|
||||
#define _USARTCONDUCTOR_H
|
||||
|
||||
void UsartConductor_Init(void);
|
||||
void UsartConductor_Run(void);
|
||||
|
||||
#endif // _USARTCONDUCTOR_H
|
||||
@ -0,0 +1,39 @@
|
||||
#include "Types.h"
|
||||
#include "UsartConfigurator.h"
|
||||
|
||||
void Usart_ConfigureUsartIO(void)
|
||||
{
|
||||
AT91C_BASE_PIOA->PIO_ASR = USART0_TX_PIN;
|
||||
AT91C_BASE_PIOA->PIO_BSR = 0;
|
||||
AT91C_BASE_PIOA->PIO_PDR = USART0_TX_PIN;
|
||||
}
|
||||
|
||||
void Usart_EnablePeripheralClock(void)
|
||||
{
|
||||
AT91C_BASE_PMC->PMC_PCER = ((uint32)1) << USART0_CLOCK_ENABLE;
|
||||
}
|
||||
|
||||
void Usart_Reset(void)
|
||||
{
|
||||
AT91C_BASE_US0->US_IDR = 0xffffffff;
|
||||
AT91C_BASE_US0->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS;
|
||||
}
|
||||
|
||||
void Usart_ConfigureMode(void)
|
||||
{
|
||||
AT91C_BASE_US0->US_MR = AT91C_US_USMODE_NORMAL |
|
||||
AT91C_US_NBSTOP_1_BIT |
|
||||
AT91C_US_PAR_NONE |
|
||||
AT91C_US_CHRL_8_BITS |
|
||||
AT91C_US_CLKS_CLOCK;
|
||||
}
|
||||
|
||||
void Usart_SetBaudRateRegister(uint8 baudRateRegisterSetting)
|
||||
{
|
||||
AT91C_BASE_US0->US_BRGR = baudRateRegisterSetting;
|
||||
}
|
||||
|
||||
void Usart_Enable(void)
|
||||
{
|
||||
AT91C_BASE_US0->US_CR = AT91C_US_TXEN;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
#ifndef _USARTCONFIGURATOR_H
|
||||
#define _USARTCONFIGURATOR_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
void Usart_ConfigureUsartIO(void);
|
||||
void Usart_EnablePeripheralClock(void);
|
||||
void Usart_Reset(void);
|
||||
void Usart_ConfigureMode(void);
|
||||
void Usart_SetBaudRateRegister(uint8 baudRateRegisterSetting);
|
||||
void Usart_Enable(void);
|
||||
|
||||
#endif // _USARTCONFIGURATOR_H
|
||||
@ -0,0 +1,22 @@
|
||||
#include "Types.h"
|
||||
#include "UsartHardware.h"
|
||||
#include "UsartConfigurator.h"
|
||||
#include "UsartPutChar.h"
|
||||
|
||||
void UsartHardware_Init(uint8 baudRateRegisterSetting)
|
||||
{
|
||||
Usart_ConfigureUsartIO();
|
||||
Usart_EnablePeripheralClock();
|
||||
Usart_Reset();
|
||||
Usart_ConfigureMode();
|
||||
Usart_SetBaudRateRegister(baudRateRegisterSetting);
|
||||
Usart_Enable();
|
||||
}
|
||||
|
||||
void UsartHardware_TransmitString(char* data)
|
||||
{
|
||||
while(*data != NULL)
|
||||
{
|
||||
Usart_PutChar(*data++);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
#ifndef _USARTHARDWARE_H
|
||||
#define _USARTHARDWARE_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
void UsartHardware_Init(uint8 baudRateRegisterSetting);
|
||||
void UsartHardware_TransmitString(char* data);
|
||||
|
||||
#endif // _USARTHARDWARE_H
|
||||
@ -0,0 +1,34 @@
|
||||
#include "Types.h"
|
||||
#include "UsartModel.h"
|
||||
#include "ModelConfig.h"
|
||||
#include "UsartBaudRateRegisterCalculator.h"
|
||||
#include "TemperatureFilter.h"
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
char formattedTemperature[32];
|
||||
char* wakeup = "It's Awesome Time!\n";
|
||||
|
||||
uint8 UsartModel_GetBaudRateRegisterSetting(void)
|
||||
{
|
||||
return UsartModel_CalculateBaudRateRegisterSetting(MASTER_CLOCK, USART0_BAUDRATE);
|
||||
}
|
||||
|
||||
char* UsartModel_GetFormattedTemperature(void)
|
||||
{
|
||||
float temperature = TemperatureFilter_GetTemperatureInCelcius();
|
||||
if (temperature == -INFINITY)
|
||||
{
|
||||
sprintf(formattedTemperature, "%s", "Temperature sensor failure!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(formattedTemperature, "%.1f C\n", temperature);
|
||||
}
|
||||
return formattedTemperature;
|
||||
}
|
||||
|
||||
char* UsartModel_GetWakeupMessage(void)
|
||||
{
|
||||
return wakeup;
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
#ifndef _USARTMODEL_H
|
||||
#define _USARTMODEL_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
uint8 UsartModel_GetBaudRateRegisterSetting(void);
|
||||
char* UsartModel_GetFormattedTemperature(void);
|
||||
char* UsartModel_GetWakeupMessage(void);
|
||||
|
||||
#endif // _USARTMODEL_H
|
||||
@ -0,0 +1,16 @@
|
||||
#include "Types.h"
|
||||
#include "UsartPutChar.h"
|
||||
#include "UsartTransmitBufferStatus.h"
|
||||
#ifdef SIMULATE
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
void Usart_PutChar(char data)
|
||||
{
|
||||
while(!Usart_ReadyToTransmit());
|
||||
#ifdef SIMULATE
|
||||
printf("%c", data);
|
||||
#else
|
||||
AT91C_BASE_US0->US_THR = data;
|
||||
#endif
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
#ifndef _USARTPUT_HAR_H
|
||||
#define _USARTPUT_HAR_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
void Usart_PutChar(char data);
|
||||
|
||||
#endif // _USARTPUT_HAR_H
|
||||
@ -0,0 +1,7 @@
|
||||
#include "Types.h"
|
||||
#include "UsartTransmitBufferStatus.h"
|
||||
|
||||
bool Usart_ReadyToTransmit(void)
|
||||
{
|
||||
return (AT91C_BASE_US0->US_CSR & AT91C_US_TXRDY) > 0;
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
#ifndef _USARTTRANSMITBUFFERSTATUS_H
|
||||
#define _USARTTRANSMITBUFFERSTATUS_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
bool Usart_ReadyToTransmit(void);
|
||||
|
||||
#endif // _USARTTRANSMITBUFFERSTATUS_H
|
||||
@ -0,0 +1,121 @@
|
||||
#include "unity.h"
|
||||
#include "UnityHelper.h"
|
||||
#include "Types.h"
|
||||
#include "Types.h"
|
||||
#include "AdcConductor.h"
|
||||
#include "MockAdcModel.h"
|
||||
#include "MockAdcHardware.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testInitShouldCallHardwareInit(void)
|
||||
{
|
||||
AdcHardware_Init_Expect();
|
||||
AdcConductor_Init();
|
||||
}
|
||||
|
||||
void testRunShouldNotDoAnythingIfItIsNotTime(void)
|
||||
{
|
||||
AdcModel_DoGetSample_ExpectAndReturn(FALSE);
|
||||
|
||||
AdcConductor_Run();
|
||||
}
|
||||
|
||||
void testRunShouldNotPassAdcResultToModelIfSampleIsNotComplete(void)
|
||||
{
|
||||
AdcModel_DoGetSample_ExpectAndReturn(TRUE);
|
||||
AdcHardware_GetSampleComplete_ExpectAndReturn(FALSE);
|
||||
|
||||
AdcConductor_Run();
|
||||
}
|
||||
|
||||
void testRunShouldGetLatestSampleFromAdcAndPassItToModelAndStartNewConversionWhenItIsTime(void)
|
||||
{
|
||||
AdcModel_DoGetSample_ExpectAndReturn(TRUE);
|
||||
AdcHardware_GetSampleComplete_ExpectAndReturn(TRUE);
|
||||
AdcHardware_GetSample_ExpectAndReturn(293U);
|
||||
AdcModel_ProcessInput_Expect(293U);
|
||||
AdcHardware_StartConversion_Expect();
|
||||
|
||||
AdcConductor_Run();
|
||||
}
|
||||
|
||||
void testJustHereToTest_Should_ProperlyPassAStructAndVerifyIt(void)
|
||||
{
|
||||
EXAMPLE_STRUCT_T TestStruct;
|
||||
TestStruct.x = 5;
|
||||
TestStruct.y = 7;
|
||||
|
||||
AdcModel_DoNothingExceptTestASpecialType_ExpectAndReturn(TestStruct, TRUE);
|
||||
|
||||
TEST_ASSERT_TRUE(AdcConductor_JustHereToTest());
|
||||
}
|
||||
|
||||
//void testJustHereToTest_Should_FailThisTestIfYouUncommentXIsBecauseItsWrong(void)
|
||||
//{
|
||||
// EXAMPLE_STRUCT_T TestStruct;
|
||||
// TestStruct.x = 6;
|
||||
// TestStruct.y = 7;
|
||||
//
|
||||
// AdcModel_DoNothingExceptTestASpecialType_ExpectAndReturn(TestStruct, TRUE);
|
||||
//
|
||||
// TEST_ASSERT_TRUE(AdcConductor_JustHereToTest());
|
||||
//}
|
||||
//
|
||||
//void testJustHereToTest_Should_FailThisTestIfYouUncommentYIsBecauseItsWrong(void)
|
||||
//{
|
||||
// EXAMPLE_STRUCT_T TestStruct;
|
||||
// TestStruct.x = 5;
|
||||
// TestStruct.y = 8;
|
||||
//
|
||||
// AdcModel_DoNothingExceptTestASpecialType_ExpectAndReturn(TestStruct, TRUE);
|
||||
//
|
||||
// TEST_ASSERT_TRUE(AdcConductor_JustHereToTest());
|
||||
//}
|
||||
|
||||
void test_AdcConductor_AlsoHereToTest_Should_ProperlyReturnAStructAsExpected1(void)
|
||||
{
|
||||
EXAMPLE_STRUCT_T TestStruct;
|
||||
TestStruct.x = 99;
|
||||
TestStruct.y = 1;
|
||||
|
||||
AdcModel_DoNothingExceptReturnASpecialType_ExpectAndReturn(TestStruct);
|
||||
|
||||
TEST_ASSERT_TRUE(AdcConductor_AlsoHereToTest());
|
||||
}
|
||||
|
||||
void test_AdcConductor_AlsoHereToTest_Should_ProperlyReturnAStructAsExpected2(void)
|
||||
{
|
||||
EXAMPLE_STRUCT_T TestStruct;
|
||||
TestStruct.x = 98;
|
||||
TestStruct.y = 1;
|
||||
|
||||
AdcModel_DoNothingExceptReturnASpecialType_ExpectAndReturn(TestStruct);
|
||||
|
||||
TEST_ASSERT_FALSE(AdcConductor_AlsoHereToTest());
|
||||
}
|
||||
|
||||
void test_AdcConductor_YetAnotherTest_Should_VerifyThatPointersToStructsAreTestable(void)
|
||||
{
|
||||
uint32 TestNum = 3;
|
||||
|
||||
AdModel_DoNothingExceptTestPointers_ExpectAndReturn(&TestNum, TRUE);
|
||||
|
||||
TEST_ASSERT_TRUE(AdcConductor_YetAnotherTest());
|
||||
}
|
||||
|
||||
//void test_AdcConductor_YetAnotherTest_Should_FailIfYouUncommentThisTestBecauseTheValuePointedToIsWrong(void)
|
||||
//{
|
||||
// uint32 TestNum = 7;
|
||||
//
|
||||
// AdModel_DoNothingExceptTestPointers_ExpectAndReturn(&TestNum, FALSE);
|
||||
//
|
||||
// TEST_ASSERT_FALSE(AdcConductor_YetAnotherTest());
|
||||
//}
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "AdcHardware.h"
|
||||
#include "MockAdcHardwareConfigurator.h"
|
||||
#include "MockAdcTemperatureSensor.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testInitShouldDelegateToConfiguratorAndTemperatureSensor(void)
|
||||
{
|
||||
Adc_Reset_Expect();
|
||||
Adc_ConfigureMode_Expect();
|
||||
Adc_EnableTemperatureChannel_Expect();
|
||||
Adc_StartTemperatureSensorConversion_Expect();
|
||||
|
||||
AdcHardware_Init();
|
||||
}
|
||||
|
||||
void testGetSampleCompleteShouldReturn_FALSE_WhenTemperatureSensorSampleReadyReturns_FALSE(void)
|
||||
{
|
||||
Adc_TemperatureSensorSampleReady_ExpectAndReturn(FALSE);
|
||||
TEST_ASSERT(!AdcHardware_GetSampleComplete());
|
||||
}
|
||||
|
||||
void testGetSampleCompleteShouldReturn_TRUE_WhenTemperatureSensorSampleReadyReturns_TRUE(void)
|
||||
{
|
||||
Adc_TemperatureSensorSampleReady_ExpectAndReturn(TRUE);
|
||||
TEST_ASSERT(AdcHardware_GetSampleComplete());
|
||||
}
|
||||
|
||||
void testGetSampleShouldDelegateToAdcTemperatureSensor(void)
|
||||
{
|
||||
uint16 sample;
|
||||
Adc_ReadTemperatureSensor_ExpectAndReturn(847);
|
||||
|
||||
sample = AdcHardware_GetSample();
|
||||
TEST_ASSERT_EQUAL(847, sample);
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "AdcHardwareConfigurator.h"
|
||||
#include "AT91SAM7X256.h"
|
||||
#include "ModelConfig.h"
|
||||
|
||||
AT91S_ADC AdcPeripheral;
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testResetShouldResetTheAdcConverterPeripheral(void)
|
||||
{
|
||||
AT91C_BASE_ADC->ADC_CR = 0;
|
||||
Adc_Reset();
|
||||
TEST_ASSERT_EQUAL(AT91C_ADC_SWRST, AT91C_BASE_ADC->ADC_CR);
|
||||
}
|
||||
|
||||
void testConfigureModeShouldSetAdcModeRegisterAppropriately(void)
|
||||
{
|
||||
uint32 prescaler = (MASTER_CLOCK / (2 * 2000000)) - 1; // 5MHz ADC clock
|
||||
|
||||
AT91C_BASE_ADC->ADC_MR = 0;
|
||||
|
||||
Adc_ConfigureMode();
|
||||
|
||||
TEST_ASSERT_EQUAL(prescaler, (AT91C_BASE_ADC->ADC_MR & AT91C_ADC_PRESCAL) >> 8);
|
||||
}
|
||||
|
||||
void testEnableTemperatureChannelShouldEnableTheAppropriateAdcInput(void)
|
||||
{
|
||||
AT91C_BASE_ADC->ADC_CHER = 0;
|
||||
|
||||
Adc_EnableTemperatureChannel();
|
||||
|
||||
TEST_ASSERT_EQUAL(0x1 << 4, AT91C_BASE_ADC->ADC_CHER);
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "AdcModel.h"
|
||||
#include "MockTaskScheduler.h"
|
||||
#include "MockTemperatureCalculator.h"
|
||||
#include "MockTemperatureFilter.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testDoGetSampleShouldReturn_FALSE_WhenTaskSchedulerReturns_FALSE(void)
|
||||
{
|
||||
TaskScheduler_DoAdc_ExpectAndReturn(FALSE);
|
||||
TEST_ASSERT_EQUAL(FALSE, AdcModel_DoGetSample());
|
||||
}
|
||||
|
||||
void testDoGetSampleShouldReturn_TRUE_WhenTaskSchedulerReturns_TRUE(void)
|
||||
{
|
||||
TaskScheduler_DoAdc_ExpectAndReturn(TRUE);
|
||||
TEST_ASSERT_EQUAL(TRUE, AdcModel_DoGetSample());
|
||||
}
|
||||
|
||||
void testProcessInputShouldDelegateToTemperatureCalculatorAndPassResultToFilter(void)
|
||||
{
|
||||
TemperatureCalculator_Calculate_ExpectAndReturn(21473, 23.5f);
|
||||
TemperatureFilter_ProcessInput_Expect(23.5f);
|
||||
AdcModel_ProcessInput(21473);
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "AdcTemperatureSensor.h"
|
||||
#include "AT91SAM7X256.h"
|
||||
|
||||
AT91S_ADC AdcPeripheral;
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testShouldStartTemperatureSensorConversionWhenTriggered(void)
|
||||
{
|
||||
AT91C_BASE_ADC->ADC_CR = 0;
|
||||
Adc_StartTemperatureSensorConversion();
|
||||
TEST_ASSERT_EQUAL(AT91C_ADC_START, AT91C_BASE_ADC->ADC_CR);
|
||||
}
|
||||
|
||||
void testTemperatureSensorSampleReadyShouldReturnChannelConversionCompletionStatus(void)
|
||||
{
|
||||
AT91C_BASE_ADC->ADC_SR = 0;
|
||||
TEST_ASSERT_EQUAL(FALSE, Adc_TemperatureSensorSampleReady());
|
||||
AT91C_BASE_ADC->ADC_SR = ~AT91C_ADC_EOC4;
|
||||
TEST_ASSERT_EQUAL(FALSE, Adc_TemperatureSensorSampleReady());
|
||||
AT91C_BASE_ADC->ADC_SR = AT91C_ADC_EOC4;
|
||||
TEST_ASSERT_EQUAL(TRUE, Adc_TemperatureSensorSampleReady());
|
||||
AT91C_BASE_ADC->ADC_SR = 0xffffffff;
|
||||
TEST_ASSERT_EQUAL(TRUE, Adc_TemperatureSensorSampleReady());
|
||||
}
|
||||
|
||||
void testReadTemperatureSensorShouldFetchAndTranslateLatestReadingToMillivolts(void)
|
||||
{
|
||||
uint16 result;
|
||||
|
||||
// ADC bit weight at 10-bit resolution with 3.0V reference = 2.9296875 mV/LSB
|
||||
AT91C_BASE_ADC->ADC_CDR4 = 138;
|
||||
result = Adc_ReadTemperatureSensor();
|
||||
TEST_ASSERT_EQUAL(404, result);
|
||||
|
||||
AT91C_BASE_ADC->ADC_CDR4 = 854;
|
||||
result = Adc_ReadTemperatureSensor();
|
||||
TEST_ASSERT_EQUAL(2502, result);
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "Executor.h"
|
||||
#include "MockModel.h"
|
||||
#include "MockUsartConductor.h"
|
||||
#include "MockAdcConductor.h"
|
||||
#include "MockTimerConductor.h"
|
||||
#include "MockIntrinsicsWrapper.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testInitShouldCallInitOfAllConductorsAndTheModel(void)
|
||||
{
|
||||
Model_Init_Expect();
|
||||
UsartConductor_Init_Expect();
|
||||
AdcConductor_Init_Expect();
|
||||
TimerConductor_Init_Expect();
|
||||
Interrupt_Enable_Expect();
|
||||
|
||||
Executor_Init();
|
||||
}
|
||||
|
||||
void testRunShouldCallRunForEachConductorAndReturnTrueAlways(void)
|
||||
{
|
||||
UsartConductor_Run_Expect();
|
||||
TimerConductor_Run_Expect();
|
||||
AdcConductor_Run_Expect();
|
||||
|
||||
TEST_ASSERT_EQUAL(TRUE, Executor_Run());
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "MockExecutor.h"
|
||||
#include "Main.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testMainShouldCallExecutorInitAndContinueToCallExecutorRunUntilHalted(void)
|
||||
{
|
||||
Executor_Init_Expect();
|
||||
Executor_Run_ExpectAndReturn(TRUE);
|
||||
Executor_Run_ExpectAndReturn(TRUE);
|
||||
Executor_Run_ExpectAndReturn(TRUE);
|
||||
Executor_Run_ExpectAndReturn(TRUE);
|
||||
Executor_Run_ExpectAndReturn(FALSE);
|
||||
|
||||
AppMain();
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "Model.h"
|
||||
#include "MockTaskScheduler.h"
|
||||
#include "MockTemperatureFilter.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testInitShouldCallSchedulerAndTemperatureFilterInit(void)
|
||||
{
|
||||
TaskScheduler_Init_Expect();
|
||||
TemperatureFilter_Init_Expect();
|
||||
Model_Init();
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "TaskScheduler.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
TaskScheduler_Init();
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testShouldScheduleUsartTaskAfter1000ms(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoUsart());
|
||||
|
||||
TaskScheduler_Update(999);
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoUsart());
|
||||
|
||||
TaskScheduler_Update(1000);
|
||||
TEST_ASSERT_EQUAL(TRUE, TaskScheduler_DoUsart());
|
||||
}
|
||||
|
||||
void testShouldClearUsartDoFlagAfterReported(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoUsart());
|
||||
TaskScheduler_Update(1000);
|
||||
TEST_ASSERT_EQUAL(TRUE, TaskScheduler_DoUsart());
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoUsart());
|
||||
}
|
||||
|
||||
void testShouldScheduleUsartTaskEvery1000ms(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoUsart());
|
||||
|
||||
TaskScheduler_Update(1300);
|
||||
TEST_ASSERT_EQUAL(TRUE, TaskScheduler_DoUsart());
|
||||
|
||||
TaskScheduler_Update(2000);
|
||||
TEST_ASSERT_EQUAL(TRUE, TaskScheduler_DoUsart());
|
||||
|
||||
TaskScheduler_Update(3100);
|
||||
TEST_ASSERT_EQUAL(TRUE, TaskScheduler_DoUsart());
|
||||
}
|
||||
|
||||
void testShouldScheduleUsartTaskOnlyOncePerPeriod(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoUsart());
|
||||
TaskScheduler_Update(1000);
|
||||
TEST_ASSERT_EQUAL(TRUE, TaskScheduler_DoUsart());
|
||||
TaskScheduler_Update(1001);
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoUsart());
|
||||
TaskScheduler_Update(1999);
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoUsart());
|
||||
TaskScheduler_Update(2000);
|
||||
TEST_ASSERT_EQUAL(TRUE, TaskScheduler_DoUsart());
|
||||
}
|
||||
|
||||
void testShouldScheduleAdcTaskAfter100ms(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoAdc());
|
||||
|
||||
TaskScheduler_Update(99);
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoAdc());
|
||||
|
||||
TaskScheduler_Update(100);
|
||||
TEST_ASSERT_EQUAL(TRUE, TaskScheduler_DoAdc());
|
||||
}
|
||||
|
||||
void testShouldClearAdcDoFlagAfterReported(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoAdc());
|
||||
TaskScheduler_Update(100);
|
||||
TEST_ASSERT_EQUAL(TRUE, TaskScheduler_DoAdc());
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoAdc());
|
||||
}
|
||||
|
||||
void testShouldScheduleAdcTaskEvery100ms(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoAdc());
|
||||
|
||||
TaskScheduler_Update(121);
|
||||
TEST_ASSERT_EQUAL(TRUE, TaskScheduler_DoAdc());
|
||||
|
||||
TaskScheduler_Update(200);
|
||||
TEST_ASSERT_EQUAL(TRUE, TaskScheduler_DoAdc());
|
||||
|
||||
TaskScheduler_Update(356);
|
||||
TEST_ASSERT_EQUAL(TRUE, TaskScheduler_DoAdc());
|
||||
}
|
||||
|
||||
void testShouldScheduleAdcTaskOnlyOncePerPeriod(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoAdc());
|
||||
TaskScheduler_Update(100);
|
||||
TEST_ASSERT_EQUAL(TRUE, TaskScheduler_DoAdc());
|
||||
TaskScheduler_Update(101);
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoAdc());
|
||||
TaskScheduler_Update(199);
|
||||
TEST_ASSERT_EQUAL(FALSE, TaskScheduler_DoAdc());
|
||||
TaskScheduler_Update(200);
|
||||
TEST_ASSERT_EQUAL(TRUE, TaskScheduler_DoAdc());
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "TemperatureCalculator.h"
|
||||
#include <math.h>
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testTemperatureCalculatorShouldCalculateTemperatureFromMillivolts(void)
|
||||
{
|
||||
float result;
|
||||
|
||||
// Series resistor is 5k Ohms; Reference voltage is 3.0V
|
||||
// R(t) = A * e^(B*t); R is resistance of thermisor; t is temperature in C
|
||||
result = TemperatureCalculator_Calculate(1000);
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 25.0f, result);
|
||||
|
||||
result = TemperatureCalculator_Calculate(2985);
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 68.317f, result);
|
||||
|
||||
result = TemperatureCalculator_Calculate(3);
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, -19.96f, result);
|
||||
}
|
||||
|
||||
void testShouldReturnNegativeInfinityWhen_0_millivoltsInput(void)
|
||||
{
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.0000001f, -INFINITY, TemperatureCalculator_Calculate(0));
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "TemperatureFilter.h"
|
||||
#include <math.h>
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
TemperatureFilter_Init();
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testShouldInitializeTemeratureToInvalidValue(void)
|
||||
{
|
||||
TemperatureFilter_Init();
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.0001f, -INFINITY, TemperatureFilter_GetTemperatureInCelcius());
|
||||
}
|
||||
|
||||
void testShouldInitializeTemperatureAfterCallToInit(void)
|
||||
{
|
||||
TemperatureFilter_Init();
|
||||
TemperatureFilter_ProcessInput(17.8f);
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.0001f, 17.8f, TemperatureFilter_GetTemperatureInCelcius());
|
||||
|
||||
TemperatureFilter_Init();
|
||||
TemperatureFilter_ProcessInput(32.6f);
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.0001f, 32.6f, TemperatureFilter_GetTemperatureInCelcius());
|
||||
}
|
||||
|
||||
void setValueAndVerifyResponse(float input, float response)
|
||||
{
|
||||
float actual;
|
||||
TemperatureFilter_ProcessInput(input);
|
||||
actual = TemperatureFilter_GetTemperatureInCelcius();
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.0001f, response, actual);
|
||||
}
|
||||
|
||||
void testShouldWeightEachSubsequentValueBy25PercentAfterInitialValue(void)
|
||||
{
|
||||
TemperatureFilter_Init();
|
||||
setValueAndVerifyResponse(0.0f, 0.0f);
|
||||
setValueAndVerifyResponse(10.0f, 2.5f);
|
||||
setValueAndVerifyResponse(10.0f, 4.375f);
|
||||
setValueAndVerifyResponse(10.0f, 5.78125f);
|
||||
|
||||
TemperatureFilter_Init();
|
||||
setValueAndVerifyResponse(100.0f, 100.0f);
|
||||
setValueAndVerifyResponse(0.0f, 75.0f);
|
||||
setValueAndVerifyResponse(0.0f, 56.25f);
|
||||
setValueAndVerifyResponse(0.0f, 42.1875f);
|
||||
}
|
||||
|
||||
void setInvalidTemperatureAndVerifyReinitialized(float invalidTemperature)
|
||||
{
|
||||
TemperatureFilter_Init();
|
||||
setValueAndVerifyResponse(100.0f, 100.0f);
|
||||
setValueAndVerifyResponse(invalidTemperature, -INFINITY);
|
||||
setValueAndVerifyResponse(14.3f, 14.3f);
|
||||
}
|
||||
|
||||
void testShouldResetAverageIfPassedInfinityOrInvalidValue(void)
|
||||
{
|
||||
setInvalidTemperatureAndVerifyReinitialized(-INFINITY);
|
||||
setInvalidTemperatureAndVerifyReinitialized(+INFINITY);
|
||||
setInvalidTemperatureAndVerifyReinitialized(+NAN);
|
||||
setInvalidTemperatureAndVerifyReinitialized(-NAN);
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "TimerConductor.h"
|
||||
#include "MockTimerHardware.h"
|
||||
#include "MockTimerModel.h"
|
||||
#include "MockTimerInterruptHandler.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testInitShouldCallHardwareInit(void)
|
||||
{
|
||||
TimerHardware_Init_Expect();
|
||||
|
||||
TimerConductor_Init();
|
||||
}
|
||||
|
||||
void testRunShouldGetSystemTimeAndPassOnToModelForEventScheduling(void)
|
||||
{
|
||||
Timer_GetSystemTime_ExpectAndReturn(1230);
|
||||
TimerModel_UpdateTime_Expect(1230);
|
||||
TimerConductor_Run();
|
||||
|
||||
Timer_GetSystemTime_ExpectAndReturn(837460);
|
||||
TimerModel_UpdateTime_Expect(837460);
|
||||
TimerConductor_Run();
|
||||
}
|
||||
@ -0,0 +1,112 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "TimerConfigurator.h"
|
||||
#include "AT91SAM7X256.h"
|
||||
#include "MockTimerInterruptConfigurator.h"
|
||||
|
||||
AT91S_PMC PmcPeripheral;
|
||||
AT91S_TC TimerCounter0Peripheral;
|
||||
AT91S_PIO PioBPeripheral;
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testEnablePeripheralClocksShouldEnableClockToTimer0Peripheral(void)
|
||||
{
|
||||
AT91C_BASE_PMC->PMC_PCER = 0;
|
||||
Timer_EnablePeripheralClocks();
|
||||
TEST_ASSERT_EQUAL(
|
||||
TIMER0_CLOCK_ENABLE,
|
||||
AT91C_BASE_PMC->PMC_PCER & TIMER0_CLOCK_ENABLE);
|
||||
}
|
||||
|
||||
void testEnablePeripheralClocksShouldEnableClockToPIOBPeripheral(void)
|
||||
{
|
||||
AT91C_BASE_PMC->PMC_PCER = 0;
|
||||
Timer_EnablePeripheralClocks();
|
||||
TEST_ASSERT_EQUAL(
|
||||
PIOB_CLOCK_ENABLE,
|
||||
AT91C_BASE_PMC->PMC_PCER & PIOB_CLOCK_ENABLE);
|
||||
}
|
||||
|
||||
void testResetShouldSetTimer0ClockDisableBit_DisableTimer0Interrupts_ClearStatusRegister(void)
|
||||
{
|
||||
AT91C_BASE_TC0->TC_CCR = 0;
|
||||
AT91C_BASE_TC0->TC_IDR = 0;
|
||||
AT91C_BASE_TC0->TC_SR = 0xFFFFFFFF;
|
||||
Timer_Reset();
|
||||
TEST_ASSERT_EQUAL(0x00000002, AT91C_BASE_TC0->TC_CCR);
|
||||
TEST_ASSERT_EQUAL(0xffffffff, AT91C_BASE_TC0->TC_IDR);
|
||||
// CANNOT BE VERIFIED!! TEST_ASSERT_EQUAL(0X00000000, AT91C_BASE_TC0->TC_SR);
|
||||
}
|
||||
|
||||
void testEnableOutputPinShouldEnable_TIOA0_DigitalOutput(void)
|
||||
{
|
||||
AT91C_BASE_PIOB->PIO_PDR = 0;
|
||||
Timer_EnableOutputPin();
|
||||
TEST_ASSERT_EQUAL(TIOA0_PIN_MASK, AT91C_BASE_PIOB->PIO_PDR);
|
||||
}
|
||||
|
||||
void testConfigureModeShouldConfigureTimer0ClockSourceForMasterClockDividedBy1024(void)
|
||||
{
|
||||
AT91C_BASE_TC0->TC_CMR = 0;
|
||||
Timer_ConfigureMode();
|
||||
TEST_ASSERT_EQUAL(0x00000004, AT91C_BASE_TC0->TC_CMR & 0x00000007);
|
||||
}
|
||||
|
||||
void testConfigureModeShouldConfigureTimer0ForWaveGeneration(void)
|
||||
{
|
||||
AT91C_BASE_TC0->TC_CMR = 0;
|
||||
Timer_ConfigureMode();
|
||||
TEST_ASSERT_EQUAL(0x00008000, AT91C_BASE_TC0->TC_CMR & 0x00008000);
|
||||
}
|
||||
|
||||
void testConfigureModeShouldConfigureTimer0ForUpModeWithAutomaticTriggerOnRCCompare(void)
|
||||
{
|
||||
AT91C_BASE_TC0->TC_CMR = 0;
|
||||
Timer_ConfigureMode();
|
||||
TEST_ASSERT_EQUAL(0x00004000, AT91C_BASE_TC0->TC_CMR & 0x00006000);
|
||||
}
|
||||
|
||||
void testConfigureModeShouldConfigureTimer0ToToggleTIOAOnRCCompare(void)
|
||||
{
|
||||
AT91C_BASE_TC0->TC_CMR = 0;
|
||||
Timer_ConfigureMode();
|
||||
TEST_ASSERT_EQUAL(0x000C0000, AT91C_BASE_TC0->TC_CMR & 0x000C0000);
|
||||
}
|
||||
|
||||
void testConfigurePeriodShouldConfigureRegisterCFor10msInterval(void)
|
||||
{
|
||||
AT91C_BASE_TC0->TC_RC = 0;
|
||||
Timer_ConfigurePeriod();
|
||||
TEST_ASSERT_EQUAL(469, AT91C_BASE_TC0->TC_RC);
|
||||
}
|
||||
|
||||
void testEnableShouldSetEnableFlagForTimer0(void)
|
||||
{
|
||||
AT91C_BASE_TC0->TC_CCR = 0;
|
||||
Timer_Enable();
|
||||
TEST_ASSERT_EQUAL_INT(1, AT91C_BASE_TC0->TC_CCR);
|
||||
}
|
||||
|
||||
void testConfigureInterruptHandler(void)
|
||||
{
|
||||
Timer_DisableInterrupt_Expect();
|
||||
Timer_ResetSystemTime_Expect();
|
||||
Timer_ConfigureInterrupt_Expect();
|
||||
Timer_EnableInterrupt_Expect();
|
||||
|
||||
Timer_ConfigureInterruptHandler();
|
||||
}
|
||||
|
||||
void testStartShouldSetSoftwareTriggerFlag(void)
|
||||
{
|
||||
AT91C_BASE_TC0->TC_CCR = 0;
|
||||
Timer_Start();
|
||||
TEST_ASSERT_EQUAL(0x04, AT91C_BASE_TC0->TC_CCR);
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "TimerHardware.h"
|
||||
#include "MockTimerConfigurator.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testInitShouldDelegateAppropriatelyToConfigurator(void)
|
||||
{
|
||||
Timer_EnablePeripheralClocks_Expect();
|
||||
Timer_Reset_Expect();
|
||||
Timer_ConfigureMode_Expect();
|
||||
Timer_ConfigurePeriod_Expect();
|
||||
Timer_EnableOutputPin_Expect();
|
||||
Timer_Enable_Expect();
|
||||
Timer_ConfigureInterruptHandler_Expect();
|
||||
Timer_Start_Expect();
|
||||
|
||||
TimerHardware_Init();
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "TimerInterruptConfigurator.h"
|
||||
#include "MockTimerInterruptHandler.h"
|
||||
#include "AT91SAM7X256.h"
|
||||
|
||||
AT91S_AIC AicPeripheral;
|
||||
AT91S_TC TimerCounter0Peripheral;
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void test_TIMER0_ID_MASK_ShouldBeCorrect(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(((uint32)0x1) << AT91C_ID_TC0, TIMER0_ID_MASK);
|
||||
}
|
||||
|
||||
void testDisableInterruptDisablesTimer0InterruptInTheInterruptController(void)
|
||||
{
|
||||
AT91C_BASE_AIC->AIC_IDCR = 0;
|
||||
Timer_DisableInterrupt();
|
||||
TEST_ASSERT_EQUAL(TIMER0_ID_MASK, AT91C_BASE_AIC->AIC_IDCR);
|
||||
}
|
||||
|
||||
void testResetSystemTimeDelegatesTo_Timer_SetSystemTime_Appropriately(void)
|
||||
{
|
||||
Timer_SetSystemTime_Expect(0);
|
||||
Timer_ResetSystemTime();
|
||||
}
|
||||
|
||||
void testConfigureInterruptShouldSetInterruptHandlerAppropriately(void)
|
||||
{
|
||||
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC0] = (uint32)NULL;
|
||||
Timer_ConfigureInterrupt();
|
||||
TEST_ASSERT_EQUAL((uint32)Timer_InterruptHandler, AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC0]);
|
||||
}
|
||||
|
||||
void testConfigureInterruptShouldSetInterruptLevelInSourceModeRegisterAppropriately(void)
|
||||
{
|
||||
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] = 0;
|
||||
Timer_ConfigureInterrupt();
|
||||
TEST_ASSERT_EQUAL(
|
||||
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
|
||||
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] & 0x00000060);
|
||||
}
|
||||
|
||||
void testConfigureInterruptShouldSetInterruptPriorityInSourceModeRegisterAppropriately(void)
|
||||
{
|
||||
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] = 0;
|
||||
Timer_ConfigureInterrupt();
|
||||
TEST_ASSERT_EQUAL(1, AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC0] & 0x00000007);
|
||||
}
|
||||
|
||||
void testConfigureInterruptShouldClearTimer0InterruptOnTheInterruptController(void)
|
||||
{
|
||||
AT91C_BASE_AIC->AIC_ICCR = 0;
|
||||
Timer_ConfigureInterrupt();
|
||||
TEST_ASSERT_EQUAL(TIMER0_ID_MASK, AT91C_BASE_AIC->AIC_ICCR);
|
||||
}
|
||||
|
||||
void testConfigureInterruptShouldEnableCompareInterruptForRegisterC(void)
|
||||
{
|
||||
AT91C_BASE_TC0->TC_IER = 0;
|
||||
Timer_ConfigureInterrupt();
|
||||
TEST_ASSERT_EQUAL(AT91C_TC_CPCS, AT91C_BASE_TC0->TC_IER);
|
||||
}
|
||||
|
||||
void testEnableInterruptShouldEnableTimer0InterruptsInInterruptCotroller(void)
|
||||
{
|
||||
AT91C_BASE_AIC->AIC_IECR = 0;
|
||||
Timer_EnableInterrupt();
|
||||
TEST_ASSERT_EQUAL(TIMER0_ID_MASK, AT91C_BASE_AIC->AIC_IECR);
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "TimerInterruptHandler.h"
|
||||
#include "AT91SAM7X256.h"
|
||||
|
||||
AT91S_TC TimerCounter0Peripheral;
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testSetAndGetSystemTime(void)
|
||||
{
|
||||
Timer_SetSystemTime(0);
|
||||
TEST_ASSERT_EQUAL(0, Timer_GetSystemTime());
|
||||
|
||||
Timer_SetSystemTime(129837);
|
||||
TEST_ASSERT_EQUAL(129837, Timer_GetSystemTime());
|
||||
|
||||
Timer_SetSystemTime(UINT32_MAX);
|
||||
TEST_ASSERT_EQUAL(UINT32_MAX, Timer_GetSystemTime());
|
||||
}
|
||||
|
||||
void testInterruptHandlerShouldIncrementSystemTimeOnlyIfStatusHasCompareRegisterCOverflowBitSet(void)
|
||||
{
|
||||
Timer_SetSystemTime(0);
|
||||
AT91C_BASE_TC0->TC_SR = 0;
|
||||
Timer_InterruptHandler();
|
||||
TEST_ASSERT_EQUAL(0, Timer_GetSystemTime());
|
||||
|
||||
Timer_SetSystemTime(0);
|
||||
AT91C_BASE_TC0->TC_SR = ~AT91C_TC_CPCS;
|
||||
Timer_InterruptHandler();
|
||||
TEST_ASSERT_EQUAL(0, Timer_GetSystemTime());
|
||||
|
||||
Timer_SetSystemTime(0);
|
||||
AT91C_BASE_TC0->TC_SR = AT91C_TC_CPCS;
|
||||
Timer_InterruptHandler();
|
||||
TEST_ASSERT(Timer_GetSystemTime() > 0);
|
||||
|
||||
Timer_SetSystemTime(0);
|
||||
AT91C_BASE_TC0->TC_SR = 0xffffffff;
|
||||
Timer_InterruptHandler();
|
||||
TEST_ASSERT(Timer_GetSystemTime() > 0);
|
||||
}
|
||||
|
||||
void testInterruptHandlerShouldIncrementSystemTimerBy_10(void)
|
||||
{
|
||||
Timer_SetSystemTime(0);
|
||||
AT91C_BASE_TC0->TC_SR = AT91C_TC_CPCS;
|
||||
Timer_InterruptHandler();
|
||||
TEST_ASSERT_EQUAL(10, Timer_GetSystemTime());
|
||||
|
||||
AT91C_BASE_TC0->TC_SR = AT91C_TC_CPCS;
|
||||
Timer_InterruptHandler();
|
||||
TEST_ASSERT_EQUAL(20, Timer_GetSystemTime());
|
||||
|
||||
Timer_SetSystemTime(39426857);
|
||||
AT91C_BASE_TC0->TC_SR = AT91C_TC_CPCS;
|
||||
Timer_InterruptHandler();
|
||||
TEST_ASSERT_EQUAL(39426867, Timer_GetSystemTime());
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "TimerModel.h"
|
||||
#include "MockTaskScheduler.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testUpdateTimeShouldDelegateToTaskScheduler(void)
|
||||
{
|
||||
TaskScheduler_Update_Expect(19387L);
|
||||
TimerModel_UpdateTime(19387L);
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "UsartBaudRateRegisterCalculator.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testCalculateBaudRateRegisterSettingShouldCalculateRegisterSettingAppropriately(void)
|
||||
{
|
||||
// BaudRate = MCK / (CD x 16) - per datasheet section 30.6.1.2 "Baud Rate Calculation Example"
|
||||
TEST_ASSERT_EQUAL(26, UsartModel_CalculateBaudRateRegisterSetting(48000000, 115200));
|
||||
TEST_ASSERT_EQUAL(6, UsartModel_CalculateBaudRateRegisterSetting(3686400, 38400));
|
||||
TEST_ASSERT_EQUAL(23, UsartModel_CalculateBaudRateRegisterSetting(14318180, 38400));
|
||||
TEST_ASSERT_EQUAL(20, UsartModel_CalculateBaudRateRegisterSetting(12000000, 38400));
|
||||
TEST_ASSERT_EQUAL(13, UsartModel_CalculateBaudRateRegisterSetting(12000000, 56800));
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "UsartConductor.h"
|
||||
#include "MockUsartModel.h"
|
||||
#include "MockUsartHardware.h"
|
||||
#include "MockTaskScheduler.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testShouldInitializeHardwareWhenInitCalled(void)
|
||||
{
|
||||
UsartModel_GetBaudRateRegisterSetting_ExpectAndReturn(4);
|
||||
UsartModel_GetWakeupMessage_ExpectAndReturn("Hey there!");
|
||||
UsartHardware_TransmitString_Expect("Hey there!");
|
||||
UsartHardware_Init_Expect(4);
|
||||
|
||||
UsartConductor_Init();
|
||||
}
|
||||
|
||||
void testRunShouldNotDoAnythingIfSchedulerSaysItIsNotTimeYet(void)
|
||||
{
|
||||
TaskScheduler_DoUsart_ExpectAndReturn(FALSE);
|
||||
|
||||
UsartConductor_Run();
|
||||
}
|
||||
|
||||
void testRunShouldGetCurrentTemperatureAndTransmitIfSchedulerSaysItIsTime(void)
|
||||
{
|
||||
TaskScheduler_DoUsart_ExpectAndReturn(TRUE);
|
||||
UsartModel_GetFormattedTemperature_ExpectAndReturn("hey there");
|
||||
UsartHardware_TransmitString_Expect("hey there");
|
||||
|
||||
UsartConductor_Run();
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "UsartConfigurator.h"
|
||||
|
||||
AT91S_PIO PioAPeripheral;
|
||||
AT91S_PMC PmcPeripheral;
|
||||
AT91S_USART Usart0Peripheral;
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testConfigureUsartIOShouldConfigureUsartTxPinfForPeripheralIO(void)
|
||||
{
|
||||
AT91C_BASE_PIOA->PIO_ASR = 0;
|
||||
AT91C_BASE_PIOA->PIO_BSR = 0xffffffff;
|
||||
AT91C_BASE_PIOA->PIO_PDR = 0;
|
||||
Usart_ConfigureUsartIO();
|
||||
TEST_ASSERT_EQUAL(USART0_TX_PIN, AT91C_BASE_PIOA->PIO_ASR);
|
||||
TEST_ASSERT_EQUAL(0, AT91C_BASE_PIOA->PIO_BSR);
|
||||
TEST_ASSERT_EQUAL(USART0_TX_PIN, AT91C_BASE_PIOA->PIO_PDR);
|
||||
}
|
||||
|
||||
void testEnablePeripheralClockShouldEnableClockToUsartPeripheral(void)
|
||||
{
|
||||
AT91C_BASE_PMC->PMC_PCER = 0;
|
||||
Usart_EnablePeripheralClock();
|
||||
TEST_ASSERT_EQUAL(((uint32)1) << USART0_CLOCK_ENABLE, AT91C_BASE_PMC->PMC_PCER);
|
||||
}
|
||||
|
||||
void testResetShouldDisableAllUsartInterrupts(void)
|
||||
{
|
||||
AT91C_BASE_US0->US_IDR = 0;
|
||||
Usart_Reset();
|
||||
TEST_ASSERT_EQUAL(0xffffffff, AT91C_BASE_US0->US_IDR);
|
||||
}
|
||||
|
||||
void testResetShouldResetUsartTransmitterAndReceiver(void)
|
||||
{
|
||||
AT91C_BASE_US0->US_CR = 0;
|
||||
Usart_Reset();
|
||||
TEST_ASSERT_EQUAL(AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS, AT91C_BASE_US0->US_CR);
|
||||
}
|
||||
|
||||
void testConfigureModeShouldSetUsartModeToAsynchronous(void)
|
||||
{
|
||||
uint32 asyncMode = (AT91C_US_USMODE_NORMAL |
|
||||
AT91C_US_NBSTOP_1_BIT |
|
||||
AT91C_US_PAR_NONE |
|
||||
AT91C_US_CHRL_8_BITS |
|
||||
AT91C_US_CLKS_CLOCK);
|
||||
|
||||
AT91C_BASE_US0->US_MR = ~asyncMode;
|
||||
Usart_ConfigureMode();
|
||||
TEST_ASSERT_EQUAL(asyncMode, AT91C_BASE_US0->US_MR);
|
||||
}
|
||||
|
||||
void testSetBaudRateRegisterShouldSetUsartBaudRateRegisterToValuePassedAsParameter(void)
|
||||
{
|
||||
AT91C_BASE_US0->US_BRGR = 0;
|
||||
Usart_SetBaudRateRegister(3);
|
||||
TEST_ASSERT_EQUAL(3, AT91C_BASE_US0->US_BRGR);
|
||||
Usart_SetBaudRateRegister(251);
|
||||
TEST_ASSERT_EQUAL(251, AT91C_BASE_US0->US_BRGR);
|
||||
}
|
||||
|
||||
|
||||
void testEnableShouldEnableUsart0Transmitter(void)
|
||||
{
|
||||
AT91C_BASE_US0->US_CR = 0;
|
||||
Usart_Enable();
|
||||
TEST_ASSERT_EQUAL(AT91C_US_TXEN, AT91C_BASE_US0->US_CR);
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "UsartHardware.h"
|
||||
#include "AT91SAM7X256.h"
|
||||
#include "MockUsartConfigurator.h"
|
||||
#include "MockUsartPutChar.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testInitShouldConfigureUsartPeripheralByCallingConfiguratorAppropriately(void)
|
||||
{
|
||||
Usart_ConfigureUsartIO_Expect();
|
||||
Usart_EnablePeripheralClock_Expect();
|
||||
Usart_Reset_Expect();
|
||||
Usart_ConfigureMode_Expect();
|
||||
Usart_SetBaudRateRegister_Expect(73);
|
||||
Usart_Enable_Expect();
|
||||
|
||||
UsartHardware_Init(73);
|
||||
}
|
||||
|
||||
void testTransmitStringShouldSendDesiredStringOutUsingUsart(void)
|
||||
{
|
||||
Usart_PutChar_Expect('h');
|
||||
Usart_PutChar_Expect('e');
|
||||
Usart_PutChar_Expect('l');
|
||||
Usart_PutChar_Expect('l');
|
||||
Usart_PutChar_Expect('o');
|
||||
|
||||
UsartHardware_TransmitString("hello");
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "UsartModel.h"
|
||||
#include "ModelConfig.h"
|
||||
#include "MockTemperatureFilter.h"
|
||||
#include "MockUsartBaudRateRegisterCalculator.h"
|
||||
#include <math.h>
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testGetBaudRateRegisterSettingShouldReturnAppropriateBaudRateRegisterSetting(void)
|
||||
{
|
||||
uint8 dummyRegisterSetting = 17;
|
||||
UsartModel_CalculateBaudRateRegisterSetting_ExpectAndReturn(MASTER_CLOCK, USART0_BAUDRATE, dummyRegisterSetting);
|
||||
|
||||
TEST_ASSERT_EQUAL(dummyRegisterSetting, UsartModel_GetBaudRateRegisterSetting());
|
||||
}
|
||||
|
||||
void testGetFormattedTemperatureFormatsTemperatureFromCalculatorAppropriately(void)
|
||||
{
|
||||
TemperatureFilter_GetTemperatureInCelcius_ExpectAndReturn(25.0f);
|
||||
TEST_ASSERT_EQUAL_STRING("25.0 C\n", UsartModel_GetFormattedTemperature());
|
||||
}
|
||||
|
||||
void testShouldReturnErrorMessageUponInvalidTemperatureValue(void)
|
||||
{
|
||||
TemperatureFilter_GetTemperatureInCelcius_ExpectAndReturn(-INFINITY);
|
||||
TEST_ASSERT_EQUAL_STRING("Temperature sensor failure!\n", UsartModel_GetFormattedTemperature());
|
||||
}
|
||||
|
||||
void testShouldReturnWakeupMessage(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL_STRING("It's Awesome Time!\n", UsartModel_GetWakeupMessage());
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "UsartPutChar.h"
|
||||
#include "MockUsartTransmitBufferStatus.h"
|
||||
|
||||
AT91S_USART Usart0Peripheral;
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testPutCharShouldWriteDesiredCharacterToUsartTransmitBuffer(void)
|
||||
{
|
||||
AT91C_BASE_US0->US_THR = 0;
|
||||
|
||||
Usart_ReadyToTransmit_ExpectAndReturn(TRUE);
|
||||
Usart_PutChar('x');
|
||||
TEST_ASSERT_EQUAL('x', AT91C_BASE_US0->US_THR);
|
||||
|
||||
Usart_ReadyToTransmit_ExpectAndReturn(TRUE);
|
||||
Usart_PutChar('1');
|
||||
TEST_ASSERT_EQUAL('1', AT91C_BASE_US0->US_THR);
|
||||
|
||||
Usart_ReadyToTransmit_ExpectAndReturn(TRUE);
|
||||
Usart_PutChar(':');
|
||||
TEST_ASSERT_EQUAL(':', AT91C_BASE_US0->US_THR);
|
||||
}
|
||||
|
||||
void testPutCharShouldWaitUntilReadyToTransmitBeforeLoadingTransmitBufffer(void)
|
||||
{
|
||||
AT91C_BASE_US0->US_THR = 0;
|
||||
|
||||
Usart_ReadyToTransmit_ExpectAndReturn(FALSE);
|
||||
Usart_ReadyToTransmit_ExpectAndReturn(FALSE);
|
||||
Usart_ReadyToTransmit_ExpectAndReturn(FALSE);
|
||||
Usart_ReadyToTransmit_ExpectAndReturn(TRUE);
|
||||
Usart_PutChar('x');
|
||||
TEST_ASSERT_EQUAL('x', AT91C_BASE_US0->US_THR);
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
#include "unity.h"
|
||||
#include "Types.h"
|
||||
#include "UsartTransmitBufferStatus.h"
|
||||
|
||||
AT91S_USART Usart0Peripheral;
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void testReadyToTransmitShouldReturnStatusPerTransmitBufferReadyStatus(void)
|
||||
{
|
||||
AT91C_BASE_US0->US_CSR = 0;
|
||||
TEST_ASSERT(!Usart_ReadyToTransmit());
|
||||
|
||||
AT91C_BASE_US0->US_CSR = AT91C_US_TXRDY;
|
||||
TEST_ASSERT(Usart_ReadyToTransmit());
|
||||
}
|
||||
@ -0,0 +1,111 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
['../config/production_environment',
|
||||
'cmock_header_parser',
|
||||
'cmock_generator',
|
||||
'cmock_file_writer',
|
||||
'cmock_config',
|
||||
'cmock_plugin_manager',
|
||||
'cmock_generator_utils',
|
||||
'cmock_unityhelper_parser'].each { |req| require "#{__dir__}/#{req}" }
|
||||
|
||||
class CMock
|
||||
def initialize(options = nil)
|
||||
cm_config = CMockConfig.new(options)
|
||||
cm_unityhelper = CMockUnityHelperParser.new(cm_config)
|
||||
cm_writer = CMockFileWriter.new(cm_config)
|
||||
cm_gen_utils = CMockGeneratorUtils.new(cm_config,
|
||||
:unity_helper => cm_unityhelper)
|
||||
cm_gen_plugins = CMockPluginManager.new(cm_config, cm_gen_utils)
|
||||
@cm_parser = CMockHeaderParser.new(cm_config)
|
||||
@cm_generator = CMockGenerator.new(cm_config, cm_writer, cm_gen_utils,
|
||||
cm_gen_plugins)
|
||||
@silent = (cm_config.verbosity < 2)
|
||||
end
|
||||
|
||||
def setup_mocks(files, folder = nil)
|
||||
[files].flatten.each do |src|
|
||||
generate_mock(src, folder)
|
||||
end
|
||||
end
|
||||
|
||||
def setup_skeletons(files)
|
||||
[files].flatten.each do |src|
|
||||
generate_skeleton src
|
||||
end
|
||||
end
|
||||
|
||||
private ###############################
|
||||
|
||||
def generate_mock(src, folder)
|
||||
name = File.basename(src, '.*')
|
||||
ext = File.extname(src)
|
||||
puts "Creating mock for #{name}..." unless @silent
|
||||
@cm_generator.create_mock(name, @cm_parser.parse(name, File.read(src)), ext, folder)
|
||||
end
|
||||
|
||||
def generate_skeleton(src)
|
||||
name = File.basename(src, '.*')
|
||||
puts "Creating skeleton for #{name}..." unless @silent
|
||||
@cm_generator.create_skeleton(name, @cm_parser.parse(name, File.read(src)))
|
||||
end
|
||||
end
|
||||
|
||||
def option_maker(options, key, val)
|
||||
options ||= {}
|
||||
options[key.to_sym] =
|
||||
if val.chr == ':'
|
||||
val[1..-1].to_sym
|
||||
elsif val.include? ';'
|
||||
val.split(';')
|
||||
elsif val == 'true'
|
||||
true
|
||||
elsif val == 'false'
|
||||
false
|
||||
elsif val =~ /^\d+$/
|
||||
val.to_i
|
||||
else
|
||||
val
|
||||
end
|
||||
options
|
||||
end
|
||||
|
||||
# Command Line Support ###############################
|
||||
|
||||
if $0 == __FILE__
|
||||
usage = "usage: ruby #{__FILE__} (-oOptionsFile) File(s)ToMock"
|
||||
|
||||
unless ARGV[0]
|
||||
puts usage
|
||||
exit 1
|
||||
end
|
||||
|
||||
options = {}
|
||||
filelist = []
|
||||
ARGV.each do |arg|
|
||||
if arg =~ /^-o\"?([a-zA-Z0-9@._\\\/:\s]+)\"?/
|
||||
options.merge! CMockConfig.load_config_file_from_yaml(arg.gsub(/^-o/, ''))
|
||||
elsif arg == '--skeleton'
|
||||
options[:skeleton] = true
|
||||
elsif arg =~ /^--strippables=\"?(.*)\"?/
|
||||
# --strippables are dealt with separately since the user is allowed to
|
||||
# enter any valid regular expression as argument
|
||||
options = option_maker(options, 'strippables', Regexp.last_match(1))
|
||||
elsif arg =~ /^--([a-zA-Z0-9._\\\/:\s]+)=\"?([a-zA-Z0-9._\-\\\/:\s\;]*)\"?/x
|
||||
options = option_maker(options, Regexp.last_match(1),
|
||||
Regexp.last_match(2))
|
||||
else
|
||||
filelist << arg
|
||||
end
|
||||
end
|
||||
|
||||
if options[:skeleton]
|
||||
CMock.new(options).setup_skeletons(filelist)
|
||||
else
|
||||
CMock.new(options).setup_mocks(filelist)
|
||||
end
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user