This commit is contained in:
2025-09-16 13:23:11 +03:00
parent 99cc783f82
commit 03cd22ef4b
13 changed files with 5049 additions and 4622 deletions

File diff suppressed because it is too large Load Diff

278
gcc/l502-bf.ld_experimental Normal file
View File

@ -0,0 +1,278 @@
MEMORY
{
MEM_L1_CODE : ORIGIN = 0xFFA00000, LENGTH = 0xc000
MEM_L1_CODE_CACHE : ORIGIN = 0xFFA10000, LENGTH = 0x4000
MEM_L1_SCRATCH : ORIGIN = 0xFFB00000, LENGTH = 0x1000
MEM_L1_DATA_B : ORIGIN = 0xFF900000, LENGTH = 0x8000
MEM_L1_DATA_A : ORIGIN = 0xFF800000, LENGTH = 0x8000
MEM_SDRAM : ORIGIN = 0x00000000, LENGTH = 32 * 1024 * 1024
}
/* The default linker script, for single core blackfin standalone executables */
OUTPUT_FORMAT("elf32-bfin", "elf32-bfin", "elf32-bfin")
OUTPUT_ARCH(bfin)
ENTRY(__start)
SECTIONS
{
.sdram_noinit (NOLOAD) :
{
KEEP(*(.sdram_noinit, .sdram_noinit.*))
} > MEM_SDRAM
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x0)); . = SEGMENT_START("text-segment", 0x0);
.interp : { *(.interp) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
.rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) }
.rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) }
.rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
.rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
.rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) }
.rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) }
.rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) }
.rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) }
.rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) }
.rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) }
.rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) }
.rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
.rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
.rel.iplt :
{
PROVIDE_HIDDEN (___rel_iplt_start = .);
*(.rel.iplt)
PROVIDE_HIDDEN (___rel_iplt_end = .);
}
.rela.iplt :
{
PROVIDE_HIDDEN (___rela_iplt_start = .);
*(.rela.iplt)
PROVIDE_HIDDEN (___rela_iplt_end = .);
}
.rel.plt :
{
*(.rel.plt)
}
.rela.plt :
{
*(.rela.plt)
}
.init :
{
KEEP (*(.init))
KEEP (*basiccrt*(.text .text.*))
} >MEM_L1_CODE =0
.plt : { *(.plt) }
.iplt : { *(.iplt) }
.text :
{
*(.text.unlikely .text.*_unlikely)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
. = ALIGN( 64 );
} >MEM_L1_CODE
.fini :
{
KEEP (*(.fini))
} >MEM_L1_CODE
. = ALIGN( 64 );
PROVIDE (___etext = .);
PROVIDE (__etext = .);
PROVIDE (_etext = .);
.board_state :
{
_startfix_sect = .;
KEEP(*(board_state .board_state .board_state.*))
. = _startfix_sect + 8196;
} >MEM_L1_DATA_A
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } > MEM_L1_DATA_A
.rodata1 : { *(.rodata1) }
.sdata2 :
{
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
}
.sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
.eh_frame_hdr : { *(.eh_frame_hdr) } > MEM_L1_DATA_A
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } > MEM_L1_DATA_A
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1));
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
/* Thread Local Storage sections */
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.preinit_array :
{
PROVIDE_HIDDEN (___preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (___preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (___init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE_HIDDEN (___init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN (___fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array))
PROVIDE_HIDDEN (___fini_array_end = .);
}
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} > MEM_L1_DATA_A
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} > MEM_L1_DATA_A
.jcr : { KEEP (*(.jcr)) } > MEM_L1_DATA_A
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
.dynamic : { *(.dynamic) }
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
. = ALIGN( 64 );
} > MEM_L1_DATA_A
.data1 : { *(.data1) }
.got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata :
{
*(.sdata .sdata.* .gnu.linkonce.s.*)
}
__edata = .; PROVIDE (_edata = .);
___bss_start = .;
.sbss :
{
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
}
.bss :
{
__bss_start = .;
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
. = ALIGN( 64 );
__bss_end = .;
} > MEM_L1_DATA_A
. = ALIGN( 64 );
__end = .; PROVIDE (_end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo .zdebug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames .zdebug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges .zdebug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames .zdebug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.* .zdebug_info) }
.debug_abbrev 0 : { *(.debug_abbrev .zdebug_abbrev) }
.debug_line 0 : { *(.debug_line .zdebug_line) }
.debug_frame 0 : { *(.debug_frame .zdebug_frame) }
.debug_str 0 : { *(.debug_str .zdebug_str) }
.debug_loc 0 : { *(.debug_loc .zdebug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo .zdebug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames .zdebug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames .zdebug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames .zdebug_typenames) }
.debug_varnames 0 : { *(.debug_varnames .zdebug_varnames) }
/* DWARF 3 */
.debug_pubtypes 0 : { *(.debug_pubtypes .zdebug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges .zdebug_ranges) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
__end = .; PROVIDE (_end = .);
__stack_start = ORIGIN(MEM_L1_SCRATCH);
__stack_end = ORIGIN(MEM_L1_SCRATCH) + 0x1000;
}

