5.3 CORDIC Guide

This chapter describes the file composition and 11 public functions of the CORDIC driver in the N32H49x standard peripheral library, together with 3 examples. The CORDIC is a hardware coordinate rotation digital computer built into the chip that accelerates trigonometric and hyperbolic functions, magnitude and arctangent; for the data width, scale factor and output limiting settings, see the “Coordinate rotation digital computer (CORDIC)” chapter of the user manual.

5.3.1 Related files

Relative path Purpose
firmware/n32h49x_std_periph_driver/inc/n32h49x_cordic.h Defines the function, data width, scale and limit options and the register masks, and declares the 11 public functions
firmware/n32h49x_std_periph_driver/src/n32h49x_cordic.c Implements the 11 functions above: initialization and structure defaults, interrupt and DMA request control, data register address retrieval and read/write, and status flag read and clear
projects/n32h49x_EVAL/examples/CORDIC/ CORDIC example root directory, containing the 3 examples CORDIC_Fixed_Sin_DMA, CORDIC_Fixed_Sin_IT and CORDIC_Float_Sin_IT
projects/n32h49x_EVAL/examples/CORDIC/CORDIC_Fixed_Sin_DMA/ Project directory composition of this example: MDK-ARM/, EWARM/, inc/, src/, readme.txt
projects/n32h49x_EVAL/bsp/ Common board files referenced by this example: the UART log function

5.3.2 API reference

Search API11 functions

The following 11 public functions are listed in the declaration order of n32h49x_cordic.h in 4 groups; each entry gives a summary and the original comment above the function in n32h49x_cordic.c.

Initialization and reset

CORDIC_DeInit, CORDIC_Init, CORDIC_StructInit

Interrupt and DMA request

CORDIC_InterruptCmd, CORDIC_DMAReadRequestCmd, CORDIC_DMAWriteRequestCmd

Data read and write

CORDIC_GetRegisterAddr, CORDIC_WriteData, CORDIC_ReadData

Status and flags

CORDIC_GetFlagStatus, CORDIC_ClearStatusFlag

void CORDIC_DeInit(void)DeInitializes the CORDIC peripheral.
Source comment
name    CORDIC_DeInit.
fun     DeInitializes the CORDIC peripheral.
param   none
return  none
void CORDIC_Init(CORDIC_InitType* CORDIC_InitParam)Initialize the CORDIC module with CORDIC_InitParam of type CORDIC_InitType.
Source comment
name    CORDIC_Init.
fun     Initialize the CORDIC module with CORDIC_InitParam of type CORDIC_InitType.
param   CORDIC_InitParam :
          - Pointer to the CORDIC_InitType structure which will be initialized.
return  none
void CORDIC_StructInit(CORDIC_InitType* CORDIC_InitParam)Initializes the structure parameter of type CORDIC_InitType used to initialize CORDIC. This function is usually called before initializing a parameter of type CORDIC_InitType.
Source comment
name    CORDIC_StructInit.
fun     Initializes the structure parameter of type CORDIC_InitType used to
        initialize CORDIC. This function is usually called before initializing
        a parameter of type CORDIC_InitType.
param   CORDIC_InitParam :
          - Pointer to the CORDIC_InitType structure which will be initialized.
return  none
void CORDIC_InterruptCmd(uint32_t Interrupt, FunctionalStatus Cmd)Enables or disables the specified CORDIC interrupts.
Source comment
name    CORDIC_InterruptCmd.
fun     Enables or disables the specified CORDIC interrupts.
param   Interrupt (The input parameters must be the following values):
          - CORDIC_INT
          - CORDIC_INT_INOVERFLOW
param   Cmd (The input parameters must be the following values):
          - ENABLE
          - DISABLE
return  none
void CORDIC_DMAReadRequestCmd(FunctionalStatus Cmd)Enables or disables the CORDIC DMA read request.
Source comment
name    CORDIC_DMAReadRequestCmd.
fun     Enables or disables the CORDIC DMA read request.
param   Cmd (The input parameters must be the following values):
          - ENABLE
          - DISABLE
return  none
void CORDIC_DMAWriteRequestCmd(FunctionalStatus Cmd)Enables or disables the CORDIC DMA write request.
Source comment
name    CORDIC_DMAWriteRequestCmd.
fun     Enables or disables the CORDIC DMA write request.
param   Cmd (The input parameters must be the following values):
          - ENABLE
          - DISABLE
