简体   繁体   English

fmodf() 是否会导致 stm32 出现硬故障?

[英]Does fmodf() cause a hardfault in stm32?

I am trying to create a modulated waveform out of 2 sine waves.我正在尝试从 2 个正弦波中创建一个调制波形。 To do this I need the modulo(fmodf) to know what amplitude a sine with a specific frequency(lo_frequency) has at that time(t).为此,我需要模(fmodf)来知道具有特定频率(lo_frequency)的正弦在当时(t)的幅度。 But I get a hardfault when the following line is executed:但是当执行以下行时,我遇到了硬故障:

j = fmodf(2 * PI * lo_frequency * t, 2 * PI);

Do you have an idea why this gives me a hardfault ?你知道为什么这会给我一个硬故障吗?

Edit 1:编辑1:

I exchanged fmodf with my_fmodf:我用 my_fmodf 交换了 fmodf:

float my_fmodf(float x, float y){
    if(y == 0){
        return 0;
    }
    float n = x / y;
    return x - n * y;
}

But still the hardfault occurs, and when I debug it it doesn't even jump into this function(my_fmodf).但是仍然发生了硬故障,当我调试它时,它甚至没有跳入这个函数(my_fmodf)。

Heres the whole function in which this error occurs:这是发生此错误的整个函数:

int* create_wave(int* message){
    /* Mixes the message signal at 10kHz and the carrier at 40kHz.
     * When a bit of the message is 0 the amplitude is lowered to 10%.
     * When a bit of the message is 1 the amplitude is 100%.
     * The output of the STM32 can't be negative, thats why the wave swings between
     * 0 and 256 (8bit precision for faster DAC)
     */
    static int rf_frequency = 10000;
    static int lo_frequency = 40000;
    static int sample_rate = 100000;
    int output[sample_rate];
    int index, mix;
    float j, t;
    for(int i = 0; i <= sample_rate; i++){
        t = i * 0.00000001f; // i * 10^-8
        j = my_fmodf(2 * PI * lo_frequency * t, 2 * PI);

        if (j < 0){
            j += (float) 2 * PI;
        }
        index = floor((16.0f / (lo_frequency/rf_frequency * 0.0001f)) * t);
        if (index < 16) {
            if (!message[index]) {
                mix = 115 + sin1(j) * 0.1f;
            } else {
                mix = sin1(j);
            }
        } else {
            break;
        }
        output[i] = mix;
    }
    return output;
}

Edit 2:编辑2:

I fixed the warning: function returns address of local variable [-Wreturn-local-addr] the way "chux - Reinstate Monica" suggested.我修复了警告:函数以“chux - Reinstate Monica”建议的方式返回局部变量 [-Wreturn-local-addr] 的地址。

int* create_wave(int* message){
    static uint16_t rf_frequency = 10000;
    static uint32_t lo_frequency = 40000;
    static uint32_t sample_rate = 100000;
    int *output = malloc(sizeof *output * sample_rate);
    uint8_t index, mix;
    float j, n, t;
    for(int i = 0; i < sample_rate; i++){
        t = i * 0.00000001f; // i * 10^-8
        j = fmodf(2 * PI * lo_frequency * t, 2 * PI);
        if (j < 0){
            j += 2 * PI;
        }
        index = floor((16.0f / (lo_frequency/rf_frequency * 0.0001f)) * t);
        if (index < 16) {
            if (!message[index]) {
                mix = (uint8_t) floor(115 + sin1(j) * 0.1f);
            } else {
                mix = sin1(j);
            }
        } else {
            break;
        }
        output[i] = mix;
    }
    return output;
}

But now I get the hardfault on this line:但是现在我在这条线上遇到了硬故障:

output[i] = mix;

EDIT 3:编辑 3:

Because the previous code contained a very large buffer array that did not fit into the 16KB SRAM of the STM32F303K8 I needed to change it.由于之前的代码包含一个非常大的缓冲区数组,无法放入 STM32F303K8 的 16KB SRAM,因此我需要对其进行更改。

Now I use a "ping-pong" buffer where I use the callback of the DMA for "first-half-transmitted" and "completly-transmitted":现在我使用一个“乒乓”缓冲区,在那里我将 DMA 的回调用于“前半传输”和“完全传输”:

void HAL_DAC_ConvHalfCpltCallbackCh1(DAC_HandleTypeDef * hdac){
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET);
    for(uint16_t i = 0; i < 128; i++){
        new_value = sin_table[(i * 8) % 256];
        if (message[message_index] == 0x0){
            dac_buf[i] = new_value * 0.1f + 115;
        } else {
            dac_buf[i] = new_value;
        }
    }
}

