This commit is contained in:
Steven Dan
2026-03-20 19:42:15 +08:00
parent 8108aac6f8
commit 3f89011703
17 changed files with 323 additions and 1003 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -137,7 +137,7 @@ set(APP_COMPILER_FLAGS_ex3d_71_all ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
-DMAX_FREQ=48000
-DUSE_EX3D
-DMIXER=0
-DAIZIP_DNR=0 -ldnr_50ms
-ldnr_11ms
-llib_ex3d_all
-DEQ_EN=1
-DEX3D_SF_NUM=3

View File

@@ -1,7 +0,0 @@
// Copyright 2011-2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
void agc_init_interface(void);

View File

@@ -10,33 +10,39 @@
#include <xcore/chanend.h>
#include <xcore/channel.h>
#include "xc_ptr.h"
#include "dnr_dsp_buf.h"
#include "xua_conf.h"
#include "share_buffer.h"
void buffer_exchange(chanend_t c_data, unsigned sampsFromUsbToAudio[]) {
#if EQ_EN
chan_out_buf_word (c_data, sampsFromUsbToAudio, 2) ;
void dnr_exchange_buffer(int32_t *data);
void buffer_exchange(chanend_t c_data, unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[]) {
chan_out_buf_word (c_data, sampsFromUsbToAudio, 2);
chan_out_buf_word (c_data, sampsFromAudioToUsb, 2);
chan_in_buf_word (c_data , sampsFromUsbToAudio, 2);
#endif
chan_in_buf_word (c_data , sampsFromAudioToUsb, 2);
}
void dsp_main (chanend_t c_data) {
#if EQ_EN
int input[NUM_USB_CHAN_OUT];
int output[I2S_CHANS_DAC];
void dsp_main (chanend_t c_data) {
int play_input[NUM_USB_CHAN_OUT];
int play_output[I2S_CHANS_DAC];
int mic_input[NUM_USB_CHAN_IN];
int mic_output[I2S_CHANS_ADC];
int count = 0;
unsigned ch[1] = {2};
while (1) {
chan_in_buf_word (c_data , input, 2) ;
chan_out_buf_word (c_data , output, I2S_CHANS_DAC);
write_to_ring_buffer(0, input[0]);
write_to_ring_buffer(1, input[1]);
output[0] = read_from_ring_buffer(2);
output[1] = read_from_ring_buffer(3);
chan_in_buf_word (c_data , play_input, 2) ;
chan_in_buf_word (c_data , mic_input, 2) ;
chan_out_buf_word (c_data , play_output, I2S_CHANS_DAC);
chan_out_buf_word (c_data , mic_output, I2S_CHANS_ADC);
write_to_ring_buffer(0, play_input[0]);
write_to_ring_buffer(1, play_input[1]);
play_output[0] = read_from_ring_buffer(2);
play_output[1] = read_from_ring_buffer(3);
dnr_exchange_buffer(mic_input);
mic_output[0] = mic_input[0];
mic_output[1] = mic_input[1];
// dnr_exchange_buffer((int32_t *)mic_input, (int32_t *)mic_output);
}
#endif
}

View File

@@ -0,0 +1,55 @@
#ifndef AZP_H_
#define AZP_H_
#include "stdint.h"
typedef enum
{
errAZP_NoError = 0, // No error
errAZP_NotReady, // Not ready
errAZP_InvalidParam, // Invalid parameter
errAZP_InvalidLicense, // Invalid license
errAZP_BufferOverflow, // Buffer overflow
errAZP_BufferTooSmall, // Buffer too small
} AZP_STATUS;
typedef struct
{
int8_t *buffer1; // Pointer to the first buffer
int8_t *buffer2; // Pointer to the second buffer
int32_t buffer1_size; // Size of the first buffer
int32_t buffer2_size; // Size of the second buffer
int32_t sample_rate; // Sample rate, only support 16000Hz
} azp_dnr_param_t;
/// @brief DNR initialization
/// @param param Configuration parameters
/// @return License status
/// @brief DNR initialization
/// @param param Configuration parameters
/// @return License status
AZP_STATUS AI_DNR_init(azp_dnr_param_t *param);
/// @brief DNR processing
/// @param audio Q31 input and output
/// @return License status
AZP_STATUS AI_DNR_Processing(int32_t *audio);
/// @brief Get version number
/// @return If not licensed, returns NULL
char *AI_DNR_Version();
/// @brief Get the size of the working buffers
/// @param buf_size Size of the first buffer
/// @param buf_size2 Size of the second buffer
void getBufferSize(int32_t *buf_size, int32_t *buf_size2);
/// @brief Set the noise reduction depth
/// @param dB Range (-200 to 0 dB)
/// -200: Maximum noise reduction
/// 0: No noise reduction
void setNoisy_mix_factor(float dB);
#endif // AZP_H_

View File

@@ -0,0 +1,52 @@
// Copyright 2016-2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#if UART_DEBUG || DEBUG_MEMORY_LOG_ENABLED
#define DEBUG_PRINT_ENABLE 1
#endif
#include <xs1.h>
#include <xua_conf.h>
#include "ringbuf.h"
#include <xcore/chanend.h>
#include <xcore/channel.h>
#include "dnr_dsp_buf.h"
#include "xc_ptr.h"
#include "debug_print.h"
unsigned g_dsp_eof = 0;
void dnr_exchange_buffer(int32_t *data) {
static unsigned buff_index = 0;
write_to_sample_in_buf(data[1], buff_index, 0);
read_from_sample_out_buf(&data[1],buff_index, 0);
data[0] = data[1];
buff_index++;
#if DNR_11MS
if (buff_index == 128)
{
#else
if (buff_index == 512)
{
#endif
buf_slot_rotate();
buff_index = 0;
SET_SHARED_GLOBAL(g_dsp_eof, 1);
}
}
void Aizip_DNR_init(void);
void dnr_dsp_proc_task(void)
{
Aizip_DNR_init();
while(1) {
unsigned dsp_eof = 0;
GET_SHARED_GLOBAL(dsp_eof, g_dsp_eof);
if (dsp_eof) {
SET_SHARED_GLOBAL(g_dsp_eof, 0);
start_dsp_processing();
}
}
}

View File

@@ -0,0 +1,95 @@
// Copyright 2011-2023 XMOS LIMITED.
//
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#if UART_DEBUG || DEBUG_MEMORY_LOG_ENABLED
#define DEBUG_PRINT_ENABLE 1
#endif
#include <xs1.h>
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <platform.h>
#include <string.h>
#include "dnr_dsp_buf.h"
#include "aizip_dnr.h"
#include "debug_print.h"
#include "flash.h"
//for AGC
//static agc_stage_ctx_t DWORD_ALIGNED agc_stage_state = {};
static unsigned __attribute__((aligned (4))) dsp_dnr_frame_buf[BUF_SLOT_NUM][DSP_CH_NUM][DNR_DSP_FRAME_SIZE];
unsigned sample_in_buf_slot=0;
unsigned processing_buf_slot=2;
unsigned sample_out_buf_slot=1;
void dsp_buf_init()
{
sample_in_buf_slot=0;
sample_out_buf_slot=1;
processing_buf_slot=2;
}
static void buf_slot_inc(unsigned* buf_slot_input)
{
if(*buf_slot_input == BUF_SLOT_NUM-1){
*buf_slot_input = 0;
}
else{
*buf_slot_input = *buf_slot_input+1;
}
}
void buf_slot_rotate()
{
buf_slot_inc(&sample_in_buf_slot);
buf_slot_inc(&sample_out_buf_slot);
buf_slot_inc(&processing_buf_slot);
}
void write_to_sample_in_buf(unsigned data, unsigned index, unsigned ch)
{
dsp_dnr_frame_buf[sample_in_buf_slot][ch][index]=data;
}
void read_from_sample_out_buf(unsigned* read_data, unsigned index, unsigned ch)
{
*read_data = dsp_dnr_frame_buf[sample_out_buf_slot][ch][index];
}
#if DNR_11MS
int8_t buffer[4208] __attribute__((aligned(4)));
int8_t buffer2[31136] __attribute__((aligned(4)));
#else
int8_t buffer[21416] __attribute__((aligned(4)));
int8_t buffer2[31712] __attribute__((aligned(4)));
#endif
azp_dnr_param_t pram = {
.buffer1 = buffer,
.buffer1_size = sizeof(buffer),
.buffer2 = buffer2,
.buffer2_size = sizeof(buffer2),
.sample_rate = 48000};
unsigned g_dnr_init_flag = 0;
void Aizip_DNR_init(void)
{
delay_microseconds(10000);
// setFlashPortPins(XS1_PORT_1B,XS1_PORT_1C,XS1_PORT_4B, XS1_CLKBLK_3);
int sta = AI_DNR_init(&pram);
g_dnr_init_flag = 1;
debug_printf("AI_DNR_init status %d\n", sta);
}
void start_dsp_processing(void)
{
float level = -200;
setNoisy_mix_factor(level);
AI_DNR_Processing((int32_t *)&dsp_dnr_frame_buf[processing_buf_slot][0][0]);
}

View File

@@ -0,0 +1,39 @@
// Copyright 2011-2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifndef __DNR_DSP_BUF_H__
#define __DNR_DSP_BUF_H__
#include <xs1.h>
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <platform.h>
#include <xcore/chanend.h>
#include <xcore/channel.h>
#if DNR_11MS
#define DNR_DSP_FRAME_SIZE 128
#else
#define DNR_DSP_FRAME_SIZE 512
#endif
#define BUF_SLOT_NUM 3 //one for input, one for output, one for processing
#define DSP_CH_NUM 2
#if __XC__
extern "C" {
#endif
void dnr_set_chan(chanend_t dnr_tile0_c, chanend_t dnr_tile1_c);
void dsp_buf_init();
void buf_slot_rotate();
void write_to_sample_in_buf(unsigned data, unsigned index, unsigned ch);
void read_from_sample_out_buf(unsigned* read_data, unsigned index, unsigned ch);
void start_dsp_processing(void);
void Aizip_DNR_init(void);
#if __XC__
} //extern c
#endif
#endif //RINGBUFFER_H

View File

@@ -0,0 +1,5 @@
#ifndef __FLASH_H__
#define __FLASH_H__
#include "stdint.h"
void setFlashPortPins(uint32_t cs,uint32_t sclk,uint32_t sio,uint32_t clkblk);
#endif

View File

@@ -0,0 +1,45 @@
// Copyright 2011-2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifndef __RINGBUF_H__
#define __RINGBUF_H__
#include <xs1.h>
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <platform.h>
#if __XC__
extern "C" {
#endif
#define FRAME_SIZE 120 //101623 - from 256 to 120
#define RF_CHAN_NUM 2 //stereo. Multichannel uses NUM_USB_CHAN_OUT
//
#define RB_SIZE FRAME_SIZE*RF_CHAN_NUM*16 //2 channel, 32-bit, 16 frame
#define RB_MASK (RB_SIZE - 1)
extern uint32_t r_buffer[RB_SIZE];
typedef struct {
uint32_t * buf_addr;
int next_empty;
int next_data;
int full;
int empty;
} ring_buffer_t;
void rb_init(void);
void rb_put_word(uint32_t data);
uint32_t rb_get_word(void);
int rb_is_full(void);
int rb_is_empty(void);
#if __XC__
} //extern c
#endif
#endif //RINGBUFFER_H

View File

@@ -142,7 +142,7 @@ void UserBufferManagementInit(unsigned sampFreq)
}
float fLevel[NUM_USB_CHAN_OUT] = {0,};
enum {UBM_A3D_OFF=0, UBM_A3D_VON=1, UBM_A3D_ON=2};
extern void buffer_exchange(chanend_t c_data, unsigned sampsFromUsbToAudio[]);
extern void buffer_exchange(chanend_t c_data, unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[]);
extern unsigned int is_eq_disabled(void);
void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[])
{
@@ -280,8 +280,8 @@ void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudi
#endif
};
buffer_exchange(uc_eq_data, sampsFromUsbToAudio);
sampsFromAudioToUsb[0] = sampsFromAudioToUsb[1];
buffer_exchange(uc_eq_data, sampsFromUsbToAudio, sampsFromAudioToUsb);
// sampsFromAudioToUsb[0] = sampsFromAudioToUsb[1];
}
#ifndef HID_MAX_DATA_BYTES

View File

@@ -102,7 +102,7 @@ void lfs_deinit(void) {
swlock_release(&lfs_lock);
}
#pragma stackfunction 5480
#pragma stackfunction 1300
void lfs_read_config(unsigned char * config, unsigned char * buffer, unsigned size)
{
swlock_acquire(&lfs_lock);
@@ -130,7 +130,7 @@ void lfs_read_config(unsigned char * config, unsigned char * buffer, unsigned si
}
#pragma stackfunction 5480
#pragma stackfunction 1300
void lfs_write_config(unsigned char * config, unsigned char * buffer, unsigned size)
{
swlock_acquire(&lfs_lock);

View File

@@ -1,710 +0,0 @@
// Copyright 2020-2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#define DEBUG_UNIT QSPI_FLASH
#include "qspi_flash.h"
#include "sfdp.h"
#if QSPI_FLASH_SANITY_CHECKS
/*
* Ensure NDEBUG is not defined when the
* flash sanity checks are enabled.
*/
#if defined(NDEBUG)
#undef NDEBUG
#endif
#endif
#include <xcore/assert.h>
#include <xcore/hwtimer.h>
/*
* TODO: This isn't fully supported yet
*/
#define FOUR_BYTE_ADDRESS_SUPPORT 0
#define BARRIER() asm volatile("": : :"memory")
#define WRITE_ENABLE_COMMAND QSPI_IO_BYTE_TO_MOSI(0x06)
#define WRITE_DISABLE_COMMAND QSPI_IO_BYTE_TO_MOSI(0x04)
#define ERASE_CHIP_COMMAND QSPI_IO_BYTE_TO_MOSI(0xC7)
#define PP_1_1_1_COMMAND QSPI_IO_BYTE_TO_MOSI(0x02)
#define PP_1_1_4_COMMAND QSPI_IO_BYTE_TO_MOSI(0x32)
#define PP_1_4_4_COMMAND QSPI_IO_BYTE_TO_MOSI(0x38)
#define READ_STATUS_REG_COMMAND QSPI_IO_BYTE_TO_MOSI(0x05)
#define READ_ID_COMMAND QSPI_IO_BYTE_TO_MOSI(0x9F)
#define WRITE_STATUS_REG_COMMAND QSPI_IO_BYTE_TO_MOSI(0x01)
#define FAST_READ_COMMAND QSPI_IO_BYTE_TO_MOSI(0x0B)
#define QUAD_IO_READ_CMD_VAL 0xEB
#define QUAD_IO_READ_COMMAND QSPI_IO_BYTE_TO_MOSI(QUAD_IO_READ_CMD_VAL)
#if FOUR_BYTE_ADDRESS_SUPPORT
#define QUAD_IO_READ_DUMMY_CYCLES 6
#else
#define QUAD_IO_READ_DUMMY_CYCLES 4
#endif
#define FAST_READ_DUMMY_CYCLES 8
bool qspi_flash_quad_enable_write(qspi_flash_ctx_t *ctx, bool set)
{
uint8_t status[2];
uint8_t quad_enable_bitmask;
const uint32_t no_cmd = QSPI_IO_BYTE_TO_MOSI(0x00);
if (ctx->qe_reg == 0) {
return true;
}
xassert(ctx->qe_reg == 1 || ctx->qe_reg == 2);
xassert(ctx->qe_bit >= 0 && ctx->qe_bit <= 7);
quad_enable_bitmask = 1 << ctx->qe_bit;
if (ctx->qe_reg == 1 || ctx->sr2_read_cmd == no_cmd) {
qspi_flash_read_status_register(ctx, status, ctx->qe_reg);
} else {
qspi_flash_read_status_register(ctx, &status[0], 1);
qspi_flash_read_register(ctx, ctx->sr2_read_cmd, &status[1], 1);
}
if (!!(status[ctx->qe_reg - 1] & quad_enable_bitmask) != set) {
if (set) {
status[ctx->qe_reg - 1] |= quad_enable_bitmask;
} else {
status[ctx->qe_reg - 1] &= ~quad_enable_bitmask;
}
qspi_flash_write_enable(ctx);
if (ctx->qe_reg == 1 || ctx->sr2_write_cmd == no_cmd) {
qspi_flash_write_status_register(ctx, status, ctx->qe_reg);
} else {
qspi_flash_write_register(ctx, ctx->sr2_write_cmd, &status[1], 1);
}
qspi_flash_wait_while_write_in_progress(ctx);
status[0] = 0;
status[1] = 0;
if (ctx->qe_reg == 1 || ctx->sr2_read_cmd == no_cmd) {
qspi_flash_read_status_register(ctx, status, ctx->qe_reg);
} else {
qspi_flash_read_register(ctx, ctx->sr2_read_cmd, &status[1], 1);
}
return !!(status[ctx->qe_reg - 1] & quad_enable_bitmask) == set;
} else {
return true;
}
}
void qspi_flash_write_enable(qspi_flash_ctx_t *ctx)
{
qspi_io_ctx_t *qspi_io_ctx = &ctx->qspi_io_ctx;
uint8_t status;
do {
qspi_io_start_transaction(qspi_io_ctx, WRITE_ENABLE_COMMAND, 8, qspi_io_full_speed);
qspi_io_end_transaction(qspi_io_ctx);
qspi_flash_read_status_register(ctx, &status, 1);
} while ((status & QSPI_FLASH_STATUS_REG_WEL_BM) == 0);
}
void qspi_flash_write_disable(qspi_flash_ctx_t *ctx)
{
qspi_io_ctx_t *qspi_io_ctx = &ctx->qspi_io_ctx;
uint8_t status;
do {
qspi_io_start_transaction(qspi_io_ctx, WRITE_DISABLE_COMMAND, 8, qspi_io_full_speed);
qspi_io_end_transaction(qspi_io_ctx);
qspi_flash_read_status_register(ctx, &status, 1);
} while ((status & QSPI_FLASH_STATUS_REG_WEL_BM) != 0);
}
bool qspi_flash_write_in_progress(qspi_flash_ctx_t *ctx)
{
uint8_t status_reg;
qspi_flash_read_register(ctx, ctx->busy_poll_cmd, &status_reg, 1);
return ((status_reg >> ctx->busy_poll_bit) & 1) != ctx->busy_poll_ready_value;
}
void qspi_flash_wait_while_write_in_progress(qspi_flash_ctx_t *ctx)
{
qspi_flash_poll_register(ctx, ctx->busy_poll_cmd, (1 << ctx->busy_poll_bit), ctx->busy_poll_ready_value << ctx->busy_poll_bit);
}
void qspi_flash_erase(qspi_flash_ctx_t *ctx,
uint32_t address,
qspi_flash_erase_length_t erase_length)
{
qspi_io_ctx_t *qspi_io_ctx = &ctx->qspi_io_ctx;
size_t cycles;
uint32_t cmd;
uint8_t *address_bytes;
#if QSPI_FLASH_SANITY_CHECKS
uint8_t status_reg;
qspi_flash_read_status_register(ctx, &status_reg, 1);
xassert(status_reg & QSPI_FLASH_STATUS_REG_WEL_BM);
#endif
/*
* Manipulate the address so that in memory it is:
* {byte 2, byte 1, byte 0, XX}
* it will get sent out as 3 bytes.
*/
address = byterev(address << 8);
address_bytes = (uint8_t *) &address;
xassert(erase_length >= 0 && erase_length <= qspi_flash_erase_chip);
if (erase_length > qspi_flash_erase_chip) {
return;
}
if (erase_length == qspi_flash_erase_chip) {
cmd = ERASE_CHIP_COMMAND;
cycles = 8;
} else {
xassert(ctx->erase_info[erase_length].size_log2 > 0);
if (ctx->erase_info[erase_length].size_log2 <= 0) {
return;
}
cmd = ctx->erase_info[erase_length].cmd;
cycles = 32;
}
qspi_io_start_transaction(qspi_io_ctx, cmd, cycles, qspi_io_full_speed);
if (cycles == 32) {
qspi_io_mosi_out(qspi_io_ctx, qspi_io_transfer_normal, address_bytes, 3);
}
qspi_io_end_transaction(qspi_io_ctx);
}
void qspi_flash_write_register(qspi_flash_ctx_t *ctx,
uint32_t cmd,
const uint8_t *val,
size_t len)
{
qspi_io_ctx_t *qspi_io_ctx = &ctx->qspi_io_ctx;
size_t cycles = 8 + /* 8 cycles for the command */
8 * len; /* 2 cycles per byte */
qspi_io_start_transaction(qspi_io_ctx, cmd, cycles, qspi_io_full_speed);
qspi_io_mosi_out(qspi_io_ctx, qspi_io_transfer_normal, val, len);
qspi_io_end_transaction(qspi_io_ctx);
}
void qspi_flash_write_status_register(qspi_flash_ctx_t *ctx,
const uint8_t *val,
size_t len)
{
#if QSPI_FLASH_SANITY_CHECKS
uint8_t status_reg;
qspi_flash_read_status_register(ctx, &status_reg, 1);
xassert(status_reg & QSPI_FLASH_STATUS_REG_WEL_BM);
#endif
qspi_flash_write_register(ctx, WRITE_STATUS_REG_COMMAND, val, len);
}
void qspi_flash_read_register(qspi_flash_ctx_t *ctx,
uint32_t cmd,
uint8_t *val,
size_t len)
{
qspi_io_ctx_t *qspi_io_ctx = &ctx->qspi_io_ctx;
size_t cycles = 8 + /* 8 cycles for the command */
8 * len; /* 8 cycles per byte */
qspi_io_start_transaction(qspi_io_ctx, cmd, cycles, qspi_io_spi_read);
qspi_io_sio_direction_input(qspi_io_ctx);
qspi_io_miso_in(qspi_io_ctx, qspi_io_transfer_normal, val,
8 + /* 8 cycles for the command */
7, /* input on the last cycle of the first byte */
len);
// }
qspi_io_end_transaction(qspi_io_ctx);
}
void qspi_flash_read_status_register(qspi_flash_ctx_t *ctx,
uint8_t *val,
size_t len)
{
qspi_flash_read_register(ctx, READ_STATUS_REG_COMMAND, val, len);
}
void qspi_flash_read_id(qspi_flash_ctx_t *ctx,
uint8_t *val,
size_t len)
{
qspi_flash_read_register(ctx, READ_ID_COMMAND, val, len);
}
void qspi_flash_poll_register(qspi_flash_ctx_t *ctx,
uint32_t cmd,
const uint8_t mask,
const uint8_t val)
{
qspi_io_ctx_t *qspi_io_ctx = &ctx->qspi_io_ctx;
size_t cycles = 8 + /* 8 cycles for the command */
8 * 2; /* Read the register at least twice */
qspi_io_start_transaction(qspi_io_ctx, cmd, cycles, qspi_io_spi_read);
qspi_io_sio_direction_input(qspi_io_ctx);
qspi_io_miso_poll(qspi_io_ctx, mask, val,
8 + /* 8 cycles for the command */
7); /* input on the last cycle of the first byte */
qspi_io_end_transaction(qspi_io_ctx);
}
void qspi_flash_poll_status_register(qspi_flash_ctx_t *ctx,
const uint8_t mask,
const uint8_t val)
{
qspi_flash_poll_register(ctx, READ_STATUS_REG_COMMAND, mask, val);
}
__attribute__((always_inline))
static void qspi_flash_fast_read_i(qspi_flash_ctx_t *ctx,
uint32_t cmd,
uint8_t *data,
uint32_t address,
size_t len)
{
qspi_io_ctx_t *qspi_io_ctx = &ctx->qspi_io_ctx;
uint8_t *address_bytes;
size_t cycles = 8 + /* 8 cycles for the command */
24 + /* 24 cycles for the address */
FAST_READ_DUMMY_CYCLES + /* dummy cycles */
8 * len; /* 8 cycles per byte */
size_t input_cycle = 8 + /* 8 cycles for the command */
24 + /* 24 cycles for the address */
FAST_READ_DUMMY_CYCLES + /* dummy cycles */
7; /* input on the last cycle of the first byte */
/*
* Manipulate the address so that in memory it is:
* {byte 2, byte 1, byte 0, XX}
* it will get sent out as 3 bytes.
*/
address = byterev(address << 8);
address_bytes = (uint8_t *) &address;
qspi_io_start_transaction(qspi_io_ctx, cmd, cycles, qspi_io_full_speed);
qspi_io_mosi_out(qspi_io_ctx, qspi_io_transfer_normal, address_bytes, 3);
qspi_io_sio_direction_input(qspi_io_ctx);
qspi_io_miso_in(qspi_io_ctx, qspi_io_transfer_normal, data, input_cycle, len);
qspi_io_end_transaction(qspi_io_ctx);
}
void qspi_flash_fast_read(qspi_flash_ctx_t *ctx,
uint8_t *data,
uint32_t address,
size_t len)
{
qspi_flash_ctx_t local_ctx = *ctx;
qspi_flash_fast_read_i(&local_ctx, QSPI_IO_BYTE_TO_MOSI(FAST_READ_COMMAND), data, address, len);
}
__attribute__ ((noinline))
static void qspi_flash_read_calc(const int xip,
#if FOUR_BYTE_ADDRESS_SUPPORT
const int four_byte_address,
#endif
uint32_t *address,
size_t len,
size_t *cycles,
size_t *input_cycle)
{
/* The first input should occur on either the fourth
* byte, or the last byte, whichever is first. */
const size_t first_input_byte = len > 4 ? 4 : len;
#if FOUR_BYTE_ADDRESS_SUPPORT
if (xip) {
*cycles = (four_byte_address ? 8 : 6) + /* 6 or 8 cycles for address */
QUAD_IO_READ_DUMMY_CYCLES + /* dummy cycles */
2 * len; /* 2 cycles per byte */
*input_cycle = (four_byte_address ? 8 : 6) + /* 6 or 8 cycles for address */
QUAD_IO_READ_DUMMY_CYCLES + /* dummy cycles */
2 * first_input_byte - 1; /* input on the last cycle of the first input byte */
} else {
*cycles = 8 + /* 8 cycles each for command */
(four_byte_address ? 8 : 6) + /* 6 or 8 cycles for address */
QUAD_IO_READ_DUMMY_CYCLES + /* dummy cycles */
2 * len; /* 2 cycles per byte */
*input_cycle = 8 + /* 8 cycles each for command */
(four_byte_address ? 8 : 6) + /* 6 or 8 cycles for address */
QUAD_IO_READ_DUMMY_CYCLES + /* dummy cycles */
2 * first_input_byte - 1; /* input on the last cycle of the first input byte */
}
#else
if (xip) {
*cycles = 8 + /* 8 cycles for address */
QUAD_IO_READ_DUMMY_CYCLES + /* dummy cycles */
2 * len; /* 2 cycles per byte */
*input_cycle = 8 + /* 8 cycles for address */
QUAD_IO_READ_DUMMY_CYCLES + /* dummy cycles */
2 * first_input_byte - 1; /* input on the last cycle of the first input byte */
} else {
*cycles = 8 * 2 + /* 8 cycles each for command and address */
QUAD_IO_READ_DUMMY_CYCLES + /* dummy cycles */
2 * len; /* 2 cycles per byte */
*input_cycle = 8 * 2 + /* 8 cycles each for command and address */
QUAD_IO_READ_DUMMY_CYCLES + /* dummy cycles */
2 * first_input_byte - 1; /* input on the last cycle of the first input byte */
}
#endif
#if FOUR_BYTE_ADDRESS_SUPPORT
if (!four_byte_address) {
#endif
/*
* The address is really contained in the upper 24 bits.
* The lower 8 bits are essentially 2 dummy cycles.
* Rotate, such that the MSB of address is sent out during
* the first two dummy cycles. Some flashes use this to
* enter "performance" or "XIP" mode.
*/
*address = (*address << 8) | (*address >> 24);
#if FOUR_BYTE_ADDRESS_SUPPORT
}
#endif
}
__attribute__((always_inline))
inline void qspi_flash_read_i(qspi_flash_ctx_t *ctx,
const qspi_io_transfer_mode_t transfer_mode,
const int xip,
#if FOUR_BYTE_ADDRESS_SUPPORT
const int four_byte_address,
#endif
uint8_t *data,
uint32_t address,
size_t len)
{
qspi_io_ctx_t *qspi_io_ctx = &ctx->qspi_io_ctx;
size_t cycles;
size_t input_cycle;
qspi_flash_read_calc(xip,
#if FOUR_BYTE_ADDRESS_SUPPORT
four_byte_address,
#endif
&address,
len,
&cycles,
&input_cycle);
if (xip) {
qspi_io_start_transaction(qspi_io_ctx, address, cycles, qspi_io_full_speed);
} else {
qspi_io_start_transaction(qspi_io_ctx, QUAD_IO_READ_COMMAND, cycles, qspi_io_full_speed);
qspi_io_words_out(qspi_io_ctx, qspi_io_transfer_normal, &address, 1);
}
#if FOUR_BYTE_ADDRESS_SUPPORT
if (four_byte_address) {
uint8_t mode = 0xFF;
qspi_io_bytes_out(qspi_io_ctx, transfer_mode, &mode, 1);
}
#endif
qspi_io_sio_direction_input(qspi_io_ctx);
qspi_io_bytes_in(qspi_io_ctx, transfer_mode, data, input_cycle, len);
qspi_io_end_transaction(qspi_io_ctx);
}
void qspi_flash_read(qspi_flash_ctx_t *ctx,
uint8_t *data,
uint32_t address,
size_t len)
{
qspi_flash_ctx_t local_ctx = *ctx;
qspi_flash_read_i(&local_ctx, qspi_io_transfer_normal, 0,
#if FOUR_BYTE_ADDRESS_SUPPORT
0,
#endif
data, address, len);
}
void qspi_flash_read_nibble_swapped(qspi_flash_ctx_t *ctx,
uint8_t *data,
uint32_t address,
size_t len)
{
qspi_flash_ctx_t local_ctx = *ctx;
qspi_flash_read_i(&local_ctx, qspi_io_transfer_nibble_swap, 0,
#if FOUR_BYTE_ADDRESS_SUPPORT
0,
#endif
data, address, len);
}
void qspi_flash_xip_read(qspi_flash_ctx_t *ctx,
uint8_t *data,
uint32_t address,
size_t len)
{
qspi_flash_ctx_t local_ctx = *ctx;
qspi_flash_read_i(&local_ctx, qspi_io_transfer_normal, 1,
#if FOUR_BYTE_ADDRESS_SUPPORT
0,
#endif
data, address, len);
}
void qspi_flash_xip_read_nibble_swapped(qspi_flash_ctx_t *ctx,
uint8_t *data,
uint32_t address,
size_t len)
{
qspi_flash_ctx_t local_ctx = *ctx;
qspi_flash_read_i(&local_ctx, qspi_io_transfer_nibble_swap, 1,
#if FOUR_BYTE_ADDRESS_SUPPORT
0,
#endif
data, address, len);
}
__attribute__((always_inline))
inline void qspi_flash_write_i(qspi_flash_ctx_t *ctx,
const qspi_io_transfer_mode_t transfer_mode,
const uint8_t *data,
uint32_t address,
size_t len)
{
qspi_io_ctx_t *qspi_io_ctx = &ctx->qspi_io_ctx;
uint8_t *address_bytes;
uint32_t pp_cmd;
size_t cycles;
#if QSPI_FLASH_SANITY_CHECKS
uint8_t status_reg;
qspi_flash_read_status_register(ctx, &status_reg, 1);
xassert(status_reg & QSPI_FLASH_STATUS_REG_WEL_BM);
#endif
switch (ctx->quad_page_program_cmd) {
case qspi_flash_page_program_1_1_4:
pp_cmd = PP_1_1_4_COMMAND;
cycles = 8 + /* 8 cycles for command */
24 + /* 24 cycles for address */
2 * len; /* 2 cycles per byte */
break;
case qspi_flash_page_program_1_4_4:
pp_cmd = PP_1_4_4_COMMAND;
cycles = 8 + /* 8 cycles for command */
6 + /* 6 cycles for address */
2 * len; /* 2 cycles per byte */
break;
case qspi_flash_page_program_1_1_1:
default:
pp_cmd = PP_1_1_1_COMMAND;
cycles = 8 + /* 8 cycles for command */
24 + /* 24 cycles for address */
8 * len; /* 8 cycles per byte */
break;
}
/*
* Manipulate the address so that in memory it is:
* {byte 2, byte 1, byte 0, XX}
* it will get sent out as 3 bytes.
*/
address = byterev(address << 8);
address_bytes = (uint8_t *) &address;
qspi_io_start_transaction(qspi_io_ctx, pp_cmd, cycles, qspi_io_full_speed);
switch (ctx->quad_page_program_cmd) {
case qspi_flash_page_program_1_1_4:
qspi_io_mosi_out(qspi_io_ctx, qspi_io_transfer_normal, address_bytes, 3);
qspi_io_bytes_out(qspi_io_ctx, transfer_mode, data, len);
break;
case qspi_flash_page_program_1_4_4:
qspi_io_bytes_out(qspi_io_ctx, qspi_io_transfer_normal, address_bytes, 3);
qspi_io_bytes_out(qspi_io_ctx, transfer_mode, data, len);
break;
case qspi_flash_page_program_1_1_1:
default:
qspi_io_mosi_out(qspi_io_ctx, qspi_io_transfer_normal, address_bytes, 3);
qspi_io_mosi_out(qspi_io_ctx, transfer_mode, data, len);
break;
}
qspi_io_end_transaction(qspi_io_ctx);
}
void qspi_flash_write(qspi_flash_ctx_t *ctx,
const uint8_t *data,
uint32_t address,
size_t len)
{
qspi_flash_ctx_t local_ctx = *ctx;
qspi_flash_write_i(&local_ctx, qspi_io_transfer_normal, data, address, len);
}
void qspi_flash_write_nibble_swapped(qspi_flash_ctx_t *ctx,
const uint8_t *data,
uint32_t address,
size_t len)
{
qspi_flash_ctx_t local_ctx = *ctx;
qspi_flash_write_i(&local_ctx, qspi_io_transfer_nibble_swap, data, address, len);
}
SFDP_READ_CALLBACK_ATTR
void qspi_flash_sfdp_read(qspi_flash_ctx_t *ctx,
uint8_t *data,
uint32_t address,
size_t len)
{
qspi_flash_ctx_t local_ctx = *ctx;
qspi_flash_fast_read_i(&local_ctx, QSPI_IO_BYTE_TO_MOSI(SFDP_READ_INSTRUCTION), data, address, len);
}
void qspi_flash_deinit(qspi_flash_ctx_t *ctx)
{
qspi_io_ctx_t *qspi_io_ctx = &ctx->qspi_io_ctx;
qspi_io_deinit(qspi_io_ctx);
}
void qspi_flash_init(qspi_flash_ctx_t *ctx)
{
sfdp_info_t sfdp_info;
qspi_io_ctx_t *qspi_io_ctx = &ctx->qspi_io_ctx;
if (!ctx->custom_clock_setup) {
ctx->source_clock = qspi_io_source_clock_ref;
/* 100 / (2 * 2) = 25 MHz */
qspi_io_ctx->full_speed_clk_divisor = 2;
qspi_io_ctx->full_speed_sclk_sample_delay = 0;
qspi_io_ctx->full_speed_sclk_sample_edge = qspi_io_sample_edge_falling;
qspi_io_ctx->full_speed_sio_pad_delay = 0;
/* 100 / (2 * 2) = 25 MHz */
qspi_io_ctx->spi_read_clk_divisor = 2;
qspi_io_ctx->spi_read_sclk_sample_delay = 0;
qspi_io_ctx->spi_read_sclk_sample_edge = qspi_io_sample_edge_falling;
qspi_io_ctx->spi_read_sio_pad_delay = 0;
}
/* configure the QSPI I/O interface */
qspi_io_init(qspi_io_ctx, ctx->source_clock);
if ((ctx->sfdp_skip == false) && sfdp_discover(&sfdp_info, ctx, (sfdp_read_cb_t) qspi_flash_sfdp_read)) {
int ret;
int erase_table_entries;
uint8_t read_instruction;
uint8_t write_instruction;
ctx->sfdp_supported = true;
/* Parameters from SFDP used:
* 1) Flash size.
* 2) Page size.
* 3) Address bytes - 3, 4, or both
* Set the "current" address bytes to 3 if it's 3 only.
* Otherwise set to 4.
* If both modes are allowed, then should switch to 4 byte mode.
* 4) Supports_144_fast_read. This is required. Ensure that its command
* is 0xEB.
* 5) Ensure that the quad i/o read's mode plus dummy clocks equals 6.
* 6) All the erase sizes and commands. Sort them and save to a table
* inside the flash ctx.
* 7) The busy poll method.
* 8) The quad enable method.
*
* TODO:
* 9) If XIP mode is supported, The XIP entry/exit methods and implement them.
* Should have xip enter/xip exit functions. Reads will need issue the
* proper mode bits. Continue to use the xip read function?
*/
/* Verify that the QSPI flash chip supports quad I/O read mode with 6 dummy cycles */
xassert(sfdp_info.basic_parameter_table.supports_144_fast_read && "Quad I/O Read mode support is required");
xassert(sfdp_info.basic_parameter_table.quad_144_read_cmd == QUAD_IO_READ_CMD_VAL && "Unsupported Quad I/O Read command");
xassert(sfdp_info.basic_parameter_table.quad_144_read_mode_clocks + sfdp_info.basic_parameter_table.quad_144_read_dummy_clocks == 6 && "Unsupported number of dummy clocks");
/* Save the page and flash sizes. Calculate the page count */
ctx->page_size_bytes = sfdp_flash_page_size_bytes(&sfdp_info);
ctx->flash_size_kbytes = sfdp_flash_size_kbytes(&sfdp_info);
if (ctx->flash_size_kbytes) {
ctx->page_count = (ctx->flash_size_kbytes >> sfdp_info.basic_parameter_table.page_size) << 10;
}
xassert(ctx->flash_size_kbytes != 0 && "Unsupported flash size");
/* Save the supported busy poll method */
ret = sfdp_busy_poll_method(&sfdp_info, &read_instruction, &ctx->busy_poll_bit, &ctx->busy_poll_ready_value);
if (ret == 0) {
ctx->busy_poll_cmd = QSPI_IO_BYTE_TO_MOSI(read_instruction);
}
xassert(ret == 0 && "Unsupported busy poll method");
/* Save the supported quad enable method */
ret = sfdp_quad_enable_method(&sfdp_info, &ctx->qe_reg, &ctx->qe_bit, &read_instruction, &write_instruction);
if (ret == 0) {
ctx->sr2_read_cmd = QSPI_IO_BYTE_TO_MOSI(read_instruction);
ctx->sr2_write_cmd = QSPI_IO_BYTE_TO_MOSI(write_instruction);
}
xassert(ret == 0 && "Unsupported QE enable method");
/* Parse and save the erase table */
erase_table_entries = 0;
for (int i = 0; i < 4; i++) {
if (sfdp_info.basic_parameter_table.erase_info[i].size != 0) {
ctx->erase_info[erase_table_entries].size_log2 = sfdp_info.basic_parameter_table.erase_info[i].size;
ctx->erase_info[erase_table_entries].cmd = QSPI_IO_BYTE_TO_MOSI(sfdp_info.basic_parameter_table.erase_info[i].cmd);
} else {
ctx->erase_info[erase_table_entries].size_log2 = 0;
}
erase_table_entries++;
}
xassert(erase_table_entries > 0 && "Erase table found in SFDP is empty!");
/* Determine the number of address bytes. If 4 byte mode is available, switch to it */
switch (sfdp_info.basic_parameter_table.address_bytes) {
case sfdp_3_or_4_byte_address:
ctx->address_bytes = 3; break; /* leave it in 3 byte address mode for now */
/* TODO: enable 4 byte address mode now and fall thru to next case */
// @suppress("No break at end of case")
case sfdp_4_byte_address:
ctx->address_bytes = 4;
xassert(0 && "4 byte address mode entry not yet implemented");
break;
case sfdp_3_byte_address:
default:
ctx->address_bytes = 3;
break;
}
} else {
ctx->sfdp_supported = false;
xassert((ctx->address_bytes == 3 || ctx->address_bytes == 4) && ctx->busy_poll_bit <= 7 && (ctx->busy_poll_ready_value == 0 || ctx->busy_poll_ready_value == 1));
}
}

View File

@@ -1,88 +0,0 @@
// Copyright 2020-2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <stdint.h>
#include "qspi_io.h"
void qspi_io_deinit(const qspi_io_ctx_t *ctx)
{
port_disable(ctx->cs_port);
port_disable(ctx->sio_port);
port_reset(ctx->sclk_port);
port_start_buffered(ctx->sclk_port,32);
clock_disable(ctx->clock_block);
}
void qspi_io_init(const qspi_io_ctx_t *ctx,
qspi_io_source_clock_t source_clock)
{
/* Setup the clock block */
clock_enable(ctx->clock_block);
if (source_clock == qspi_io_source_clock_ref) {
clock_set_source_clk_ref(ctx->clock_block);
} else {
clock_set_source_clk_xcore(ctx->clock_block);
}
/* Setup the chip select port */
port_enable(ctx->cs_port);
port_set_clock(ctx->cs_port, ctx->clock_block);
/*
* CS is used internally as the ready signal for SIO, so it must be
* driven high when it is asserted. However, it must be active low
* on the chip pin itself for the external QSPI device. Therefore the
* CS port is put into invert mode.
* NOTE: invert mode is not modeled correctly in xsim VCD trace.
*/
port_set_invert(ctx->cs_port);
/* Set chip select as the ready source for the clock */
clock_set_ready_src(ctx->clock_block, ctx->cs_port);
/* Setup the SIO port */
port_enable(ctx->sio_port);
/*
* Ensure SIO begins outputing high on all lines.
* This requires an active clock.
*/
port_set_clock(ctx->sio_port, XS1_CLKBLK_REF);
port_out(ctx->sio_port, 0xF);
port_sync(ctx->sio_port);
/* Now set SIO to use the desired clock block. */
port_set_clock(ctx->sio_port, ctx->clock_block);
/*
* Always sample on the falling edge. This allows for
* faster SCLK frequencies, but in general works with
* any frequency that meets timing. This also ensures
* that the internal CS ready signal is captured on time
* at higher frequencies, so is important both when SIO
* is input and output.
*/
port_set_sample_falling_edge(ctx->sio_port);
/*
* SIO is put into strobed slave mode. CS is already
* setup as the ready signal for SCLK. This ensures that
* the data does not begin shifting out out until CS
* is asserted.
*/
port_set_buffered(ctx->sio_port);
port_set_transfer_width(ctx->sio_port, 32);
port_set_ready_strobed(ctx->sio_port);
port_set_slave(ctx->sio_port);
/* Ensure the buffer is clear before the first transaction. */
port_clear_buffer(ctx->sio_port);
/* Setup the SCLK port */
port_enable(ctx->sclk_port);
port_set_clock(ctx->sclk_port, ctx->clock_block);
port_set_out_clock(ctx->sclk_port);
}

View File

@@ -1,168 +0,0 @@
// Copyright 2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#define DEBUG_UNIT SFDP
#include "sfdp.h"
size_t sfdp_flash_size_kbytes(sfdp_info_t *sfdp_info)
{
size_t flash_size_kbytes;
if (sfdp_info->basic_parameter_table.memory_density_is_exponent) {
if (sfdp_info->basic_parameter_table.memory_density >=32 && sfdp_info->basic_parameter_table.memory_density <= 44) {
flash_size_kbytes = 1 << (sfdp_info->basic_parameter_table.memory_density - 13);
} else {
flash_size_kbytes = 0;
}
} else {
flash_size_kbytes = (1 + sfdp_info->basic_parameter_table.memory_density) >> 13;
}
return flash_size_kbytes;
}
size_t sfdp_flash_page_size_bytes(sfdp_info_t *sfdp_info)
{
return 1 << sfdp_info->basic_parameter_table.page_size;
}
int sfdp_busy_poll_method(sfdp_info_t *sfdp_info,
uint8_t *instruction,
uint8_t *bit,
uint8_t *ready_value)
{
uint32_t method_set = sfdp_info->basic_parameter_table.busy_poll_methods;
if (method_set & SFDP_BUSY_POLL_ALT1_BM) {
*instruction = 0x70;
*bit = 7;
*ready_value = 1;
} else if (method_set & SFDP_BUSY_POLL_LEGACY_BM) {
*instruction = 0x05;
*bit = 0;
*ready_value = 0;
} else {
return -1;
}
return 0;
}
int sfdp_quad_enable_method(sfdp_info_t *sfdp_info,
uint8_t *qe_reg,
uint8_t *qe_bit,
uint8_t *sr2_read_instruction,
uint8_t *sr2_write_instruction)
{
switch (sfdp_info->basic_parameter_table.quad_enable_method) {
case 0:
*qe_reg = 0;
*qe_bit = 0;
*sr2_read_instruction = 0;
*sr2_write_instruction = 0;
break;
case 1:
*qe_reg = 2;
*qe_bit = 1;
*sr2_read_instruction = 0;
*sr2_write_instruction = 0;
break;
case 2:
*qe_reg = 1;
*qe_bit = 6;
*sr2_read_instruction = 0;
*sr2_write_instruction = 0;
break;
case 3:
*qe_reg = 2;
*qe_bit = 7;
*sr2_read_instruction = 0x3F;
*sr2_write_instruction = 0x3E;
break;
case 4:
*qe_reg = 2;
*qe_bit = 1;
*sr2_read_instruction = 0;
*sr2_write_instruction = 0;
break;
case 5:
*qe_reg = 2;
*qe_bit = 1;
*sr2_read_instruction = 0x35;
*sr2_write_instruction = 0;
break;
case 6:
*qe_reg = 2;
*qe_bit = 1;
*sr2_read_instruction = 0x35;
*sr2_write_instruction = 0x31;
break;
default:
return -1;
}
return 0;
}
static void sfdp_erase_table_sort(sfdp_info_t *sfdp_info)
{
sfdp_parameter_table_t *t = &sfdp_info->basic_parameter_table;
const int n = 4;
int i, j;
for (i = 0; i < n - 1; i++) {
for (j = 0; j < n - i - 1; j++) {
/* Treat size 0 as a maximum value to keep them at the end of the table */
if (t->erase_info[j].size == 0 || (t->erase_info[j + 1].size != 0 && t->erase_info[j].size > t->erase_info[j + 1].size)) {
uint8_t size = t->erase_info[j].size;
uint8_t cmd = t->erase_info[j].cmd;
t->erase_info[j].size = t->erase_info[j + 1].size;
t->erase_info[j].cmd = t->erase_info[j + 1].cmd;
t->erase_info[j + 1].size = size;
t->erase_info[j + 1].cmd = cmd;
}
}
}
}
bool sfdp_discover(sfdp_info_t *sfdp_info,
void *serial_flash_ctx,
SFDP_READ_CALLBACK_ATTR sfdp_read_cb_t sfdp_read)
{
const uint32_t sfdp_signature = 0x50444653;
const uint8_t req_major_revision = 1;
const uint8_t req_min_minor_revision = 5;
size_t table_read_length;
sfdp_read(serial_flash_ctx, sfdp_info, 0x000000, sizeof(sfdp_header_t) + sizeof(sfdp_parameter_header_t));
table_read_length = sizeof(uint32_t) * sfdp_info->basic_parameter_header.length;
if (sfdp_info->sfdp_header.signature == sfdp_signature &&
sfdp_info->sfdp_header.major_revision == req_major_revision &&
sfdp_info->basic_parameter_header.major_revision == req_major_revision &&
sfdp_info->sfdp_header.minor_revision >= req_min_minor_revision &&
sfdp_info->basic_parameter_header.minor_revision >= req_min_minor_revision &&
table_read_length >= sizeof(sfdp_parameter_table_t)) {
// debug_printf("Supported SFDP flash device found\n");
} else {
if (sfdp_info->sfdp_header.signature != sfdp_signature) {
// debug_printf("No SFDP flash device found\n");
} else {
// debug_printf("Unsupported SFDP flash device found\n");
}
return false;
}
if (sizeof(sfdp_parameter_table_t) < table_read_length) {
table_read_length = sizeof(sfdp_parameter_table_t);
}
sfdp_read(serial_flash_ctx, &sfdp_info->basic_parameter_table, sfdp_info->basic_parameter_header.table_address, table_read_length);
/* Ensure that the erase table is sorted by size, with unused entries at the end. */
sfdp_erase_table_sort(sfdp_info);
return true;
}

View File

@@ -21,19 +21,13 @@ extern void SetEqDataChan (chanend c);
/* I2C interface ports */
extern port p_scl;
extern port p_sda;
extern void i2c_control_task(void);
extern int dsp_worker_tile(chanend c_dsp_to_ex3d, int worker_id);
//extern int dsp_worker_tile_1(chanend c_dsp_to_ex3d, int worker_id);
extern void ex3d_task();
extern void hid_button_task(chanend cc_mic_level, chanend c_hid, chanend c_hidSendData, chanend c_uac_vol);
extern void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol);
#if AIZIP_DNR == 1
extern void dnr_dsp_buffer_task(chanend cc_dsp_in, chanend cc_dsp_eof, chanend cc_mic_level);
extern void dnr_dsp_proc_task(chanend cc_dsp_eof);
#else
//#define dnr_dsp_buffer_task(cc_dsp_in, cc_dsp_eof, cc_mic_level)
//#define dnr_dsp_proc_task(cc_dsp_eof)
#endif
extern void dnr_dsp_proc_task(void);
//XUA_DFU_EN do i need it?
@@ -130,6 +124,8 @@ extern void key_receiver(chanend c_key);
{ dsp_core0(); } \
}\
on tile[0]: {dsp_main(c_eq_data); } \
on tile[0]: {dnr_dsp_proc_task(); } \
#endif // AIZIP_DNR