return  none
uint32_t CORDIC_GetRegisterAddr(uint32_t Direction)Get the CORDIC data register address used for DMA transfer.
Source comment
name    CORDIC_GetRegisterAddr.
fun     Get the CORDIC data register address used for DMA transfer.
param   Direction (The input parameters must be the following values):
          - CORDIC_AS_DMA_SRCADDR
          - CORDIC_AS_DMA_DSTADDR
return  Address of data register.
void CORDIC_WriteData(uint32_t *pInData)Write 32-bit input data for the CORDIC processing.
Source comment
name    CORDIC_WriteData.
fun     Write 32-bit input data for the CORDIC processing.
param   pInData :
          - Points to the address of input data
return  none
void CORDIC_ReadData(uint32_t *pOutData)Return 32-bit output data of CORDIC processing.
Source comment
name    CORDIC_ReadData.
fun     Return 32-bit output data of CORDIC processing.
param   pOutData :
          - Points to the address where the output data is stored
return  32-bit output data of CORDIC processing.
FlagStatus CORDIC_GetFlagStatus(uint32_t Flag)Checks whether the specified CORDIC flag is set or not.
Source comment
name    CORDIC_GetFlagStatus.
fun     Checks whether the specified CORDIC flag is set or not.
param   Flag (The input parameters must be the following values):
          - CORDIC_FLAG_RRF
          - CORDIC_FLAG_INOVF
          - CORDIC_FLAG_DMAWENF
          - CORDIC_FLAG_DMARENF
          - CORDIC_FLAG_INTENF
return  SET or RESET
void CORDIC_ClearStatusFlag(uint32_t Flag)Clears the pending flag for the CORDIC.
Source comment
name    CORDIC_ClearStatusFlag.
fun     Clears the pending flag for the CORDIC.
param   Flag (The input parameters must be the following values):
          - CORDIC_FLAG_INOVF
          - CORDIC_FLAG_DMAWENF
          - CORDIC_FLAG_DMARENF
          - CORDIC_FLAG_INTENF
return  none
note    The RRF flag cannot be cleared by a call to this function;
        the RRF flag is cleared by hardware when reading the data
        register is complete.

5.3.3 Demo descriptions

This section describes the 3 CORDIC examples: CORDIC_Fixed_Sin_DMA moves the fixed-point sine inputs and outputs by DMA, CORDIC_Fixed_Sin_IT reads the fixed-point results by interrupt, and CORDIC_Float_Sin_IT reads the floating-point results by interrupt.

5.3.3.1 CORDIC_Fixed_Sin_DMA fixed-point sine over DMA

Example directory: projects/n32h49x_EVAL/examples/CORDIC/CORDIC_Fixed_Sin_DMA/

Configure the CORDIC and DMA1 clocks→Reset the CORDIC and set up the sine parameters→Fetch the CORDIC read and write register addresses→Configure the DMA channels and enable the DMA requests→Wait for the result-ready flag and compare with the reference sines

