Initial commit
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
<buildSystem id="preference.org.eclipse.cdt.managedbuilder.core.configurationDataProvider.1578931625">
|
||||
<storageModule id="preference.org.eclipse.cdt.managedbuilder.core.configurationDataProvider.1578931625" moduleId="org.eclipse.cdt.core.settings"/>
|
||||
</buildSystem>
|
||||
<cconfiguration id="preference.org.eclipse.cdt.managedbuilder.core.configurationDataProvider.1578931625">
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration buildProperties="" description="" id="preference.org.eclipse.cdt.managedbuilder.core.configurationDataProvider.1578931625" name="Nios II" parent="org.eclipse.cdt.build.core.prefbase.cfg">
|
||||
<folderInfo id="preference.org.eclipse.cdt.managedbuilder.core.configurationDataProvider.1578931625." name="/" resourcePath="">
|
||||
<toolChain id="altera.nios2.linux.gcc4.1436420066" name="Linux Nios II GCC4" superClass="altera.nios2.linux.gcc4">
|
||||
<targetPlatform id="altera.nios2.linux.gcc4.1506303804" name="Nios II" osList="linux" superClass="altera.nios2.linux.gcc4"/>
|
||||
<builder buildPath="${workspace_loc://signal_processing}" id="altera.tool.gnu.builder.1107813232" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="altera.tool.gnu.builder"/>
|
||||
<tool id="altera.tool.gnu.c.compiler.1149346695" name="Nios II GCC C Compiler" superClass="altera.tool.gnu.c.compiler">
|
||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1301990062" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
||||
</tool>
|
||||
<tool id="altera.tool.gnu.cpp.compiler.423409496" name="Nios II GCC C++ Compiler" superClass="altera.tool.gnu.cpp.compiler">
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1863230573" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
|
||||
</tool>
|
||||
<tool id="altera.tool.gnu.archiver.1974628331" name="Nios II GCC Archiver" superClass="altera.tool.gnu.archiver"/>
|
||||
<tool id="altera.tool.gnu.c.linker.164791439" name="Nios II GCC C Linker" superClass="altera.tool.gnu.c.linker"/>
|
||||
<tool id="altera.tool.gnu.cpp.linker.425602587" name="Nios II GCC C++ Linker" superClass="altera.tool.gnu.cpp.linker">
|
||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.947771420" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
|
||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
||||
</inputType>
|
||||
</tool>
|
||||
<tool id="altera.tool.gnu.assembler.1629937142" name="Nios II GCC Assembler" superClass="altera.tool.gnu.assembler">
|
||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1175573843" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="preference.org.eclipse.cdt.managedbuilder.core.configurationDataProvider.1578931625" moduleId="org.eclipse.cdt.core.settings" name="Nios II">
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<project id="signal_processing.null.700250918" name="signal_processing"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<scannerConfigBuildInfo instanceId="preference.org.eclipse.cdt.managedbuilder.core.configurationDataProvider.1578931625;preference.org.eclipse.cdt.managedbuilder.core.configurationDataProvider.1578931625.;altera.tool.gnu.c.compiler.1149346695;cdt.managedbuild.tool.gnu.c.compiler.input.1301990062">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="preference.org.eclipse.cdt.managedbuilder.core.configurationDataProvider.1578931625;preference.org.eclipse.cdt.managedbuilder.core.configurationDataProvider.1578931625.;altera.tool.gnu.cpp.compiler.423409496;cdt.managedbuild.tool.gnu.cpp.compiler.input.1863230573">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
|
||||
<buildTargets>
|
||||
<target name="mem_init_install" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>mem_init_install</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
<runAllBuilders>false</runAllBuilders>
|
||||
</target>
|
||||
<target name="mem_init_generate" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>mem_init_generate</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
<runAllBuilders>false</runAllBuilders>
|
||||
</target>
|
||||
<target name="help" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>help</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
<runAllBuilders>false</runAllBuilders>
|
||||
</target>
|
||||
</buildTargets>
|
||||
</storageModule>
|
||||
</cproject>
|
||||
@@ -0,0 +1,7 @@
|
||||
.settings/
|
||||
obj/
|
||||
readme.txt
|
||||
signal_processing.elf
|
||||
signal_processing.map
|
||||
signal_processing.objdump
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>signal_processing</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.altera.sbtgui.project.makefileBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.altera.sbtgui.project.makefileBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
<nature>org.eclipse.cdt.core.ccnature</nature>
|
||||
<nature>com.altera.sbtgui.project.SBTGUINature</nature>
|
||||
<nature>com.altera.sbtgui.project.SBTGUIAppNature</nature>
|
||||
<nature>com.altera.sbtgui.project.SBTGUIManagedNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
#include "system/task_add.h"
|
||||
#include "system/data_channel.h"
|
||||
#include "system/float_word.h"
|
||||
|
||||
int task_add_run( void * task ) {
|
||||
|
||||
// TODO
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "system/task_crc.h"
|
||||
#include "system/data_channel.h"
|
||||
#include "system/float_word.h"
|
||||
|
||||
int task_crc_run( void * task ) {
|
||||
|
||||
// TODO
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "system/task_fft.h"
|
||||
#include "system/data_channel.h"
|
||||
#include "system/Complex.h"
|
||||
#include "system/float_word.h"
|
||||
|
||||
int task_fft_run( void * task ) {
|
||||
|
||||
// TODO
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#include <stdio.h>
|
||||
#include <system.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "system/binding.h"
|
||||
#include "system/signal_processing.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
uint32_t bindings[ TASK_COUNT ] = {
|
||||
BINDING_SW,
|
||||
BINDING_SW,
|
||||
BINDING_SW,
|
||||
BINDING_SW,
|
||||
BINDING_HW,
|
||||
BINDING_SW,
|
||||
BINDING_SW
|
||||
};
|
||||
|
||||
SignalProcessing system;
|
||||
signal_processing_init( & system, bindings );
|
||||
signal_processing_run( & system );
|
||||
signal_processing_print_results( & system );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "system/task_rand.h"
|
||||
#include "system/hardware_task.h"
|
||||
#include "system/data_channel.h"
|
||||
#include "system/float_word.h"
|
||||
|
||||
int task_rand_run( void * task ) {
|
||||
|
||||
// TODO
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "system/task_sine.h"
|
||||
#include "system/data_channel.h"
|
||||
#include "system/float_word.h"
|
||||
|
||||
int task_sine_run( void * data ) {
|
||||
|
||||
// TODO
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#include "Complex.h"
|
||||
#include <math.h>
|
||||
|
||||
float complex_abs( const Complex * c ) {
|
||||
return sqrt( pow( c->re, 2 ) + pow( c->im, 2 ) );
|
||||
}
|
||||
|
||||
float complex_arg( const Complex * a )
|
||||
{
|
||||
return atan2( a->im, a->re );
|
||||
}
|
||||
|
||||
Complex complex_comjunction( const Complex * a ) {
|
||||
Complex c = { a->re, - a->im };
|
||||
return c;
|
||||
}
|
||||
|
||||
float complex_phi( const Complex * c ) {
|
||||
float phi = 0.0;
|
||||
|
||||
// quadrant I
|
||||
if ( c->re >= 0 && c->im >= 0 ) phi = atan( c->im / c->re );
|
||||
// quadrant II, III
|
||||
if ( c->re < 0 ) phi = atan( c->im / c->re ) + M_PI;
|
||||
// quadrant IV
|
||||
if ( c->re > 0 && c->im < 0 ) phi = atan( c->im / c->re ) + 2 * M_PI;
|
||||
|
||||
return phi * 180.0 / M_PI;
|
||||
}
|
||||
|
||||
Complex complex_scalar_mul( const Complex * a, const float b ) {
|
||||
Complex c = { 0.0, 0.0 };
|
||||
float o_re = b;
|
||||
float o_im = 0.0;
|
||||
|
||||
c.re = a->re * o_re - a->im * o_im;
|
||||
c.im = a->re * o_im + o_re * a->im;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Complex complex_mul( const Complex * a, const Complex * b ) {
|
||||
Complex c = { 0.0, 0.0 };
|
||||
float o_re = b->re;
|
||||
float o_im = b->im;
|
||||
|
||||
c.re = a->re * o_re - a->im * o_im;
|
||||
c.im = a->re * o_im + o_re * a->im;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Complex complex_add( const Complex * a, const Complex * b ) {
|
||||
Complex c = { 0.0, 0.0 };
|
||||
c.re = a->re + b->re;
|
||||
c.im = a->im + b->im;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Complex complex_sub( const Complex * a, const Complex * b ) {
|
||||
Complex c = { 0.0, 0.0 };
|
||||
c.re = a->re - b->re;
|
||||
c.im = a->im - b->im;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Complex complex_polar( float roh, float theta )
|
||||
{
|
||||
Complex c = { roh * cos( theta ), roh * sin( theta ) };
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
Complex complex_pow( const Complex * a, int n )
|
||||
{
|
||||
float roh = pow( complex_abs( a ), n );
|
||||
float theta = complex_arg( a );
|
||||
|
||||
return complex_polar( roh, ( float )( n ) * theta );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
float re;
|
||||
float im;
|
||||
} Complex;
|
||||
|
||||
float complex_abs( const Complex * c );
|
||||
|
||||
float complex_arg( const Complex * a );
|
||||
|
||||
Complex complex_comjunction( const Complex * a );
|
||||
|
||||
float complex_phi( const Complex * c );
|
||||
|
||||
Complex complex_scalar_mul( const Complex * a, const float b );
|
||||
|
||||
Complex complex_mul( const Complex * a, const Complex * b );
|
||||
|
||||
Complex complex_add( const Complex * a, const Complex * b );
|
||||
|
||||
Complex complex_sub( const Complex * a, const Complex * b );
|
||||
|
||||
Complex complex_polar( float roh, float theta );
|
||||
|
||||
Complex complex_pow( const Complex * a, int n );
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "task_base_config.h"
|
||||
|
||||
typedef task_base_config add_config;
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "binding.h"
|
||||
#include "signal_processing.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static const char * BINDING_HW_STRING = "HW";
|
||||
static const char * BINDING_SW_STRING = "SW";
|
||||
static const char * UNKOWN_STRING = "UNKOWN_STRING";
|
||||
|
||||
void binding_from_value( uint32_t value, uint32_t * binding ) {
|
||||
for ( uint32_t i = 0; i < TASK_COUNT; ++i ) {
|
||||
binding[ i ] = value & 1;
|
||||
value >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
int binding_get_channel_binding( const uint32_t * connections,
|
||||
const uint32_t * binding,
|
||||
uint32_t n,
|
||||
DataChannelBinding * channel_binding ) {
|
||||
|
||||
if ( n >= CHANNEL_COUNT ) {
|
||||
printf( "ERROR in %s: %" PRIu32 " not a valid channel number\n",
|
||||
__func__, n );
|
||||
return 1;
|
||||
}
|
||||
|
||||
channel_binding->sink = binding[ n ];
|
||||
channel_binding->source = binding[ connections[ n ] ];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char * binding_to_string( uint32_t binding ) {
|
||||
switch ( binding ) {
|
||||
case BINDING_SW: return BINDING_SW_STRING;
|
||||
case BINDING_HW: return BINDING_HW_STRING;
|
||||
}
|
||||
|
||||
return UNKOWN_STRING;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
enum {
|
||||
BINDING_SW = 0,
|
||||
BINDING_HW = 1
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t sink;
|
||||
uint32_t source;
|
||||
} DataChannelBinding;
|
||||
|
||||
void binding_from_value( uint32_t value, uint32_t * config );
|
||||
|
||||
int binding_get_channel_binding( const uint32_t * connections,
|
||||
const uint32_t * binding,
|
||||
uint32_t n,
|
||||
DataChannelBinding * channel_binding );
|
||||
|
||||
const char * binding_to_string( uint32_t binding );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "task_base_config.h"
|
||||
|
||||
typedef struct {
|
||||
task_base_config base;
|
||||
uint32_t start;
|
||||
} crc_config;
|
||||
@@ -0,0 +1,99 @@
|
||||
#include "data_channel.h"
|
||||
|
||||
#include <system.h>
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
|
||||
const uint32_t DATA_CHANNEL_DEPTH = 1024;
|
||||
const uint32_t DATA_CHANNEL_COUNT = 7;
|
||||
|
||||
const uint32_t DATA_CHANNEL_BASE_LIST[] = {
|
||||
DATA_CHANNEL_0_BASE,
|
||||
DATA_CHANNEL_1_BASE,
|
||||
DATA_CHANNEL_2_BASE,
|
||||
DATA_CHANNEL_3_BASE,
|
||||
DATA_CHANNEL_4_BASE,
|
||||
DATA_CHANNEL_5_BASE,
|
||||
DATA_CHANNEL_6_BASE
|
||||
};
|
||||
|
||||
#define REG_BINDING_OFFSET 0
|
||||
#define BINDING_SINK_POS 0
|
||||
#define BINDING_SOURCE_POS 1
|
||||
|
||||
#define REG_EMPTY_OFFSET 1
|
||||
#define REG_FULL_OFFSET 2
|
||||
#define REG_LEVEL_OFFSET 3
|
||||
#define REG_SINK_OFFSET 4
|
||||
#define REG_SOURCE_OFFSET 5
|
||||
#define REG_CLEAR_OFFSET 6
|
||||
|
||||
void data_channel_bind( uint32_t base, const DataChannelBinding * binding ) {
|
||||
|
||||
uint32_t value = binding->sink << BINDING_SINK_POS |
|
||||
binding->source << BINDING_SOURCE_POS;
|
||||
|
||||
IOWR( base, REG_BINDING_OFFSET, value );
|
||||
}
|
||||
|
||||
uint32_t data_channel_get_binding( uint32_t base ) {
|
||||
return IORD( base, REG_BINDING_OFFSET );
|
||||
}
|
||||
|
||||
uint32_t data_channel_is_empty( uint32_t base ) {
|
||||
return IORD( base, REG_EMPTY_OFFSET );
|
||||
}
|
||||
|
||||
uint32_t data_channel_is_full( uint32_t base ) {
|
||||
return IORD( base, REG_FULL_OFFSET );
|
||||
}
|
||||
|
||||
uint32_t data_channel_level( uint32_t base ) {
|
||||
return IORD( base, REG_LEVEL_OFFSET );
|
||||
}
|
||||
|
||||
void data_channel_clear( uint32_t base ) {
|
||||
IOWR( base, REG_CLEAR_OFFSET, 1 );
|
||||
}
|
||||
|
||||
int data_channel_write( uint32_t base, uint32_t value ) {
|
||||
if ( data_channel_is_full( base ) ) {
|
||||
return 1;
|
||||
}
|
||||
IOWR( base, REG_SINK_OFFSET, value );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int data_channel_write_all( uint32_t base, const uint32_t * data, uint32_t len ) {
|
||||
for ( uint32_t i = 0; i < len; ++i ) {
|
||||
int ret = data_channel_write( base, data[ i ] );
|
||||
if ( ret ) return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int data_channel_read( uint32_t base, uint32_t * value ) {
|
||||
if ( data_channel_is_empty( base ) ) {
|
||||
return 1;
|
||||
}
|
||||
* value = IORD( base, REG_SOURCE_OFFSET );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int data_channel_read_all( uint32_t base, void * buffer ) {
|
||||
int i;
|
||||
for ( i = 0; i < DATA_CHANNEL_DEPTH; ++i ) {
|
||||
int ret = data_channel_read( base, buffer + i );
|
||||
if ( ret ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
uint32_t data_channel_base_from_number( uint32_t channel ) {
|
||||
return DATA_CHANNEL_BASE_LIST[ channel ];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "binding.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const uint32_t DATA_CHANNEL_DEPTH;
|
||||
extern const uint32_t DATA_CHANNEL_COUNT;
|
||||
extern const uint32_t DATA_CHANNEL_BASE_LIST[];
|
||||
|
||||
void data_channel_bind( uint32_t base, const DataChannelBinding * binding );
|
||||
|
||||
uint32_t data_channel_get_binding( uint32_t base );
|
||||
|
||||
uint32_t data_channel_is_empty( uint32_t base );
|
||||
uint32_t data_channel_is_full( uint32_t base );
|
||||
uint32_t data_channel_level( uint32_t base );
|
||||
|
||||
void data_channel_clear( uint32_t base );
|
||||
|
||||
int data_channel_write( uint32_t base, uint32_t value );
|
||||
int data_channel_write_all( uint32_t base, const uint32_t * data, uint32_t len );
|
||||
int data_channel_read( uint32_t base, uint32_t * value );
|
||||
int data_channel_read_all( uint32_t base, void * buffer );
|
||||
|
||||
uint32_t data_channel_base_from_number( uint32_t channel );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "task_base_config.h"
|
||||
|
||||
typedef struct {
|
||||
task_base_config base;
|
||||
float interval;
|
||||
} fft_config;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef union {
|
||||
float value;
|
||||
uint32_t word;
|
||||
} float_word;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "hardware_task.h"
|
||||
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#define REG_START_OFFSET 0
|
||||
#define START 1
|
||||
|
||||
#define REG_STATE_OFFSET 1
|
||||
#define REG_CYCLE_COUNT_OFFSET 2
|
||||
#define REG_CONFIG_OFFSET 3
|
||||
|
||||
void hardware_task_start( uint32_t base ) {
|
||||
IOWR( base, REG_START_OFFSET, START );
|
||||
}
|
||||
|
||||
uint32_t hardware_task_get_state( uint32_t base ) {
|
||||
return IORD( base, REG_STATE_OFFSET );
|
||||
}
|
||||
|
||||
uint32_t hardware_task_get_cycle_count( uint32_t base ) {
|
||||
return IORD( base, REG_CYCLE_COUNT_OFFSET );
|
||||
}
|
||||
|
||||
void hardware_task_set_config( uint32_t base, uint32_t offset, uint32_t value ) {
|
||||
IOWR( base, REG_CONFIG_OFFSET + offset, value );
|
||||
}
|
||||
uint32_t hardware_task_get_config( uint32_t base, uint32_t offset ) {
|
||||
return IORD( base, REG_CONFIG_OFFSET + offset );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
enum {
|
||||
HARDWARE_TASK_IDLE = 0,
|
||||
HARDWARE_TASK_RUNNING = 1,
|
||||
HARDWARE_TASK_DONE = 2
|
||||
};
|
||||
|
||||
void hardware_task_start( uint32_t base );
|
||||
|
||||
uint32_t hardware_task_get_state( uint32_t base );
|
||||
|
||||
uint32_t hardware_task_get_cycle_count( uint32_t base );
|
||||
|
||||
void hardware_task_set_config( uint32_t base, uint32_t offset, uint32_t value );
|
||||
uint32_t hardware_task_get_config( uint32_t base, uint32_t offset );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "hardware_timestamp.h"
|
||||
|
||||
#include <io.h>
|
||||
|
||||
#define REG_STATE_OFFSET 0
|
||||
#define STOPPED 0
|
||||
#define RUNNING 1
|
||||
|
||||
#define REG_CYCLE_COUNT_OFFSET 1
|
||||
|
||||
uint32_t hardware_timestamp_is_running( uint32_t base ) {
|
||||
return IORD( base, REG_STATE_OFFSET ) == RUNNING;
|
||||
}
|
||||
|
||||
uint32_t hardware_timestamp_is_stopped( uint32_t base ) {
|
||||
return IORD( base, REG_STATE_OFFSET ) == STOPPED;
|
||||
}
|
||||
|
||||
uint32_t hardware_timestamp( uint32_t base ) {
|
||||
return IORD( base, REG_CYCLE_COUNT_OFFSET );
|
||||
}
|
||||
|
||||
void hardware_timestamp_start( uint32_t base ) {
|
||||
IOWR( base, REG_STATE_OFFSET, RUNNING );
|
||||
}
|
||||
|
||||
void hardware_timestamp_stop( uint32_t base ) {
|
||||
IOWR( base, REG_STATE_OFFSET, STOPPED );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
uint32_t hardware_timestamp_is_running( uint32_t base );
|
||||
uint32_t hardware_timestamp_is_stopped( uint32_t base );
|
||||
uint32_t hardware_timestamp( uint32_t base );
|
||||
|
||||
void hardware_timestamp_start( uint32_t base );
|
||||
void hardware_timestamp_stop( uint32_t base );
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "task_base_config.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef struct {
|
||||
task_base_config base;
|
||||
float seed;
|
||||
float abs_min;
|
||||
float abs_max;
|
||||
} rand_config;
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#include "signal_processing.h"
|
||||
|
||||
#include "task.h"
|
||||
#include "task_sine.h"
|
||||
#include "task_cosinus.h"
|
||||
#include "task_rand.h"
|
||||
#include "task_add.h"
|
||||
#include "task_sub.h"
|
||||
#include "task_fft.h"
|
||||
#include "task_crc.h"
|
||||
#include "binding.h"
|
||||
#include "data_channel.h"
|
||||
|
||||
#include <system.h>
|
||||
#include <stdio.h>
|
||||
|
||||
const uint32_t TASK_CONNECTIONS[ TASK_COUNT ] = { 3, 3, 4, 4, 5, 6, 7 };
|
||||
|
||||
void * TASK_LIST [ TASK_COUNT ] = {
|
||||
& SINE_CONFIG,
|
||||
& COSINE_CONFIG,
|
||||
& RAND_CONFIG,
|
||||
& ADD_SINE_COSINE_CONFIG,
|
||||
& ADD_RAND_CONFIG,
|
||||
& FFT_CONFIG,
|
||||
& CRC_CONFIG
|
||||
};
|
||||
|
||||
void signal_processing_init( SignalProcessing * system, const uint32_t * bindings ) {
|
||||
system->bindings = bindings;
|
||||
|
||||
for ( uint32_t i = 0; i < TASK_COUNT; ++i ) {
|
||||
task_bind( TASK_LIST[ i ], system->bindings[ i ] );
|
||||
}
|
||||
|
||||
for ( uint32_t i = 0; i < CHANNEL_COUNT; ++i ) {
|
||||
DataChannelBinding channel_binding;
|
||||
binding_get_channel_binding( TASK_CONNECTIONS, system->bindings, i,
|
||||
& channel_binding );
|
||||
|
||||
data_channel_bind( DATA_CHANNEL_BASE_LIST[ i ], & channel_binding );
|
||||
}
|
||||
}
|
||||
|
||||
void signal_processing_run( SignalProcessing * system ) {
|
||||
for ( uint32_t i = 0; i < TASK_COUNT; ++i ) {
|
||||
int ret = task_run( TASK_LIST[ i ] );
|
||||
if ( ret ) {
|
||||
printf( "ERROR while executing task %" PRIu32 "\n", i );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void signal_processing_print_results( SignalProcessing * system ) {
|
||||
printf( " | Software | Hardware\n" );
|
||||
printf( "----------------+------------+------------\n" );
|
||||
for ( uint32_t i = 0; i < TASK_COUNT; ++i ) {
|
||||
task_base_config * task = TASK_LIST[ i ];
|
||||
printf( "%15s |", task->name );
|
||||
if ( system->bindings[ i ] == BINDING_SW ) {
|
||||
printf( " %10" PRIu32 " |\n", task_get_cycle_count( TASK_LIST[ i ] ) );
|
||||
}
|
||||
else {
|
||||
printf( " | %10" PRIu32 "\n", task_get_cycle_count( TASK_LIST[ i ] ) );
|
||||
}
|
||||
}
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define TASK_COUNT 7
|
||||
#define CHANNEL_COUNT 7
|
||||
|
||||
extern const uint32_t TASK_CONNECTIONS[ TASK_COUNT ];
|
||||
|
||||
typedef struct {
|
||||
const uint32_t * bindings;
|
||||
uint32_t tasks[ TASK_COUNT ];
|
||||
uint32_t channels[ CHANNEL_COUNT ];
|
||||
} SignalProcessing;
|
||||
|
||||
void signal_processing_init( SignalProcessing * system, const uint32_t * bindings );
|
||||
void signal_processing_run( SignalProcessing * system );
|
||||
void signal_processing_print_results( SignalProcessing * system );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "task_base_config.h"
|
||||
|
||||
typedef struct {
|
||||
task_base_config base;
|
||||
uint32_t samples_per_periode;
|
||||
float phase;
|
||||
float amplitude;
|
||||
} sine_config;
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#include "task.h"
|
||||
#include "task_base_config.h"
|
||||
|
||||
#include "binding.h"
|
||||
#include "hardware_task.h"
|
||||
#include "hardware_timestamp.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <system.h>
|
||||
|
||||
int task_configure_and_run_hardware( void * task );
|
||||
int task_run_software( void * task );
|
||||
|
||||
int task_bind( void * task, uint32_t binding ) {
|
||||
task_base_config * base = ( task_base_config * ) task;
|
||||
base->binding = binding;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int task_run( void * task ) {
|
||||
task_base_config * base = ( task_base_config * ) task;
|
||||
|
||||
base->cycle_count = 0;
|
||||
|
||||
int ret = 0;
|
||||
if ( base->binding == BINDING_HW ) {
|
||||
ret = task_configure_and_run_hardware( task );
|
||||
}
|
||||
else {
|
||||
ret = task_run_software( task );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t task_get_cycle_count( const void * task ) {
|
||||
task_base_config * base = ( task_base_config * ) task;
|
||||
|
||||
if ( base->binding == BINDING_HW ) {
|
||||
return hardware_task_get_cycle_count( base->hardware );
|
||||
}
|
||||
|
||||
return base->cycle_count;
|
||||
}
|
||||
|
||||
int task_configure_and_run_hardware( void * task ) {
|
||||
task_base_config * base = ( task_base_config * ) task;
|
||||
if ( base->configure != NULL ) {
|
||||
base->configure( task );
|
||||
}
|
||||
|
||||
hardware_task_start( base->hardware );
|
||||
while ( hardware_task_get_state( base->hardware ) != HARDWARE_TASK_DONE );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int task_run_software( void * task ) {
|
||||
task_base_config * base = ( task_base_config * ) task;
|
||||
|
||||
hardware_timestamp_start( HARDWARE_TIMESTAMP_BASE );
|
||||
|
||||
int ret = base->software( task );
|
||||
|
||||
base->cycle_count = hardware_timestamp( HARDWARE_TIMESTAMP_BASE );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
int task_bind( void * task, uint32_t binding );
|
||||
int task_run( void * task );
|
||||
uint32_t task_get_cycle_count( const void * task );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "task_add.h"
|
||||
#include "data_channel.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <system.h>
|
||||
|
||||
add_config ADD_SINE_COSINE_CONFIG = {
|
||||
.name = "add_sine_cosine",
|
||||
.binding = BINDING_SW,
|
||||
.software = task_add_run,
|
||||
.configure = NULL,
|
||||
.hardware = HARDWARE_TASK_3_BASE,
|
||||
.sources = { DATA_CHANNEL_0_BASE, DATA_CHANNEL_1_BASE },
|
||||
.sink = DATA_CHANNEL_3_BASE,
|
||||
.cycle_count = 0 };
|
||||
|
||||
add_config ADD_RAND_CONFIG = {
|
||||
.name = "add_rand",
|
||||
.binding = BINDING_SW,
|
||||
.software = task_add_run,
|
||||
.configure = NULL,
|
||||
.hardware = HARDWARE_TASK_4_BASE,
|
||||
.sources = { DATA_CHANNEL_2_BASE, DATA_CHANNEL_3_BASE },
|
||||
.sink = DATA_CHANNEL_4_BASE,
|
||||
.cycle_count = 0 };
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "add_config.h"
|
||||
|
||||
extern add_config ADD_SINE_COSINE_CONFIG;
|
||||
extern add_config ADD_RAND_CONFIG;
|
||||
|
||||
int task_add_run( void * data );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "task_function.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef struct {
|
||||
const char * name;
|
||||
uint32_t binding;
|
||||
task_function software;
|
||||
task_function configure;
|
||||
uint32_t hardware;
|
||||
uint32_t sources[ 2 ];
|
||||
uint32_t sink;
|
||||
uint32_t cycle_count;
|
||||
} task_base_config;
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "sine_config.h"
|
||||
|
||||
extern sine_config COSINE_CONFIG;
|
||||
|
||||
int task_cosinus( void * data );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "task_crc.h"
|
||||
#include "data_channel.h"
|
||||
#include "crc_config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <system.h>
|
||||
|
||||
|
||||
crc_config CRC_CONFIG = {
|
||||
.base = { .name = "crc",
|
||||
.binding = BINDING_SW,
|
||||
.software = task_crc_run,
|
||||
.configure = NULL,
|
||||
.hardware = HARDWARE_TASK_6_BASE,
|
||||
.sources = { DATA_CHANNEL_5_BASE },
|
||||
.sink = DATA_CHANNEL_6_BASE,
|
||||
.cycle_count = 0 },
|
||||
.start = 0x00000000 };
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "task.h"
|
||||
#include "crc_config.h"
|
||||
|
||||
extern crc_config CRC_CONFIG;
|
||||
|
||||
#define CRC32POLY 0xEDB88320 /* CRC-32 Polynom (Invers)*/
|
||||
|
||||
int task_crc_run( void * task );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "task_fft.h"
|
||||
#include "data_channel.h"
|
||||
#include "fft_config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <system.h>
|
||||
|
||||
fft_config FFT_CONFIG = {
|
||||
.base = { .name = "fft",
|
||||
.binding = BINDING_SW,
|
||||
.software = task_fft_run,
|
||||
.configure = NULL,
|
||||
.hardware = HARDWARE_TASK_5_BASE,
|
||||
.sources = { DATA_CHANNEL_4_BASE },
|
||||
.sink = DATA_CHANNEL_5_BASE,
|
||||
.cycle_count = 0 },
|
||||
.interval = 1e-6 };
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "fft_config.h"
|
||||
|
||||
extern fft_config FFT_CONFIG;
|
||||
|
||||
int task_fft_run( void * data );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
typedef int ( * task_function )( void * );
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "task_rand.h"
|
||||
#include "hardware_task.h"
|
||||
#include "data_channel.h"
|
||||
#include "float_word.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <system.h>
|
||||
|
||||
#define REG_SEED_OFFSET 0
|
||||
#define REG_EXP_MIN_OFFSET 1
|
||||
#define REG_EXP_MAX_OFFSET 2
|
||||
|
||||
rand_config RAND_CONFIG = {
|
||||
.base = { .name = "rand",
|
||||
.binding = BINDING_SW,
|
||||
.software = task_rand_run,
|
||||
.configure = task_rand_configure,
|
||||
.hardware = HARDWARE_TASK_2_BASE,
|
||||
.sources = { 0, 0 },
|
||||
.sink = DATA_CHANNEL_2_BASE,
|
||||
.cycle_count = 0 },
|
||||
.seed = 1.3,
|
||||
.abs_min = 0.125,
|
||||
.abs_max = 9.0 };
|
||||
|
||||
int task_rand_configure( void * data ) {
|
||||
rand_config * task = ( rand_config * ) data;
|
||||
uint32_t base = task->base.hardware;
|
||||
|
||||
float_word value = { .value = task->seed };
|
||||
hardware_task_set_config( base, REG_SEED_OFFSET, value.word );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "rand_config.h"
|
||||
|
||||
extern rand_config RAND_CONFIG;
|
||||
|
||||
int task_rand_configure( void * task );
|
||||
|
||||
int task_rand_run( void * task );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "task_sine.h"
|
||||
#include "hardware_task.h"
|
||||
#include "sine_config.h"
|
||||
#include "data_channel.h"
|
||||
#include "float_word.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <system.h>
|
||||
|
||||
#define REG_STEP_SIZE_OFFSET 0
|
||||
#define REG_PHASE_OFFSET 1
|
||||
#define REG_AMPLITUDE_OFFSET 2
|
||||
|
||||
sine_config SINE_CONFIG = {
|
||||
.base = {
|
||||
.name = "sine",
|
||||
.binding = BINDING_SW,
|
||||
.software = task_sine_run,
|
||||
.configure = task_sine_configure,
|
||||
.hardware = HARDWARE_TASK_0_BASE,
|
||||
.sources = { 0, 0 },
|
||||
.sink = DATA_CHANNEL_0_BASE,
|
||||
.cycle_count = 0 },
|
||||
.samples_per_periode = 32,
|
||||
.phase = 0.0,
|
||||
.amplitude = 4.0 };
|
||||
|
||||
sine_config COSINE_CONFIG = {
|
||||
.base = { .name = "cosine",
|
||||
.binding = BINDING_SW,
|
||||
.software = task_sine_run,
|
||||
.configure = task_sine_configure,
|
||||
.hardware = HARDWARE_TASK_1_BASE,
|
||||
.sources = { 0, 0 },
|
||||
.sink = DATA_CHANNEL_1_BASE,
|
||||
.cycle_count = 0 },
|
||||
.samples_per_periode = 200,
|
||||
.phase = M_PI / 2.0,
|
||||
.amplitude = 2.0 };
|
||||
|
||||
uint32_t to_hardware_step_size( uint32_t steps ) {
|
||||
return UINT_MAX / steps + 1;
|
||||
}
|
||||
|
||||
uint32_t to_hardware_phase( float phase ) {
|
||||
return ( phase / ( 2.0 * M_PI ) ) * UINT_MAX;
|
||||
}
|
||||
|
||||
int task_sine_configure( void * data ) {
|
||||
sine_config * task = ( sine_config * ) data;
|
||||
uint32_t base = task->base.hardware;
|
||||
float_word amplitude;
|
||||
amplitude.value = task->amplitude;
|
||||
|
||||
hardware_task_set_config( base, REG_STEP_SIZE_OFFSET,
|
||||
to_hardware_step_size( task->samples_per_periode ) );
|
||||
|
||||
hardware_task_set_config( base, REG_PHASE_OFFSET,
|
||||
to_hardware_phase( task->phase ) );
|
||||
|
||||
hardware_task_set_config( base, REG_AMPLITUDE_OFFSET, amplitude.word );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "sine_config.h"
|
||||
|
||||
extern sine_config SINE_CONFIG;
|
||||
extern sine_config COSINE_CONFIG;
|
||||
|
||||
int task_sine_configure( void * task );
|
||||
|
||||
int task_sine_run( void * task );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "task.h"
|
||||
|
||||
int task_sub( void * data );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user