mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
Boolean fields and strict write on Registers/MMIO
This commit is contained in:
parent
f01f42fdd7
commit
4b90cba132
@ -14,6 +14,7 @@
|
||||
#ifndef _BASE__INCLUDE__UTIL__MMIO_H_
|
||||
#define _BASE__INCLUDE__UTIL__MMIO_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/register.h>
|
||||
|
||||
namespace Genode
|
||||
@ -29,13 +30,15 @@ namespace Genode
|
||||
* Write typed 'value' to MMIO base + 'o'
|
||||
*/
|
||||
template <typename _ACCESS_T>
|
||||
inline void _write(off_t const o, _ACCESS_T const value);
|
||||
inline void _write(off_t const o, _ACCESS_T const value) {
|
||||
*(_ACCESS_T volatile *)((addr_t)base + o) = value; }
|
||||
|
||||
/**
|
||||
* Read typed from MMIO base + 'o'
|
||||
*/
|
||||
template <typename _ACCESS_T>
|
||||
inline _ACCESS_T _read(off_t const o) const;
|
||||
inline _ACCESS_T _read(off_t const o) const {
|
||||
return *(_ACCESS_T volatile *)((addr_t)base + o); }
|
||||
|
||||
public:
|
||||
|
||||
@ -44,19 +47,29 @@ namespace Genode
|
||||
/**
|
||||
* An integer like region within a MMIO region.
|
||||
*
|
||||
* \param _OFFSET Offset of the region relative to the
|
||||
* base of the compound MMIO
|
||||
* \param _ACCESS_WIDTH Bit width of the region, for a list of
|
||||
* supported widths see 'Genode::Register'
|
||||
* \param _OFFSET Offset of the region relative to the
|
||||
* base of the compound MMIO
|
||||
* \param _ACCESS_WIDTH Bit width of the region, for a list of
|
||||
* supported widths see 'Genode::Register'
|
||||
* \param _STRICT_WRITE If set to 0, when writing a bitfield, we
|
||||
* read the register value, update the bits
|
||||
* on it, and write it back to the register.
|
||||
* If set to 1 we take an empty register
|
||||
* value instead, apply the bitfield on it,
|
||||
* and write it to the register. This can
|
||||
* be useful if you have registers that have
|
||||
* different means on reads and writes.
|
||||
*
|
||||
* \detail See 'Genode::Register'
|
||||
*/
|
||||
template <off_t _OFFSET, unsigned long _ACCESS_WIDTH>
|
||||
template <off_t _OFFSET, unsigned long _ACCESS_WIDTH,
|
||||
bool _STRICT_WRITE = false>
|
||||
struct Register : public Genode::Register<_ACCESS_WIDTH>
|
||||
{
|
||||
enum {
|
||||
OFFSET = _OFFSET,
|
||||
ACCESS_WIDTH = _ACCESS_WIDTH,
|
||||
STRICT_WRITE = _STRICT_WRITE,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -72,10 +85,8 @@ namespace Genode
|
||||
struct Bitfield :
|
||||
public Genode::Register<ACCESS_WIDTH>::template Bitfield<_SHIFT, _WIDTH>
|
||||
{
|
||||
/**
|
||||
* Back reference to containing register
|
||||
*/
|
||||
typedef Register<OFFSET, ACCESS_WIDTH> Compound_reg;
|
||||
/* Back reference to containing register */
|
||||
typedef Register<OFFSET, ACCESS_WIDTH, STRICT_WRITE> Compound_reg;
|
||||
};
|
||||
};
|
||||
|
||||
@ -89,6 +100,16 @@ namespace Genode
|
||||
* \param _ITEMS How many times the region gets iterated
|
||||
* successive
|
||||
* \param _ITEM_WIDTH Bit width of a region
|
||||
* \param _STRICT_WRITE If set to 0, when writing a bitfield, we
|
||||
* read the register value, update the bits
|
||||
* on it, and write it back to the register.
|
||||
* If set to 1, we take an empty register
|
||||
* value instead, apply the bitfield on it,
|
||||
* and write it to the register. This can
|
||||
* be useful if you have registers that have
|
||||
* different means on reads and writes.
|
||||
* Please note that ACCESS_WIDTH is decisive
|
||||
* for the range of such strictness.
|
||||
*
|
||||
* \detail The array takes all inner structures, wich are covered
|
||||
* by an item width and iterates them successive. Such
|
||||
@ -103,14 +124,18 @@ namespace Genode
|
||||
* effect
|
||||
*/
|
||||
template <off_t _OFFSET, unsigned long _ACCESS_WIDTH,
|
||||
unsigned long _ITEMS, unsigned long _ITEM_WIDTH>
|
||||
struct Register_array : public Register<_OFFSET, _ACCESS_WIDTH>
|
||||
unsigned long _ITEMS, unsigned long _ITEM_WIDTH,
|
||||
bool _STRICT_WRITE = false>
|
||||
|
||||
struct Register_array : public Register<_OFFSET, _ACCESS_WIDTH,
|
||||
_STRICT_WRITE>
|
||||
{
|
||||
typedef
|
||||
typename Trait::Uint_type<_ACCESS_WIDTH>::template Divisor<_ITEM_WIDTH>
|
||||
Item;
|
||||
|
||||
enum {
|
||||
STRICT_WRITE = _STRICT_WRITE,
|
||||
OFFSET = _OFFSET,
|
||||
ACCESS_WIDTH = _ACCESS_WIDTH,
|
||||
ITEMS = _ITEMS,
|
||||
@ -121,7 +146,8 @@ namespace Genode
|
||||
ITEM_MASK = (1 << ITEM_WIDTH) - 1,
|
||||
};
|
||||
|
||||
typedef typename Register<OFFSET, ACCESS_WIDTH>::access_t
|
||||
typedef
|
||||
typename Register<OFFSET, ACCESS_WIDTH, STRICT_WRITE>::access_t
|
||||
access_t;
|
||||
|
||||
/**
|
||||
@ -134,12 +160,11 @@ namespace Genode
|
||||
*/
|
||||
template <unsigned long _SHIFT, unsigned long _SIZE>
|
||||
struct Bitfield :
|
||||
public Register<OFFSET, ACCESS_WIDTH>::template Bitfield<_SHIFT, _SIZE>
|
||||
public Register<OFFSET, ACCESS_WIDTH, STRICT_WRITE>::template Bitfield<_SHIFT, _SIZE>
|
||||
{
|
||||
/**
|
||||
* Back reference to containing register array
|
||||
*/
|
||||
typedef Register_array<OFFSET, ACCESS_WIDTH, ITEMS, ITEM_WIDTH>
|
||||
/* Back reference to containing register array */
|
||||
typedef Register_array<OFFSET, ACCESS_WIDTH, ITEMS,
|
||||
ITEM_WIDTH, STRICT_WRITE>
|
||||
Compound_array;
|
||||
};
|
||||
|
||||
@ -183,19 +208,23 @@ namespace Genode
|
||||
* Typed address of register 'REGISTER'
|
||||
*/
|
||||
template <typename REGISTER>
|
||||
inline typename REGISTER::access_t volatile * typed_addr() const;
|
||||
inline typename REGISTER::access_t volatile * typed_addr() const {
|
||||
return (typename REGISTER::access_t volatile *)
|
||||
base + REGISTER::OFFSET; }
|
||||
|
||||
/**
|
||||
* Read the whole register 'REGISTER'
|
||||
*/
|
||||
template <typename REGISTER>
|
||||
inline typename REGISTER::access_t read() const;
|
||||
inline typename REGISTER::access_t read() const {
|
||||
return _read<typename REGISTER::access_t>(REGISTER::OFFSET); }
|
||||
|
||||
/**
|
||||
* Write 'value' to the register 'REGISTER'
|
||||
*/
|
||||
template <typename REGISTER>
|
||||
inline void write(typename REGISTER::access_t const value);
|
||||
inline void write(typename REGISTER::access_t const value) {
|
||||
_write<typename REGISTER::access_t>(REGISTER::OFFSET, value); }
|
||||
|
||||
|
||||
/******************************************
|
||||
@ -259,46 +288,6 @@ namespace Genode
|
||||
}
|
||||
|
||||
|
||||
template <typename ACCESS_T>
|
||||
void Genode::Mmio::_write(off_t const o, ACCESS_T const value)
|
||||
{
|
||||
*(ACCESS_T volatile *)((addr_t)base + o) = value;
|
||||
}
|
||||
|
||||
|
||||
template <typename ACCESS_T>
|
||||
ACCESS_T Genode::Mmio::_read(off_t const o) const
|
||||
{
|
||||
return *(ACCESS_T volatile *)((addr_t)base + o);
|
||||
}
|
||||
|
||||
|
||||
/*************************
|
||||
** Access to registers **
|
||||
*************************/
|
||||
|
||||
|
||||
template <typename REGISTER>
|
||||
typename REGISTER::access_t volatile * Genode::Mmio::typed_addr() const
|
||||
{
|
||||
return (typename REGISTER::access_t volatile *)base + REGISTER::OFFSET;
|
||||
}
|
||||
|
||||
|
||||
template <typename REGISTER>
|
||||
typename REGISTER::access_t Genode::Mmio::read() const
|
||||
{
|
||||
return _read<typename REGISTER::access_t>(REGISTER::OFFSET);
|
||||
}
|
||||
|
||||
|
||||
template <typename REGISTER>
|
||||
void Genode::Mmio::write(typename REGISTER::access_t const value)
|
||||
{
|
||||
_write<typename REGISTER::access_t>(REGISTER::OFFSET, value);
|
||||
}
|
||||
|
||||
|
||||
/******************************************
|
||||
** Access to bitfields within registers **
|
||||
******************************************/
|
||||
@ -309,7 +298,6 @@ typename BITFIELD::Compound_reg::access_t Genode::Mmio::read() const
|
||||
{
|
||||
typedef typename BITFIELD::Compound_reg Register;
|
||||
typedef typename Register::access_t access_t;
|
||||
|
||||
return BITFIELD::get(_read<access_t>(Register::OFFSET));
|
||||
}
|
||||
|
||||
@ -317,14 +305,22 @@ typename BITFIELD::Compound_reg::access_t Genode::Mmio::read() const
|
||||
template <typename BITFIELD>
|
||||
void Genode::Mmio::write(typename BITFIELD::Compound_reg::access_t const value)
|
||||
{
|
||||
/* Initialize the pattern that is written finally to the register */
|
||||
typedef typename BITFIELD::Compound_reg Register;
|
||||
typedef typename Register::access_t access_t;
|
||||
typename Register::access_t write_value;
|
||||
if (Register::STRICT_WRITE)
|
||||
{
|
||||
/* We must only apply the bitfield to an empty write pattern */
|
||||
write_value = 0;
|
||||
} else {
|
||||
|
||||
access_t new_reg = read<Register>();
|
||||
BITFIELD::clear(new_reg);
|
||||
BITFIELD::set(new_reg, value);
|
||||
|
||||
write<Register>(new_reg);
|
||||
/* We've got to apply the bitfield to the old register value */
|
||||
write_value = read<Register>();
|
||||
BITFIELD::clear(write_value);
|
||||
}
|
||||
/* Apply bitfield value and override register */
|
||||
BITFIELD::set(write_value, value);
|
||||
write<Register>(write_value);
|
||||
}
|
||||
|
||||
|
||||
@ -337,24 +333,18 @@ template <typename REGISTER_ARRAY>
|
||||
typename REGISTER_ARRAY::access_t
|
||||
Genode::Mmio::read(unsigned long const index) const
|
||||
{
|
||||
/**
|
||||
* Handle array overflow
|
||||
*/
|
||||
/* Reads outside the array return 0 */
|
||||
if (index > REGISTER_ARRAY::MAX_INDEX) return 0;
|
||||
|
||||
/* If item width equals access width we optimize the access */
|
||||
off_t offset;
|
||||
|
||||
/**
|
||||
* Optimize access if item width equals access width
|
||||
*/
|
||||
if (REGISTER_ARRAY::ITEM_WIDTH == REGISTER_ARRAY::ACCESS_WIDTH) {
|
||||
|
||||
offset = REGISTER_ARRAY::OFFSET
|
||||
+ (index << REGISTER_ARRAY::ITEM_WIDTH_LOG2);
|
||||
return _read<typename REGISTER_ARRAY::access_t>(offset);
|
||||
|
||||
/* Access width and item width differ */
|
||||
} else {
|
||||
|
||||
long unsigned shift;
|
||||
REGISTER_ARRAY::access_dest(offset, shift, index);
|
||||
return (_read<typename REGISTER_ARRAY::access_t>(offset) >> shift)
|
||||
@ -368,37 +358,36 @@ template <typename REGISTER_ARRAY>
|
||||
void Genode::Mmio::write(typename REGISTER_ARRAY::access_t const value,
|
||||
unsigned long const index)
|
||||
{
|
||||
/**
|
||||
* Avoid array overflow
|
||||
*/
|
||||
/* Writes outside the array are ignored */
|
||||
if (index > REGISTER_ARRAY::MAX_INDEX) return;
|
||||
|
||||
/* If item width equals access width we optimize the access */
|
||||
off_t offset;
|
||||
|
||||
/**
|
||||
* Optimize access if item width equals access width
|
||||
*/
|
||||
if (REGISTER_ARRAY::ITEM_WIDTH == REGISTER_ARRAY::ACCESS_WIDTH) {
|
||||
|
||||
offset = REGISTER_ARRAY::OFFSET
|
||||
+ (index << REGISTER_ARRAY::ITEM_WIDTH_LOG2);
|
||||
_write<typename REGISTER_ARRAY::access_t>(offset, value);
|
||||
|
||||
/* Access width and item width differ */
|
||||
} else {
|
||||
|
||||
long unsigned shift;
|
||||
REGISTER_ARRAY::access_dest(offset, shift, index);
|
||||
|
||||
/**
|
||||
* Insert new value into old register value
|
||||
*/
|
||||
typename REGISTER_ARRAY::access_t new_reg =
|
||||
_read<typename REGISTER_ARRAY::access_t>(offset);
|
||||
/* Insert new value into old register value */
|
||||
typename REGISTER_ARRAY::access_t write_value;
|
||||
if (REGISTER_ARRAY::STRICT_WRITE)
|
||||
{
|
||||
/* We must only apply the bitfield to an empty write pattern */
|
||||
write_value = 0;
|
||||
} else {
|
||||
|
||||
new_reg &= ~(REGISTER_ARRAY::ITEM_MASK << shift);
|
||||
new_reg |= (value & REGISTER_ARRAY::ITEM_MASK) << shift;
|
||||
|
||||
_write<typename REGISTER_ARRAY::access_t>(offset, new_reg);
|
||||
/* We've got to apply the bitfield to the old register value */
|
||||
write_value = _read<typename REGISTER_ARRAY::access_t>(offset);
|
||||
write_value &= ~(REGISTER_ARRAY::ITEM_MASK << shift);
|
||||
}
|
||||
/* Apply bitfield value and override register */
|
||||
write_value |= (value & REGISTER_ARRAY::ITEM_MASK) << shift;
|
||||
_write<typename REGISTER_ARRAY::access_t>(offset, write_value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -413,13 +402,22 @@ void
|
||||
Genode::Mmio::write(typename ARRAY_BITFIELD::Compound_array::access_t const value,
|
||||
long unsigned const index)
|
||||
{
|
||||
/* Initialize the pattern that is finally written to the register */
|
||||
typedef typename ARRAY_BITFIELD::Compound_array Register_array;
|
||||
typename Register_array::access_t write_value;
|
||||
if (Register_array::STRICT_WRITE)
|
||||
{
|
||||
/* We must only apply the bitfield to an empty write pattern */
|
||||
write_value = 0;
|
||||
} else {
|
||||
|
||||
typename Register_array::access_t new_reg = read<Register_array>(index);
|
||||
ARRAY_BITFIELD::clear(new_reg);
|
||||
ARRAY_BITFIELD::set(new_reg, value);
|
||||
|
||||
write<Register_array>(new_reg, index);
|
||||
/* We've got to apply the bitfield to the old register value */
|
||||
write_value = read<Register_array>(index);
|
||||
ARRAY_BITFIELD::clear(write_value);
|
||||
}
|
||||
/* Apply bitfield value and override register */
|
||||
ARRAY_BITFIELD::set(write_value, value);
|
||||
write<Register_array>(write_value, index);
|
||||
}
|
||||
|
||||
|
||||
@ -429,7 +427,6 @@ Genode::Mmio::read(long unsigned const index) const
|
||||
{
|
||||
typedef typename ARRAY_BITFIELD::Compound_array Array;
|
||||
typedef typename Array::access_t access_t;
|
||||
|
||||
return ARRAY_BITFIELD::get(read<Array>(index));
|
||||
}
|
||||
|
||||
|
@ -30,10 +30,10 @@ namespace Genode
|
||||
** base of 2 for all supported widths in 'Uint_type' **
|
||||
***************************************************************/
|
||||
|
||||
template <> struct Uint_type<8>
|
||||
template <> struct Uint_type<1>
|
||||
{
|
||||
typedef uint8_t Type;
|
||||
enum { WIDTH_LOG2 = 3 };
|
||||
typedef bool Type;
|
||||
enum { WIDTH_LOG2 = 0 };
|
||||
|
||||
/**
|
||||
* Access widths, wich are dividers to the compound type width
|
||||
@ -41,6 +41,12 @@ namespace Genode
|
||||
template <unsigned long _DIVISOR_WIDTH> struct Divisor;
|
||||
};
|
||||
|
||||
template <> struct Uint_type<8> : Uint_type<1>
|
||||
{
|
||||
typedef uint8_t Type;
|
||||
enum { WIDTH_LOG2 = 3 };
|
||||
};
|
||||
|
||||
template <> struct Uint_type<16> : Uint_type<8>
|
||||
{
|
||||
typedef uint16_t Type;
|
||||
@ -65,7 +71,7 @@ namespace Genode
|
||||
** access widths in 'Uint_type::Divisor' **
|
||||
********************************************************************/
|
||||
|
||||
template <> struct Uint_type<8>::Divisor<1> { enum { WIDTH_LOG2 = 0 }; };
|
||||
template <> struct Uint_type<1>::Divisor<1> { enum { WIDTH_LOG2 = 0 }; };
|
||||
template <> struct Uint_type<8>::Divisor<2> { enum { WIDTH_LOG2 = 1 }; };
|
||||
template <> struct Uint_type<8>::Divisor<4> { enum { WIDTH_LOG2 = 2 }; };
|
||||
template <> struct Uint_type<8>::Divisor<8> { enum { WIDTH_LOG2 = 3 }; };
|
||||
@ -137,6 +143,14 @@ namespace Genode
|
||||
static inline access_t bits(access_t const value) {
|
||||
return (value & MASK) << SHIFT; }
|
||||
|
||||
/**
|
||||
* Get a register value 'reg' masked according to this bitfield
|
||||
*
|
||||
* \detail E.g. '0x1234' masked according to a
|
||||
* 'Register<16>::Bitfield<5,7>' returns '0x0220'
|
||||
*/
|
||||
static inline access_t masked(access_t const reg) { return reg & REG_MASK; }
|
||||
|
||||
/**
|
||||
* Get value of this bitfield from 'reg'
|
||||
*/
|
||||
|
@ -1,17 +1,17 @@
|
||||
/*
|
||||
* \brief Basic test for MMIO access framework
|
||||
* \author Christian Helmuth
|
||||
* \brief Diversified test of the Register and MMIO framework
|
||||
* \author Martin Stein
|
||||
* \date 2012-01-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Genode Labs GmbH
|
||||
* Copyright (C) 2012 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/mmio.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
@ -26,7 +26,7 @@ static uint16_t cpu_state;
|
||||
* Assume this is a MMIO region
|
||||
*/
|
||||
enum{ MMIO_SIZE = 8 };
|
||||
static uint8_t mmio_mem[MMIO_SIZE];
|
||||
static uint8_t mmio_mem[MMIO_SIZE];
|
||||
|
||||
/**
|
||||
* Exemplary highly structured type for accessing 'cpu_state'
|
||||
@ -68,11 +68,11 @@ struct Test_mmio : public Mmio
|
||||
Test_mmio(addr_t const base) : Mmio(base) { }
|
||||
|
||||
struct Reg : Register<0x04, 8>
|
||||
{
|
||||
{
|
||||
struct Bit_1 : Bitfield<0,1> { };
|
||||
struct Area : Bitfield<1,3>
|
||||
{
|
||||
enum {
|
||||
enum {
|
||||
VALUE_1 = 3,
|
||||
VALUE_2 = 4,
|
||||
VALUE_3 = 5,
|
||||
@ -91,16 +91,28 @@ struct Test_mmio : public Mmio
|
||||
struct C : Bitfield<3,1> { };
|
||||
struct D : Bitfield<1,3> { };
|
||||
};
|
||||
|
||||
struct Strict_array : Register_array<0x0, 16, 10, 4, true>
|
||||
{
|
||||
struct A : Bitfield<1,1> { };
|
||||
struct B : Bitfield<2,4> { };
|
||||
};
|
||||
|
||||
struct Strict_reg : Register<0x0, 32, true>
|
||||
{
|
||||
struct A : Bitfield<3,2> { };
|
||||
struct B : Bitfield<30,4> { };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Print out memory content hexadecimal
|
||||
*/
|
||||
void dump_mem(uint8_t * base, size_t size)
|
||||
void dump_mem(uint8_t * base, size_t size)
|
||||
{
|
||||
addr_t top = (addr_t)base + size;
|
||||
for(; (addr_t)base < top;) {
|
||||
for(; (addr_t)base < top;) {
|
||||
printf("%2X ", *(uint8_t *)base);
|
||||
base = (uint8_t *)((addr_t)base + sizeof(uint8_t));
|
||||
}
|
||||
@ -110,10 +122,10 @@ void dump_mem(uint8_t * base, size_t size)
|
||||
/**
|
||||
* Zero-fill memory region
|
||||
*/
|
||||
void zero_mem(uint8_t * base, size_t size)
|
||||
void zero_mem(uint8_t * base, size_t size)
|
||||
{
|
||||
addr_t top = (addr_t)base + size;
|
||||
for(; (addr_t)base < top;) {
|
||||
for(; (addr_t)base < top;) {
|
||||
*base = 0;
|
||||
base = (uint8_t *)((addr_t)base + sizeof(uint8_t));
|
||||
}
|
||||
@ -180,7 +192,7 @@ int main()
|
||||
|
||||
static uint8_t mmio_cmpr_2[MMIO_SIZE] = {0,0,0,0,0b00000001,0,0,0};
|
||||
if (compare_mem(mmio_mem, mmio_cmpr_2, sizeof(mmio_mem)) ||
|
||||
mmio.read<Test_mmio::Reg::Bit_1>() != 1)
|
||||
mmio.read<Test_mmio::Reg::Bit_1>() != 1)
|
||||
{ return test_failed(2); }
|
||||
|
||||
/**
|
||||
@ -190,7 +202,7 @@ int main()
|
||||
|
||||
static uint8_t mmio_cmpr_3[MMIO_SIZE] = {0,0,0,0,0b00010001,0,0,0};
|
||||
if (compare_mem(mmio_mem, mmio_cmpr_3, sizeof(mmio_mem)) ||
|
||||
mmio.read<Test_mmio::Reg::Bit_2>() != 1)
|
||||
mmio.read<Test_mmio::Reg::Bit_2>() != 1)
|
||||
{ return test_failed(3); }
|
||||
|
||||
/**
|
||||
@ -291,7 +303,7 @@ int main()
|
||||
******************************************/
|
||||
|
||||
/**
|
||||
* Test 11, read/write register array items with array- and item overflows
|
||||
* Test 11, read/write register array items with array- and item overflows
|
||||
*/
|
||||
zero_mem(mmio_mem, sizeof(mmio_mem));
|
||||
mmio.write<Test_mmio::Array>(0xa, 0);
|
||||
@ -339,6 +351,42 @@ int main()
|
||||
mmio.read<Test_mmio::Array::A>(11) != 0 )
|
||||
{ return test_failed(12); }
|
||||
|
||||
/**
|
||||
* Test 13, writing to registers with 'STRICT_WRITE' set
|
||||
*/
|
||||
zero_mem(mmio_mem, sizeof(mmio_mem));
|
||||
*(uint8_t*)((addr_t)mmio_mem + sizeof(uint32_t)) = 0xaa;
|
||||
mmio.write<Test_mmio::Strict_reg::A>(0xff);
|
||||
mmio.write<Test_mmio::Strict_reg::B>(0xff);
|
||||
static uint8_t mmio_cmpr_13[MMIO_SIZE] = {0,0,0,0b11000000,0b10101010,0,0,0};
|
||||
if (compare_mem(mmio_mem, mmio_cmpr_13, sizeof(mmio_mem))) {
|
||||
return test_failed(13); }
|
||||
|
||||
/**
|
||||
* Test 14, writing to register array items with 'STRICT_WRITE' set
|
||||
*/
|
||||
zero_mem(mmio_mem, sizeof(mmio_mem));
|
||||
*(uint8_t*)((addr_t)mmio_mem + sizeof(uint16_t)) = 0xaa;
|
||||
mmio.write<Test_mmio::Strict_array>(0b1010, 0);
|
||||
mmio.write<Test_mmio::Strict_array>(0b1010, 1);
|
||||
mmio.write<Test_mmio::Strict_array>(0b1010, 2);
|
||||
mmio.write<Test_mmio::Strict_array>(0b1100, 3);
|
||||
mmio.write<Test_mmio::Strict_array>(0b110011, 3);
|
||||
static uint8_t mmio_cmpr_14[MMIO_SIZE] = {0,0b00110000,0b10101010,0,0,0,0,0};
|
||||
if (compare_mem(mmio_mem, mmio_cmpr_14, sizeof(mmio_mem))) {
|
||||
return test_failed(14); }
|
||||
|
||||
/**
|
||||
* Test 15, writing to register array bitfields with 'STRICT_WRITE' set
|
||||
*/
|
||||
zero_mem(mmio_mem, sizeof(mmio_mem));
|
||||
*(uint8_t*)((addr_t)mmio_mem + sizeof(uint16_t)) = 0xaa;
|
||||
mmio.write<Test_mmio::Strict_array::A>(0xff, 3);
|
||||
mmio.write<Test_mmio::Strict_array::B>(0xff, 3);
|
||||
static uint8_t mmio_cmpr_15[MMIO_SIZE] = {0,0b11000000,0b10101010,0,0,0,0,0};
|
||||
if (compare_mem(mmio_mem, mmio_cmpr_15, sizeof(mmio_mem))) {
|
||||
return test_failed(15); }
|
||||
|
||||
printf("Test ended successfully\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,4 +1,14 @@
|
||||
TARGET = test-util_mmio
|
||||
SRC_CC = main.cc
|
||||
#
|
||||
# \brief Diversified test of the Register and MMIO framework
|
||||
# \author Martin Stein
|
||||
# \date 2012-04-25
|
||||
#
|
||||
|
||||
LIBS = cxx env
|
||||
# Set program name
|
||||
TARGET = test-util_mmio
|
||||
|
||||
# Add C++ sources
|
||||
SRC_CC += main.cc
|
||||
|
||||
# Add libraries
|
||||
LIBS += cxx env thread
|
||||
|
Loading…
Reference in New Issue
Block a user