Item Source analysis
Function Computes 64 points of sine in Q1.31 fixed-point format;
the CORDIC is set to the sine function with 6-cycle precision and both coordinate and phase limits are enabled;
the DMA read channel moves CORDIC_RDAT results into aCalResult and the write channel moves aInData into CORDIC_WDAT;
after the transfer every point is compared against aRefResult.
Source files src/main.c: main, RCC_Configuration, NVIC_Configuration, DMA_ReadConfiguration, DMA_WriteConfiguration, CheckResidualError;
inc/n32h49x_it.h, src/n32h49x_it.c: interrupt vectors and exception handlers;
readme.txt: function, environment and usage notes;
MDK-ARM/, EWARM/: Keil and IAR projects.
Key configuration Clock: the CORDIC and DMA1 clocks are enabled and RCC_ConfigPeriphClk(RCC_PERIPH_HCLK_DIV2) is called;
CORDIC: CORDIC_FUNCTION_SINE, CORDIC_PRECISION_6CYCLES, CORDIC_CODIN_LIMIT_ENABLE and CORDIC_PHASE_LIMIT_ENABLE;
read channel: DMA1_CH1 remapped with DMA_REMAP_CORDIC_RD;
write channel: DMA1_CH2 remapped with DMA_REMAP_CORDIC_WR, both WORD wide with memory increment and a length of 64.
Program and data path main calls RCC_Configuration, NVIC_Configuration and CORDIC_DeInit in turn;
CORDIC_GetRegisterAddr returns the CORDIC_RDAT and CORDIC_WDAT addresses and CORDIC_Init selects the sine function;
after the read request is enabled DMA_ReadConfiguration moves results into aCalResult, and after the write request is enabled DMA_WriteConfiguration moves aInData into the CORDIC;
once CORDIC_FLAG_RRF is set, every point is compared with aRefResult through CheckResidualError.
Main APIs CORDIC_DeInit, CORDIC_GetRegisterAddr, CORDIC_Init, CORDIC_DMAReadRequestCmd, CORDIC_DMAWriteRequestCmd, CORDIC_GetFlagStatus
Verification After building, downloading and running, the UART prints “CORDIC demo success!!!” when all 64 points are within tolerance;
if a point deviates by more than MAX_RESIDUAL_ERROR_18, “Error[i]” is printed and the program stays in while(1).
Use note When the CORDIC is enabled the HCLK must be set to DIV2;
input data is Q1.31 fixed point, incrementing from 0 to 2*pi;
this example has no standalone main.h;
its inc/ directory only holds the interrupt header.
Core-code walkthrough and porting

The example uses two DMA channels to move the 64 fixed-point inputs into the CORDIC and the results out, and finally compares every point against the reference sines.

Data path: RCC_Configuration enables the CORDIC and DMA1 clocks and sets the HCLK to DIV2 → CORDIC_DeInit resets the module → CORDIC_GetRegisterAddr returns the CORDIC_RDAT and CORDIC_WDAT addresses → CORDIC_Init selects the sine function → the DMA read and write channels move aInData into the CORDIC and the results into aCalResult → after CORDIC_FLAG_RRF is set, every point is compared with aRefResult

1. Configure the CORDIC and DMA1 clocks. RCC_Configuration enables the CORDIC and DMA1 clocks and sets the HCLK to DIV2, which is required when the CORDIC is enabled.

src/main.csrc/main.c · RCC_Configuration
void RCC_Configuration()
{
    /* Enable DMA1 and CORDIC clock */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_CORDIC | RCC_AHB_PERIPHEN_DMA1, ENABLE);
    /* When enabling CORDIC, HCLK DIV2 must be configured */
    RCC_ConfigPeriphClk(RCC_PERIPH_HCLK_DIV2);
}

When porting to another model only the CORDIC and the used DMA clocks are needed; RCC_PERIPH_HCLK_DIV2 cannot be omitted.

2. Fetch the data register addresses and select the sine function. main first calls CORDIC_GetRegisterAddr for the read and write data register addresses used by the DMA, then configures the CORDIC for sine with 6-cycle precision and enables the coordinate and phase limits through the structure.

src/main.csrc/main.c · main
    /* Get CORDIC read register (CORDIC_RDAT) address */
    rRegAddr = CORDIC_GetRegisterAddr(CORDIC_AS_DMA_SRCADDR);
    /* Get CORDIC write register (CORDIC_WDAT) address */
    wRegAddr = CORDIC_GetRegisterAddr(CORDIC_AS_DMA_DSTADDR);

    CORDIC_StructInit(&CORDIC_InitStructure);
    /* Select sine function */
    CORDIC_InitStructure.Function   = CORDIC_FUNCTION_SINE;
    /* Set max precision for Q1.31 sine */
    CORDIC_InitStructure.Precision  = CORDIC_PRECISION_6CYCLES;
    /* Enable Coordinate Limit */
    CORDIC_InitStructure.CodinLimit = CORDIC_CODIN_LIMIT_ENABLE;
    /* Enable Phase Limit */
    CORDIC_InitStructure.PhaseLimit = CORDIC_PHASE_LIMIT_ENABLE;
    /* Configure CORDIC */
    CORDIC_Init(&CORDIC_InitStructure);

For another function or precision only Function and Precision change; the read and write register addresses are told apart by the Direction argument.

3. Configure the DMA channels and enable the DMA requests. DMA_ReadConfiguration sets the peripheral address to CORDIC_RDAT and the memory address to aCalResult, and remaps the channel to the CORDIC read request; main then enables both DMA requests, and the write side moves aInData into CORDIC_WDAT through DMA_WriteConfiguration.

src/main.csrc/main.c · DMA_ReadConfiguration
    /* Reset DMA1 channel 1 */
    DMA_DeInit(DMA1_CH1);
    /* Initialize the DMA parameter structure */
    DMA_StructInit(&DMA_InitStructure);
    DMA_InitStructure.PeriphAddr     = SrcAddr;
    DMA_InitStructure.MemAddr        = (uint32_t)DstAddr;
    DMA_InitStructure.Direction      = DMA_DIR_PERIPH_SRC;
    DMA_InitStructure.BufSize        = DataLen;
    DMA_InitStructure.MemoryInc      = DMA_MEM_INC_ENABLE;
    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_WORD;
    DMA_InitStructure.MemDataSize    = DMA_MEM_DATA_WIDTH_WORD;
    /* Initialize DMA1 channel 1 */
    DMA_Init(DMA1_CH1, &DMA_InitStructure);
    /* CORDIC read channel mapping */
    DMA_RequestRemap(DMA_REMAP_CORDIC_RD, DMA1_CH1, ENABLE);
    /* Enable DMA1 channel 1 transfer completion interrupt */
    DMA_ConfigInt(DMA1_CH1, DMA_INT_TXC, ENABLE);
    /* Enable DMA1 channel 1 */
    DMA_EnableChannel(DMA1_CH1, ENABLE);
src/main.csrc/main.c · main
    /* Configure DMA read channel */
    DMA_ReadConfiguration(rRegAddr, aCalResult, ARRAY_SIZE);
    /* Enable CORDIC DMA read request */
    CORDIC_DMAReadRequestCmd(ENABLE);

    /* Configure DMA write channel */
    DMA_WriteConfiguration(aInData, wRegAddr, ARRAY_SIZE);
    /* Enable CORDIC DMA write request */
    CORDIC_DMAWriteRequestCmd(ENABLE);

When porting, the request remap of the two channels must match the actual transfer direction; in DMA mode the CPU must not access the CORDIC data register directly.

4. Wait for the result and compare with the reference. After the computation starts main polls CORDIC_FLAG_RRF and, once it is set, compares every point with the reference sine through CheckResidualError.

src/main.csrc/main.c · main
    while (CORDIC_GetFlagStatus(CORDIC_FLAG_RRF) == RESET)
    {
        /* Do nothing */
    }
    
    /* Compare CORDIC results to the reference values */
    for (i = 0; i < ARRAY_SIZE; i++)
    {
        /* Check the data results sequentially */
        if (CheckResidualError(aCalResult[i], aRefResult[i], MAX_RESIDUAL_ERROR_18) == 0U)
        {
            log_info("Error[%d]\n", i);
            while (1);
        }
    }

The tolerance constant follows the precision: at 6-cycle precision the sine residual error is about 2^-18.

Corresponding source files: src/main.c

5.3.3.2 CORDIC_Fixed_Sin_IT fixed-point sine read by interrupt

Example directory: projects/n32h49x_EVAL/examples/CORDIC/CORDIC_Fixed_Sin_IT/

Configure the CORDIC clock→Reset and set up the sine parameters→Enable the CORDIC interrupt→Write the Q1.31 input points one by one→Read the results back in the interrupt and compare with the reference sines

Item Source analysis
Function Computes 64 points of sine in Q1.31 fixed-point format;
the input is written point by point into CORDIC_WDAT by the main loop and every ready result triggers the Cordic_IRQn interrupt;
Cordic_IRQ_IRQHandler reads the results back into aCalResult, and the main loop then compares every point against aRefResult.
Source files src/main.c: main, RCC_Configuration, NVIC_Configuration, CheckResidualError, Cordic_IRQ_IRQHandler;
inc/n32h49x_it.h, src/n32h49x_it.c: interrupt vectors and exception handlers;
readme.txt: function, environment and usage notes;
MDK-ARM/, EWARM/: Keil and IAR projects.
Key configuration Clock: the CORDIC clock is enabled and RCC_ConfigPeriphClk(RCC_PERIPH_HCLK_DIV2) is called;
CORDIC: CORDIC_FUNCTION_SINE, CORDIC_PRECISION_6CYCLES, CORDIC_CODIN_LIMIT_ENABLE and CORDIC_PHASE_LIMIT_ENABLE, with CORDIC_InterruptCmd(CORDIC_INT, ENABLE) called;
NVIC: priority group 0 with Cordic_IRQn enabled.
Program and data path main calls RCC_Configuration, NVIC_Configuration, CORDIC_DeInit and CORDIC_Init in turn;
after the interrupt is enabled a for loop writes each point of aInData with CORDIC_WriteData;
every finished computation makes Cordic_IRQ_IRQHandler check CORDIC_FLAG_RRF and read CORDIC_RDAT into aCalResult with CORDIC_ReadData;
the main loop compares every point with aRefResult through CheckResidualError.
Main APIs CORDIC_DeInit, CORDIC_Init, CORDIC_InterruptCmd, CORDIC_WriteData, CORDIC_ReadData, CORDIC_GetFlagStatus
Verification After building, downloading and running, the UART prints “CORDIC demo success!!!” when all 64 points are within tolerance;
if a point deviates by more than MAX_RESIDUAL_ERROR_18, “Error[i]” is printed and the program stays in while(1).
Use note When the CORDIC is enabled the HCLK must be set to DIV2;
reading the result register inserts a bus wait until the computation finishes, so CORDIC_ReadData can be called directly in the interrupt;
reading the data register clears CORDIC_FLAG_RRF in hardware.
Core-code walkthrough and porting

The example writes the 64 fixed-point inputs into the CORDIC point by point; every ready result is read back by the Cordic_IRQn interrupt, and the results are finally compared with the reference sines.

Data path: RCC_Configuration enables the CORDIC clock and sets the HCLK to DIV2 → CORDIC_DeInit resets the module → CORDIC_Init selects the sine function → CORDIC_InterruptCmd enables the interrupt → the main loop writes aInData with CORDIC_WriteData → Cordic_IRQ_IRQHandler reads CORDIC_RDAT into aCalResult → the main loop compares with aRefResult

1. Configure the CORDIC clock. RCC_Configuration enables the CORDIC clock and sets the HCLK to DIV2.

src/main.csrc/main.c · RCC_Configuration
void RCC_Configuration()
{
    /* Enable CORDIC clock */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_CORDIC, ENABLE);
    /* When enabling CORDIC, HCLK DIV2 must be configured */
    RCC_ConfigPeriphClk(RCC_PERIPH_HCLK_DIV2);
}

RCC_PERIPH_HCLK_DIV2 is required when the CORDIC is enabled and cannot be omitted when porting.

2. Set up the sine function and enable the interrupt. main configures the CORDIC for sine with 6-cycle precision and the coordinate and phase limits, and enables the CORDIC interrupt.

src/main.csrc/main.c · main
    CORDIC_StructInit(&CORDIC_InitStructure);
    /* Select sine function */
    CORDIC_InitStructure.Function   = CORDIC_FUNCTION_SINE;
    /* Set max precision for Q1.31 sine */
    CORDIC_InitStructure.Precision  = CORDIC_PRECISION_6CYCLES;
    /* Enable Coordinate Limit */
    CORDIC_InitStructure.CodinLimit = CORDIC_CODIN_LIMIT_ENABLE;
    /* Enable Phase Limit */
    CORDIC_InitStructure.PhaseLimit = CORDIC_PHASE_LIMIT_ENABLE;
    /* Configure CORDIC */
    CORDIC_Init(&CORDIC_InitStructure);

    /* Enable CORDIC interrupt */
    CORDIC_InterruptCmd(CORDIC_INT, ENABLE);

The interrupt scheme suits reading results as they are produced, so the CPU does not poll the completion flag.

3. Write the input points one by one. With the interrupt enabled main writes every point of aInData into the data register, and the hardware starts computing right away.

src/main.csrc/main.c · main
    for (wArrayIndex = 0; wArrayIndex < ARRAY_SIZE; wArrayIndex++)
    {
        /* Write data to be calculated */
        CORDIC_WriteData((uint32_t *)&aInData[wArrayIndex]);
    }

The Q1.31 input is spread evenly from 0 to 2*pi, and the write order is the read order of the results.