void HAL_DAC_ConvCpltCallbackCh1 (DAC_HandleTypeDef * hdac){
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET);
    for(uint16_t i = 128; i < 256; i++){
        new_value = sin_table[(i * 8) % 256];
        if (message[message_index] == 0x0){
            dac_buf[i] = new_value * 0.1f + 115;
        } else {
            dac_buf[i] = new_value;
        }
    }
    message_index++;
    if (message_index >= 16) {
        message_index = 0;
        // HAL_DAC_Stop_DMA (&hdac1, DAC_CHANNEL_1);
    }
}

And it works the way I wanted:它以我想要的方式工作: 输出

But the frequency of the created sine is too low.但是创建的正弦频率太低。 I cap at around 20kHz but I'd need 40kHz.我的上限在 20kHz 左右,但我需要 40kHz。 I allready increased the clock by a factor of 8 so that one is maxed out:我已经将时钟增加了 8 倍,以便达到最大值: 最大 . . I can still decrease the counter period (it is 50 at the moment), but when I do so the interrupt callback seems to take longer than the period to the next one.我仍然可以减少计数器周期(目前是 50),但是当我这样做时,中断回调似乎比下一个周期花费的时间更长。 At least it seems so as the output becomes very distorted when I do that.至少看起来是这样,因为当我这样做时输出变得非常扭曲。

I also tried to decrease the precision by taking only every 8th sine value but I cant do this any more because then the output does not look like a sine wave anymore.我还试图通过只取每 8 个正弦值来降低精度,但我不能再这样做了,因为这样输出看起来不再像正弦波了。

Any ideas how I could optimize the callback so that it takes less time ?有什么想法可以优化回调以减少时间吗? Any other ideas ?还有其他想法吗?

Does fmodf() cause a hardfault in stm32? fmodf() 是否会导致 stm32 出现硬故障?

It is other code problems causing the hard fault here.这是导致硬故障的其他代码问题。

Failing to compile with ample warnings编译失败并发出大量警告

Best code tip: enable all warnings.最佳代码提示:启用所有警告。 @KamilCuk @卡米尔库克
Faster feedback than Stackoverflow.比 Stackoverflow 更快的反馈。

I'd expect something like below on a well enabled compiler.我希望在启用良好的编译器上有类似下面的内容。

return output;
warning: function returns address of local variable [-Wreturn-local-addr]

Returning a local Object返回本地对象

Cannot return a local array.无法返回本地数组。 Allocate instead.改为分配。

// int output[sample_rate];
int *output = malloc(sizeof *output * sample_rate);
return output;

Calling code will need to free() the pointer.调用代码需要free()指针。

Out of range array access超出范围的数组访问

static int sample_rate = 100000;
int output[sample_rate];

// for(int i = 0; i <= sample_rate; i++){
for(int i = 0; i < sample_rate; i++){
    ...
    output[i] = mix;
}

Stack overflow?堆栈溢出?

static int sample_rate = 100000; int output[sample_rate]; is a large local variable.是一个大的局部变量。 Maybe allocate or try something smaller?也许分配或尝试更小的东西?

Advanced: loss of precision高级:精度损失

A good fmodf() does not lose precision.好的fmodf()不会丢失精度。 For a more precise answer consider double math for the intermediate results.要获得更精确的答案,请考虑中间结果的double数学。 An even better approach is more involved.更好的方法涉及更多。

float my_fmodf(float x, float y){
    if(y == 0){
        return 0;
    }
    double n = 1.0 * x / y;
    return (float) (x - n * y);
}

Can I not use any function within another ?我不能在另一个函数中使用任何函数吗?

Yes.是的。 Code has other issues.代码有其他问题。

1 value every 10uS makes only 100kSPS whis is not too much for this macro.每 10uS 1 个值仅产生 100kSPS,这对于这个宏来说不算太多。 In my designs I generate > 5MSPS signals without any problems.在我的设计中,我可以毫无问题地生成 > 5MSPS 的信号。 Usually I have one buffer and DMA in circular mode.通常我在循环模式下有一个缓冲区和 DMA。 First I fill the buffer and start generation.首先我填充缓冲区并开始生成。 When the half transmition DMA interrupt is trigerred I fill the first half of the buffer with fresh data.当触发半传输 DMA 中断时,我用新数据填充缓冲区的前半部分。 The the transmition complete interrupt is trigerred I fill the second half and this process repeats all over again.传输完成中断被触发,我填充了下半部分,这个过程再次重复。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM