Implement FIR filter with the specified coefficients. Configure the ADC in 12-bit right-aligned, single- channel, continuous conversion mode. Enable channel 2 of the microcontroller DAC. Configure timer TIM7 to generate interrupts with the specified sampling rate fs. In TIM7 period-elapsed ISR get the ADC conversion result, calculate convolution sum to determine your filter output, and update DAC data register with the result. Set the function generator to generate 0-3V peak-to-peak (positively shifted 1.5V DC) sinusoidal signal with the frequency of 100 Hz.

Before connecting a function generator to your development kit, connect the output of the function generator directly to the oscilloscope and verify that your signal is 0-3V peak-to-peak, positively shifted (1.5V DC) sine wave with the specified frequency.
Connect the output of the function generator to the ADC input via 1k resistor. Run the program and observe the DAC output with an oscilloscope.
Increase the input frequency with 100 Hz increment up to 4 kHz and determine the frequencies corresponding to –3 dB and –6 dB attenuation. In TIM7 ISR set PG2 pin before starting the computation of the filter output and reset it in the end of the timer ISR. Observe the state of the GPIO pin PG2 with an oscilloscope to determine computation time Tcomp.

To implement the FIR filter with the specified coefficients and other configurations, follow the steps below:

1. Include required header files:

```c
#include "stm32fxxx.h"
#include "stm32fxxx_hal.h"
#include "stm32fxxx_hal_adc.h"
#include "stm32fxxx_hal_dac.h"
#include "stm32fxxx_hal_tim.h"
```

2. Define filter coefficients and global variables for ADC and FIR calculations:

```c
#define N_COEFFS 32 // Number of filter coefficients, change based on your requirement
float32_t coeffs[N_COEFFS] = { /* Your filter coefficients */ };
volatile uint32_t adc_values[N_COEFFS] = { 0 }; // To store ADC values
volatile float32_t filter_output = 0; // FIR filter output
```

3. Initialize ADC, DAC, and TIM7:

```c
void adc_init(void) {
// Configure ADC in 12-bit right-aligned, single-channel, continuous conversion mode
}

void dac_init(void) {
// Enable channel 2 of the microcontroller DAC
}

void tim7_init(uint32_t fs) {
// Configure timer TIM7 to generate interrupts with the specified sampling rate fs
}
```

4. Implement TIM7 period-elapsed ISR:

```c
void TIM7_IRQHandler(void) {
// Set PG2 pin before starting the computation of the filter output
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_2, GPIO_PIN_SET);

// Get ADC conversion result
uint32_t new_adc_value = HAL_ADC_GetValue(&hadc1);

for (int i = N_COEFFS - 1; i > 0; i--) {
adc_values[i] = adc_values[i - 1];
}
adc_values[0] = new_adc_value;

// Calculate convolution sum to determine your filter output
filter_output = 0;
for (int i = 0; i < N_COEFFS; i++) {
filter_output += coeffs[i] * adc_values[i];
}

// Update DAC data register with the result
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_2, DAC_ALIGN_12B_R, (uint32_t)filter_output);

// Reset PG2 pin in the end of the timer ISR
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_2, GPIO_PIN_RESET);

// Clear TIM7 update interrupt flag
__HAL_TIM_CLEAR_FLAG(&htim7, TIM_FLAG_UPDATE);
}
```

5. Configure the function generator and verify the output signal. Then, connect it to the ADC input and observe the output with an oscilloscope.

6. Finally, increase the input frequency with 100 Hz increment up to 4 kHz and determine the frequencies corresponding to –3 dB and –6 dB attenuation using the oscilloscope.

After implementing the above code and steps, you should be able to observe the input and output signals, attenuation at desired frequencies, and the time taken for computation using the GPIO pin PG2.