4. Read the results back in the interrupt. Cordic_IRQ_IRQHandler checks CORDIC_FLAG_RRF and, when it is set, reads the data register into aCalResult; the read also clears the flag in hardware.

src/main.csrc/main.c · Cordic_IRQ_IRQHandler
void Cordic_IRQ_IRQHandler(void)
{
    if (CORDIC_GetFlagStatus(CORDIC_FLAG_RRF) != RESET)
    {
        /* Read calculation results */
        /* The RRF flag will be cleared after reading the data register */
        CORDIC_ReadData((uint32_t *)&aCalResult[rArrayIndex++]);
    }
}

When combining several channels or DMA, remember that CORDIC_RDAT must not be read by the CPU once the DMA read channel is enabled.

Corresponding source files: src/main.c

5.3.3.3 CORDIC_Float_Sin_IT floating-point sine read by interrupt

Example directory: projects/n32h49x_EVAL/examples/CORDIC/CORDIC_Float_Sin_IT/

Configure the CORDIC clock→Reset and set up the floating-point sine parameters→Enable the CORDIC interrupt→Generate and write random inputs→Read the floating-point results back in the interrupt and compare

Item Source analysis
Function Computes 64 points of sine in floating-point format;
rand generates inputs in the range -1.0 to 1.0 and sinf computes the software reference;
the CORDIC is set for floating-point input and output, and the results read back by interrupt are compared with the reference.
Source files src/main.c: main, RCC_Configuration, NVIC_Configuration, CheckResidualError, Cordic_IRQ_IRQHandler;
inc/n32h49x_it.h, src/n32h49x_it.c: interrupt vectors and exception handlers;
readme.txt: function, environment and usage notes;
MDK-ARM/, EWARM/: Keil and IAR projects.
Key configuration Clock: the CORDIC clock is enabled and RCC_ConfigPeriphClk(RCC_PERIPH_HCLK_DIV2) is called;
CORDIC: CORDIC_FUNCTION_SINE, CORDIC_PRECISION_6CYCLES, CORDIC_INPUT_FLOAT and CORDIC_OUTPUT_FLOAT, with the coordinate and phase limits enabled;
NVIC: priority group 0 with Cordic_IRQn enabled.
Program and data path main initializes the clock, the NVIC and the CORDIC in turn;
a for loop fills aInData with rand and computes aRefResult with sinf;
the inputs are then written point by point with CORDIC_WriteData and Cordic_IRQ_IRQHandler reads aCalResult back;
the main loop compares them with CheckResidualError.
Main APIs CORDIC_DeInit, CORDIC_Init, CORDIC_InterruptCmd, CORDIC_WriteData, CORDIC_ReadData, CORDIC_GetFlagStatus
Verification The UART prints “CORDIC demo success!!!” when all floating-point results are within tolerance;
if a point deviates by more than MAX_RESIDUAL_ERROR_18, “Error[i]” is printed and the program stays in while(1).
Use note The floating-point input must stay in the range -1.0 to 1.0;
the sinf reference is computed as the sine of the input multiplied by pi, matching the CORDIC convention;
the HCLK must also be set to DIV2 when the CORDIC is enabled.
Core-code walkthrough and porting

The example drives the CORDIC with random floating-point inputs and compares the results read back by interrupt with the reference computed by sinf.

Data path: RCC_Configuration enables the CORDIC clock and sets the HCLK to DIV2 → CORDIC_DeInit resets the module → CORDIC_Init selects the floating-point sine → CORDIC_InterruptCmd enables the interrupt → a loop fills aInData and aRefResult and writes with CORDIC_WriteData → Cordic_IRQ_IRQHandler reads CORDIC_RDAT into aCalResult → the main loop compares

1. Configure the CORDIC clock. As in the fixed-point example, RCC_Configuration enables the CORDIC clock and sets the HCLK to DIV2.

src/main.csrc/main.c · RCC_Configuration
void RCC_Configuration(void)
{
    /* Enable CORDIC clock */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_CORDIC, ENABLE);
    /* When enabling CORDIC, HCLK DIV2 must be configured */
    RCC_ConfigPeriphClk(RCC_PERIPH_HCLK_DIV2);
}

The divider setting matches the fixed-point example and can be reused directly.

2. Set up the floating-point sine and enable the interrupt. The structure matches the fixed-point example, with floating-point input and output selected as well.