23
src/complex.c Normal file
View File

@ -0,0 +1,23 @@
#include "complex.h"
#include <math.h>
complex conv_from_polar(double r, double radians) {
complex result;
result.re = r * cos(radians);
result.im = r * sin(radians);
return result;
}
complex add(complex left, complex right) {
complex result;
result.re = left.re + right.re;
result.im = left.im + right.im;
return result;
}
complex multiply(complex left, complex right) {
complex result;
result.re = left.re*right.re - left.im*right.im;
result.im = left.re*right.im + left.im*right.re;
return result;
}

9
src/complex.h Normal file
View File

@ -0,0 +1,9 @@
typedef struct complex_t {
double re;
double im;
} complex;
complex conv_from_polar(double r, double radians);
complex add(complex left, complex right);
complex multiply(complex left, complex right);

BIN
src/complex.o Normal file

Binary file not shown.

147
src/fft.c Normal file
View File

@ -0,0 +1,147 @@
#include "fft.h"
#include <stdlib.h>
#define PI 3.1415926535897932384626434
complex* DFT_naive(complex* x, int N) {
complex* X = (complex*) malloc(sizeof(struct complex_t) * N);
int k, n;
for(k = 0; k < N; k++) {
X[k].re = 0.0;
X[k].im = 0.0;
for(n = 0; n < N; n++) {
X[k] = add(X[k], multiply(x[n], conv_from_polar(1, -2*PI*n*k/N)));
}
}
return X;
}
/** Implements the Good-Thomas FFT algorithm.
*
* @expects: N1 and N2 must be relatively prime
* @expects: N1*N2 = N
*/
complex* FFT_GoodThomas(complex* input, int N, int N1, int N2) {
int k1, k2, z;
/* Allocate columnwise matrix */
complex** columns = (complex**) malloc(sizeof(struct complex_t*) * N1);
for(k1 = 0; k1 < N1; k1++) {
columns[k1] = (complex*) malloc(sizeof(struct complex_t) * N2);
}
/* Allocate rowwise matrix */
complex** rows = (complex**) malloc(sizeof(struct complex_t*) * N2);
for(k2 = 0; k2 < N2; k2++) {
rows[k2] = (complex*) malloc(sizeof(struct complex_t) * N1);
}
/* Reshape input into N1 columns (Using Good-Thomas Indexing) */
for(z = 0; z < 30; z++) {
k1 = z % N1;
k2 = z % N2;
columns[k1][k2] = input[z];
}
/* Compute N1 DFTs of length N2 using naive method */
for (k1 = 0; k1 < N1; k1++) {
columns[k1] = DFT_naive(columns[k1], N2);
}
/* Transpose */
for(k1 = 0; k1 < N1; k1++) {
for (k2 = 0; k2 < N2; k2++) {
rows[k2][k1] = columns[k1][k2];
}
}
/* Compute N2 DFTs of length N1 using naive method */
for (k2 = 0; k2 < N2; k2++) {
rows[k2] = DFT_naive(rows[k2], N1);
}
/* Flatten into single output (Using chinese remainder theorem) */
complex* output = (complex*) malloc(sizeof(struct complex_t) * N);
for(k1 = 0; k1 < N1; k1++) {
for (k2 = 0; k2 < N2; k2++) {
z = N1*k2 + N2*k1;
output[z%N] = rows[k2][k1];
}
}
/* Free all alocated memory except output and input arrays */
for(k1 = 0; k1 < N1; k1++) {
free(columns[k1]);
}
for(k2 = 0; k2 < N2; k2++) {
free(rows[k2]);
}
free(columns);
free(rows);
return output;
}
/** Implements the Cooley-Tukey FFT algorithm.
*
* @expects: N1*N2 = N
*/
complex* FFT_CooleyTukey(complex* input, int N, int N1, int N2) {
int k1, k2;
/* Allocate columnwise matrix */
complex** columns = (complex**) malloc(sizeof(struct complex_t*) * N1);
for(k1 = 0; k1 < N1; k1++) {
columns[k1] = (complex*) malloc(sizeof(struct complex_t) * N2);
}
/* Allocate rowwise matrix */
complex** rows = (complex**) malloc(sizeof(struct complex_t*) * N2);
for(k2 = 0; k2 < N2; k2++) {
rows[k2] = (complex*) malloc(sizeof(struct complex_t) * N1);
}
/* Reshape input into N1 columns */
for (k1 = 0; k1 < N1; k1++) {
for(k2 = 0; k2 < N2; k2++) {
columns[k1][k2] = input[N1*k2 + k1];
}
}
/* Compute N1 DFTs of length N2 using naive method */
for (k1 = 0; k1 < N1; k1++) {
columns[k1] = DFT_naive(columns[k1], N2);
}
/* Multiply by the twiddle factors ( e^(-2*pi*j/N * k1*k2)) and transpose */
for(k1 = 0; k1 < N1; k1++) {
for (k2 = 0; k2 < N2; k2++) {
rows[k2][k1] = multiply(conv_from_polar(1, -2.0*PI*k1*k2/N), columns[k1][k2]);
}
}
/* Compute N2 DFTs of length N1 using naive method */
for (k2 = 0; k2 < N2; k2++) {
rows[k2] = DFT_naive(rows[k2], N1);
}
/* Flatten into single output */
complex* output = (complex*) malloc(sizeof(struct complex_t) * N);
for(k1 = 0; k1 < N1; k1++) {
for (k2 = 0; k2 < N2; k2++) {
output[N2*k1 + k2] = rows[k2][k1];
}
}
/* Free all alocated memory except output and input arrays */
for(k1 = 0; k1 < N1; k1++) {
free(columns[k1]);
}
for(k2 = 0; k2 < N2; k2++) {
free(rows[k2]);
}
free(columns);
free(rows);
return output;
}

5
src/fft.h Normal file
View File

@ -0,0 +1,5 @@
#include "complex.h"
complex* FFT_CooleyTukey(complex* x, int N, int N1, int N2);
complex* FFT_GoodThomas(complex* x, int N, int N1, int N2);
complex* DFT_naive(complex* x, int N);

BIN
src/fft.o Normal file

Binary file not shown.

View File

@ -213,7 +213,7 @@ uint32_t usr_in_proc_data(uint32_t* data, uint32_t size) {
uint8_t header = (uint8_t)(word >> 24);
if (header == 0x00){ //digital_channel. switches LFSM state machine
DY_SYN_2_value_prev = DY_SYN_2_value;
if (word & 0b1 << 17){
if (word & (0b1 << 17)){
DY_SYN_2_value = 1;
}else{
DY_SYN_2_value = 0;
@ -224,8 +224,9 @@ uint32_t usr_in_proc_data(uint32_t* data, uint32_t size) {
Proc_state.average_N ++;
Proc_state.AVG_buff_I = 0;
Proc_state.LFSM_state = CYCLE_STARTED;
//if (Proc_state.average_N >= Proc_state.average_N_max){ //whole average ended
if (1){
if (Proc_state.average_N >= Proc_state.average_N_max){ //whole average ended
Proc_state.average_N = 0;
//if (1){
Proc_state.AVG_state = FULLY_COMPLETED;
//averaging completed => copy average results to TX_buff and start avg again
TX_buff_I = 0;
@ -243,7 +244,7 @@ uint32_t usr_in_proc_data(uint32_t* data, uint32_t size) {
}
TX_buff_state = TODO_TX;
/*
for (uint32_t i = 0; i < TX_BUFF_SIZE; ++i){
TX_buff_shadow[i] = TX_buff[i];
}
@ -254,7 +255,7 @@ uint32_t usr_in_proc_data(uint32_t* data, uint32_t size) {
// hdma_send_req_start(TX_buff, TX_BUFF_SIZE, 0);
//TX_buff_state = TRANSMITTING;
TX_buff_state = TX_DONE;
*/
}else{ //
Proc_state.AVG_state = STEP_RUNNING;
@ -269,8 +270,9 @@ uint32_t usr_in_proc_data(uint32_t* data, uint32_t size) {
if (1){
if (1){
// AVG_buff[Proc_state.AVG_buff_I++] = 0xC0000000 | (0x00FFFFFF & (AVG_buff[Proc_state.AVG_buff_I] + val));
AVG_buff[Proc_state.AVG_buff_I++] = 0xC0000000 | val;
AVG_buff[Proc_state.AVG_buff_I] = 0xC0000000 | ((val + AVG_buff[Proc_state.AVG_buff_I]) & 0xFFFFFF);
//AVG_buff[Proc_state.AVG_buff_I++] = 0xC0000000;
Proc_state.AVG_buff_I++;
if (Proc_state.AVG_buff_I >= AVG_BUFF_SIZE){
Proc_state.AVG_state = STEP_COMPLETED;
}
@ -839,7 +841,7 @@ void usr_cmd_process(t_l502_bf_cmd *cmd) {
Proc_state.mode = AVG;
Proc_state.mode_next = AVG;
Proc_state.LFSM_state = CYCLE_UNKNOWN;
Proc_state.average_N_max = 3;
Proc_state.average_N_max = 30;
// Proc_state.average_N_max = cmd->param;
Proc_state.average_N = 0;
Proc_state.TX_buff_I = 0;

View File

@ -0,0 +1 @@
#pragma section("sdram_noinit", NO_INIT)