Post Go back to editing

I want to know how to deal with crashes that occur in C language and assembler.

Category: Software
Product Number: ADSP-21565
Software Version: 2.11.0.0

Hi.

I am writing control in C language and filter calculations in assembler for high-speed calculations.
The input consists of two different sampling signals.
Signal acquisition uses DMA interrupts, and calculations use software interrupts. Additionally, I read and write to QSPI memory while outputting signals.
Switching soft interrupts or accessing memory causes a few lines of assembly code to break and crash the system. Alternatively, crashes occur due to issues with return address or jump address.
I understand that I should not use i6/i7/m7, etc., within assembly code, but
    1: What other registers besides MODE1/ASTATX/CMMR0 should be saved within assembly code?
 2: I think there are registers that should be saved during interrupts. Which registers specifically?
        How should this be written in C language? How should MODE1 be written?
        The CMMR SYSCTL can be written as follows:
                ESC_SYSCTL=*pREG_CMMR0_SYSCTL;

Thanks, Regards,

YAMAMOTO

Parents
  • Hi Yamamoto,

    Regarding "What other registers besides MODE1/ASTATX/CMMR0 should be saved within assembly code?"
    >>>In any assembly routine—especially interrupt handlers or functions called from C—you must save and restore all callee-saved registers, such as data registers (R4–R7),pointer registers (P3–P5), index and loop registers (I0–I3, L0–L3, B0–B3, M0–M3, LC0, LC1), and status registers like MODE1 and ASTAT.
    You must avoid using compiler-reserved registers such as I6, I7, and M7, as they are reserved for stack frame and return address management by the compiler. These rules are required to maintain system stability and proper C-ASM integration.

    For more details, please refer to the following help path in CCES:
    CrossCore® Embedded Studio 2.11.0 > SHARC® Development Tools Documentation > C/C++ Compiler Manual for SHARC® Processors > Compiler > C/C++ Run-Time Model and Environment > Registers

    Regarding "How should this be written in C language? How should MODE1 be written?"
    >>> Memory-mapped registers, such as CMMR0_SYSCTL, can be accessed directly in C using pointers.
          
    Please find below a code snippet demonstrating how to set and clear specific bits of the MODE1 register using the sysreg_bit_set() and sysreg_bit_clr(),
          
          #include <sysreg.h>
          sysreg_bit_set(sysreg_MODE1,(BITM_REGF_MODE1_SPERREN ));
          sysreg_bit_set(sysreg_MODE1,(BITM_REGF_MODE1_SPERREN ));
          
    Please use this snippet as a reference and modify it accordingly to your application requirement.

    Regards,
    Nandini C

  • Hi. Nandini C-san

    I am writing interrupts from the microcomputer in C language and interrupts from the filter in assembler, but sometimes it crashes.
    When calling assembler from C,
    I understood that I should not use /i6/i7/l6/l7/b6/b7/m5/m6/m7/m13/m14/m15 and that I should return with L set to 0.
    However, are the registers R4-R7, I0-I3, b0-b3, m0-m3, etc., that you mentioned not supposed to be used within the assembler?
    Do I need to restore their original values when returning from the assembler to C?
    Additionally, I understand that I can manipulate bits like MODE1, but how should I describe copying MODE1, 2, and ASTATX directly into the registers when saving them?
    I understand that SYSCTL should be written like this.
    RES_SYSCTL=*pREG_CMMR0_SYSCTL;

    Thanks, Best Regards,

    YAMAMOTO

  • Hi, Nandini C-san

    The push for MODE1/ASTAT that you taught me
    asm volatile(“%0 = MODE1;”:“=d”(mode1_backup));
    put the MODE1 data into mode1_backup.
    How do I write the reverse?
    How should I describe ASTATX?
    Also, in which manual is it written that I should write %0 = MODE1; or “=d”(mode1_backup)?

    Thanks & Regards,

    YAMAMOTO

  • Hi Yamamoto,

    Regarding "How do I write the reverse?"
    >>>Please find the below snippet for reference.

    uint32_t mode1_backup;
    asm volatile("%0 = MODE1;" : "=d"(mode1_backup)); //MODE1 register into mode1_backup
    mode1_backup |= (1U << 5);
    asm volatile("MODE1 = %0;" :: "d"(mode1_backup)); // Write modified value back to MODE1

    Regarding "How should I describe ASTATX?"
    >>> Are you asking about to read/write this register. If so,you can use the above format for ASTATX as well.

    Regarding "Also, in which manual is it written that I should write %0 = MODE1; or “=d”(mode1_backup)?"
    >>> Could you please find the asm() Construct Syntax[Page No:158/486] in the CCES Sharc complier manual.Please find the below link,
    https://www.analog.com/media/en/dsp-documentation/software-manuals/cces-sharccompiler-manual.pdf

    Regards,
    Nandini C

  • Hi. Nandini C-san

    Thanks. 

    When writing to the QUAD I/O memory while an interrupt signal is active,
    the function waiting for the external memory response in SPI_Functions.c fails to receive the response and hangs. (Code below)
      while(!(*pREG_SPI2_STAT & BITM_SPI_STAT_TF)); // wait till completion
    I need to output signals even while memory is being written.
    Is there any way to prevent this from hanging?

    Thanks, Best Regards,

    YAMAMOTO

  • Hi,

    Apologies for the delayed response.

    While waiting for the transfer complete bit (BITM_SPI_STAT_TF), this line (while(!(*pREG_SPI2_STAT & BITM_SPI_STAT_TF)); queries the SPI status register continually.

    We recommend using the DMA controller of the ADSP-21565 for your application. DMA fully offloads the task from the processor core by enabling the SPI peripheral to manage data transfers on its own. By doing this, the busy-wait loop is avoided, allowing the system to continue handling your output signals and interrupts without experiencing any performance problems.
    As an alternative to busy-waiting, you can use interrupt-driven SPI transfers. When the transfer is finished, you can set up the SPI peripheral to cause an interrupt. As a result, the system can continue other tasks while the SPI transfer is underway, and an Interrupt Service Routine (ISR) effectively handles the transfer completion.

    Regards,
    Nandini C

  • Nandini C -san

    Thank you.
    When I hear “DMA,” I imagine moving data from one address to another,
    but I can't visualize how the data moves within the SPI status register.
    Also,
    the provided program is SPI_Function.c,
    but I don't know how to modify it.
    Please provide a concrete program that reads from and writes to the QSPI memory.

    Best regards,

    YAMAMOTO

  • Hi,

    We have an example to read/write from a flash using Quad/Octal with DMA mode. Please download BSP package of ADSP-21569 using the below link:
    download.analog.com/.../ADI_EV-2156x_EZ-KIT-Rel3.0.0.exe

    After installation you find examples from the below path:
    <installation path>\EV-2156x_EZ-KIT-Rel3.0.0\EV-2156x_EZ-KIT\Examples\drivers\ospi

    These examples demonstrate the Direct mode flash access with erase, SPI/QPI read/write, and verification on supported EV-2156x SOM platforms.

    You can use this example as a reference and modify it as needed for your application.

    Regards,
    Nandini C

  • Hi Nandini C-san

    Thank you very much.
    It's a bit difficult for me, but I'll give it a try.
    I'll let you know if I run into any trouble.

    Regarads,

    YAMAMOTO

  • Hi. Nandini C-san

    Please tell me
    Where in the reference documentation is the C language implementation for
       Fn = CVT Fx:y
    documented?

    How would you implement this in C?

    Thanks, Best regards,

    YAMAMOTO

  • Hi,

    As per the ADSP-2156x PRM, this Fn = CVT Fx:y function converts the double-precision floating-point operand in the Fx:y register to a single-precision floating-point value. The converted result is placed in the FN register.

    Can you please refer the "FN = cvt FX:Y;" [Page No:491/798] in the ADSP-2156x Programming Referenc Manual. Please find the below link,
    https://www.analog.com/media/en/dsp-documentation/processor-manuals/sc58x-2158x-prm.pdf

    For more information on the built in functions for the conversion, please refer the below CCES path,

    Regards,
    Nandini C

  • Hi, -san

    Thanks.

    but

    I want to know how to express this in C.
      Fn = CVT Fx:y


    I could find this syntax in ‘buitltins.c’.
    conv_float_by(_a,_b).

    But I couldn't find that syntax in C language. 


    I want to write this assembler in C language.
    f6=pm(i9,m9);                          // LOAD:64bit Low
    f7=pm(i9,m9);                          // 64bit High
    lcntr=r0, do loop_CONV until lce;
       f8=cvt f7:6;                           // 64bit to 40bit
    dm(i4,m6)=f8, f6=pm(i9,m9);  // SAVE:40bit LOAD:next 64bit Lowh
    loop_CONV: f7=pm(i9,m9);    // LOAD:next 64bit High

    Where can I find instructions on how to rewrite assembly language syntax in C language?

    Thanks, Best regards,

    YAMAMOTO

Reply
  • Hi, -san

    Thanks.

    but

    I want to know how to express this in C.
      Fn = CVT Fx:y


    I could find this syntax in ‘buitltins.c’.
    conv_float_by(_a,_b).

    But I couldn't find that syntax in C language. 


    I want to write this assembler in C language.
    f6=pm(i9,m9);                          // LOAD:64bit Low
    f7=pm(i9,m9);                          // 64bit High
    lcntr=r0, do loop_CONV until lce;
       f8=cvt f7:6;                           // 64bit to 40bit
    dm(i4,m6)=f8, f6=pm(i9,m9);  // SAVE:40bit LOAD:next 64bit Lowh
    loop_CONV: f7=pm(i9,m9);    // LOAD:next 64bit High

    Where can I find instructions on how to rewrite assembly language syntax in C language?

    Thanks, Best regards,

    YAMAMOTO

Children
  • Hi,

    Apologies for the delayed response.

    The operation Fn = CVT Fx:y, this instruction has no direct equivalent in standard C . It’s a SHARC-specific instruction used to convert a 64-bit floating-point value to a 40-bit floating-point value using the hardware unit,
    because the C language does not define a 40-bit floating-point type and has no syntax that maps one-to-one to SHARC DSP instructions.

    In C, you can approximate it by casting a double to a float, though this does not guarantee the same 40-bit precision or rounding behavior.
    If you need exact control over the CVT instruction, the recommendation is to use inline assembly.

    For more information on the in-built functions and their usage, please refer to the below documents.
    www.analog.com/.../cces-sharclibrary-manual.pdf
    smd.hu/.../cc21k_02.pdf

    Regards,
    Nandini C

  • Hi, -san

    Thanks.

    In assembler  Fn = CVT Fx:Fy -> In C asm(" Fn=CVT Fx:Fy";);

    OK. But

    How do I write values to Fx and Fy?
    How should I handle communication between the C language data area and the assembly area?

    For example, in C language:
    CONV_64to40[0] = &coef64_GEQ;
    To store CONV_64to40[0] in Fx and CONV_64to40[1] in Fy, I believe the best approach is to store CONV_64to40[0] in assembly register b0-15.
    How would you write this in inline assembly?
    I just can't figure it out. Please help.

    Thanks, Best regards,

    YAMAMOTO

  • Hi,

    Apologies for the delayed response.

    You cannot directly assign C variables to the SHARC floating‑point registers Fx and Fy. To communication between the C and SHARC assembly it must be done by explicitly loading data from memory into registers within an inline assembly and storing the results back to memory.

    On SHARC processors, C variables stored in data or program memory, while Fx, Fy, and Fn are hardware floating-point registers. The compiler does not automatically map C variables to these registers.

    Please find the snippet below that demonstrates assigning a variable value on the SHARC processor.
    int low_32 = 0x56789000; // lower 32 bits
    int high_32 = 0x12345002; // upper 32 bits

    asm volatile (
         "f6 = %0;\n\t"
         "f7 = %1;\n\t"
         :
         : "r"(low_32), "r"(high_32)
         : "f6","f7"
    );

    Regards,
    Nandini C