src/main.csrc/main.c · main
    CORDIC_StructInit(&CORDIC_InitStructure);
    /* Select sine function */
    CORDIC_InitStructure.Function   = CORDIC_FUNCTION_SINE;
    /* Set max precision for Q1.31 sine */
    CORDIC_InitStructure.Precision  = CORDIC_PRECISION_6CYCLES;
    /* Select floating-point input */
    CORDIC_InitStructure.InSelect   = CORDIC_INPUT_FLOAT;
    /* Select floating-point output */
    CORDIC_InitStructure.OutSelect  = CORDIC_OUTPUT_FLOAT;
    /* Enable Coordinate Limit */
    CORDIC_InitStructure.CodinLimit = CORDIC_CODIN_LIMIT_ENABLE;
    /* Enable Phase Limit */
    CORDIC_InitStructure.PhaseLimit = CORDIC_PHASE_LIMIT_ENABLE;
    /* Configure CORDIC */
    CORDIC_Init(&CORDIC_InitStructure);

    /* Enable CORDIC interrupt */
    CORDIC_InterruptCmd(CORDIC_INT, ENABLE);

In floating-point mode both input and output are interpreted as single-precision floats and no Q1.31 conversion is performed.

3. Generate the random inputs and the reference. The main loop generates inputs from -1.0 to 1.0 with rand and computes the software reference with sinf.

src/main.csrc/main.c · main
    for (i = 0; i < ARRAY_SIZE; i++)
    {
        /* Random generation of input data */
        aInData[i] = -1.0f + ((float)(rand() % 1999)) * 0.001f;

        /* Software calculation results */
        aRefResult[i] = sinf(aInData[i] * PI);
    }

The generated range matches the hardware phase input range, so points outside the range would be limited and are not part of the correctness check.

4. Write the inputs and read the results back in the interrupt. As in the fixed-point example, the write side calls CORDIC_WriteData point by point and the read side reads the data register in Cordic_IRQ_IRQHandler.

src/main.csrc/main.c · Cordic_IRQ_IRQHandler
void Cordic_IRQ_IRQHandler(void)
{
    if (CORDIC_GetFlagStatus(CORDIC_FLAG_RRF) != RESET)
    {
        /* Read calculation results */
        /* The RRF flag will be cleared after reading the data register */
        CORDIC_ReadData((uint32_t *)&aCalResult[rArrayIndex++]);
    }
}

The floating-point results are compared with aRefResult directly, and the tolerance is again controlled by MAX_RESIDUAL_ERROR_18.

Corresponding source files: src/main.c

5.3.4 Notes and troubleshooting

Scenario Check & action Source
Result read and wait Once a computation has started, reading the result register inserts a bus wait until the computation finishes, so the program does not need to poll the completion flag. User manual
Output limiting CODINLIMIT clamps the coordinate outputs to ±1 and PHASELIMIT clamps the phase output to ±π;
limiting changes results that fall outside the range.
User manual
Angle range The valid range of the phase input is [-1, 1), which is the actual angle divided by pi. User manual
Input range and scaling When the magnitudes of x and y are outside the allowed range, both x and y must be scaled by the same factor before they are supplied. User manual
16-bit result packing With INSIZE = 1, NUMWRITE must be 0;
with OUTSIZE = 1, NUMREAD must be 0 and the result register is read only once.
User manual
DMA and CPU access After the DMA read channel is enabled, CORDIC_RDAT must not be accessed by the CPU;
after the DMA write channel is enabled, CORDIC_WDAT must not be accessed by the CPU.
User manual
Scale factor and DMA The SCALE factor must not be changed while a DMA transfer is in progress. User manual
DMA for repeated operations only The CORDIC has no DMA request for programming CTRLSTS, so DMA mode suits only repeated computations with the same function and settings. User manual
Writing the configuration register Writing CTRLSTS discards data that has been stored but not yet computed. User manual
Scaling precision The scale factor introduces truncation error, and the loss of precision grows with the number of scaled bits. User manual
Nations Technologies DevKit Docs

Datasheets, SDK, driver APIs and demo guides for Nations Technologies MCU development kits, organized by chip series.

© 2026 Nations Technologies Inc. All rights reserved.粤ICP备11069485号This site uses cookie-free anonymous analytics.