Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не входит в прерывание от ШИМа
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
kumle
Для AT91SAM7s256 взял из папки ИАРа для платы sam7s-ek пример basic PWM project. Загружаю его в SRAM самбой, проект запускается, генерация шима есть, но в прерывание не попадает ? Файл Board_cstartup_iar.s стандартный, IAR5.4 ? В чем может быть дело ? Может ли мешать вывод отладочной информации через DBGU com порт?

Вот мой файл Board_cstartup_iar.s
Код
/*
     IAR startup file for AT91SAM7S microcontrollers.
*/

        MODULE  ?cstartup

       ;; Forward declaration of sections.
        SECTION IRQ_STACK:DATA:NOROOT(2)
        SECTION CSTACK:DATA:NOROOT(3)

//------------------------------------------------------------------------------
//         Headers
//------------------------------------------------------------------------------

#define __ASSEMBLY__
#include "at91sam7s256/AT91SAM7S256.h"

//------------------------------------------------------------------------------
//         Definitions
//------------------------------------------------------------------------------

#define ARM_MODE_ABT     0x17
#define ARM_MODE_FIQ     0x11
#define ARM_MODE_IRQ     0x12
#define ARM_MODE_SVC     0x13
#define ARM_MODE_SYS     0x1F

#define I_BIT            0x80
#define F_BIT            0x40

//------------------------------------------------------------------------------
//         Startup routine
//------------------------------------------------------------------------------

/*
   Exception vectors
*/
        SECTION .vectors:CODE:NOROOT(2)

        PUBLIC  resetVector
        PUBLIC  irqHandler

        EXTERN  Undefined_Handler
        EXTERN  SWI_Handler
        EXTERN  Prefetch_Handler
        EXTERN  Abort_Handler
        EXTERN  FIQ_Handler

        ARM

__iar_init$$done:              ; The interrupt vector is not needed
                               ; until after copy initialization is done

resetVector:
       ; All default exception handlers (except reset) are
       ; defined as weak symbol definitions.
       ; If a handler is defined by the application it will take precedence.
        LDR     pc, =resetHandler       ; Reset
        LDR     pc, Undefined_Addr      ; Undefined instructions
        LDR     pc, SWI_Addr            ; Software interrupt (SWI/SYS)
        LDR     pc, Prefetch_Addr       ; Prefetch abort
        LDR     pc, Abort_Addr          ; Data abort
        B       .                       ; RESERVED
        LDR     pc, =irqHandler         ; IRQ
        LDR     pc, FIQ_Addr            ; FIQ

Undefined_Addr: DCD   Undefined_Handler
SWI_Addr:       DCD   SWI_Handler
Prefetch_Addr:  DCD   Prefetch_Handler
Abort_Addr:     DCD   Abort_Handler
FIQ_Addr:       DCD   FIQ_Handler
    
/*
   Handles incoming interrupt requests by branching to the corresponding
   handler, as defined in the AIC. Supports interrupt nesting.
*/
irqHandler:
        /* Save interrupt context on the stack to allow nesting */
        SUB     lr, lr, #4
        STMFD   sp!, {lr}
        MRS     lr, SPSR
        STMFD   sp!, {r0, lr}

        /* Write in the IVR to support Protect Mode */
        LDR     lr, =AT91C_BASE_AIC
        LDR     r0, [r14, #AIC_IVR]
        STR     lr, [r14, #AIC_IVR]

        /* Branch to interrupt handler in Supervisor mode */
        MSR     CPSR_c, #ARM_MODE_SYS
        STMFD   sp!, {r1-r3, r4, r12, lr}
        MOV     lr, pc
        BX      r0
        LDMIA   sp!, {r1-r3, r4, r12, lr}
        MSR     CPSR_c, #ARM_MODE_IRQ | I_BIT

        /* Acknowledge interrupt */
        LDR     lr, =AT91C_BASE_AIC
        STR     lr, [r14, #AIC_EOICR]

        /* Restore interrupt context and branch back to calling code */
        LDMIA   sp!, {r0, lr}
        MSR     SPSR_cxsf, lr
        LDMIA   sp!, {pc}^


/*
   After a reset, execution starts here, the mode is ARM, supervisor
   with interrupts disabled.
   Initializes the chip and branches to the main() function.
*/
        SECTION .cstartup:CODE:NOROOT(2)

        PUBLIC  resetHandler
        EXTERN  LowLevelInit
        EXTERN  ?main
        REQUIRE resetVector
        ARM

resetHandler:

        /* Set pc to actual code location (i.e. not in remap zone) */
        LDR     pc, =label

        /* Perform low-level initialization of the chip using LowLevelInit() */
label:
        LDR     r0, =LowLevelInit
        LDR     r4, =SFE(CSTACK)
        MOV     sp, r4
        MOV     lr, pc
        BX      r0

        /* Set up the interrupt stack pointer. */
        MSR     cpsr_c, #ARM_MODE_IRQ | I_BIT | F_BIT     ; Change the mode
        LDR     sp, =SFE(IRQ_STACK)

        /* Set up the SYS stack pointer. */
        MSR     cpsr_c, #ARM_MODE_SYS | F_BIT             ; Change the mode
        LDR     sp, =SFE(CSTACK)

        /* Branch to main() */
        LDR     r0, =?main
        MOV     lr, pc
        BX      r0

        /* Loop indefinitely when program is finished */
loop4:
        B       loop4

        END



вот обработчик
Код
//------------------------------------------------------------------------------
/// Interrupt handler for the PWM controller. Counts the number of periods and
/// updates the duty cycle after a given number.
//------------------------------------------------------------------------------
void ISR_Pwmc(void)
{
    static unsigned int count = 0;
    static unsigned int duty = MIN_DUTY_CYCLE;
    static unsigned char fade = 1;
    
    m_pPio->PIO_CODR = BIT18;  //для проверки входа в прерывание зажигаем светодиод
    

    // Interrupt on channel #0
    if ((AT91C_BASE_PWMC->PWMC_ISR & AT91C_PWMC_CHID0) == AT91C_PWMC_CHID0)
      {
      
        count++;
        if (count == 5000) //раз в полсекунды меняем длительность импульса
         {
          printf("new duty=%u", duty);
          count = 0;
          duty = fade ? duty+1 : duty-1;
          PWMC_SetDutyCycle(CHANNEL_PWM0, duty);
          //PWMC_SetDutyCycle(CHANNEL_PWM1, duty);
          //PWMC_SetDutyCycle(CHANNEL_PWM2, duty);
          //PWMC_SetDutyCycle(CHANNEL_PWM3, duty);
          if (duty == MAX_DUTY_CYCLE || duty == MIN_DUTY_CYCLE)
           {
             fade ^= 1;
           }
         }
       }
  

}


вот main.c

Код
int main(void)
{
    
     //__disable_interrupt(); //пробовал, непомогло
  
    // DBGU output configuration
    TRACE_CONFIGURE(DBGU_STANDARD, 9600, BOARD_MCK);
    printf("-- Getting Started Project %s --\n\r", SOFTPACK_VERSION);
    printf("-- %s\n\r", BOARD_NAME);
    printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__);
    printf("Sasha's compilation\n\r");
    
  // Configure led
  m_pPio->PIO_SODR  = BIT18;   // Set PA18 to HIGH -> led off
  m_pPio->PIO_OER   = BIT18;   // Configure PA8 as output
  

   //Configure PIO
    PIO_Configure(pins, PIO_LISTSIZE(pins));
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PWMC;
  
  printf("1\n\r");

  // Settings:
  // - 100kHz PWM period (PWM_FREQUENCY)
  // - 1s rise/fall time for the LED intensity

   PWMC_ConfigureClocks(PWM_FREQUENCY * MAX_DUTY_CYCLE, 0, BOARD_MCK);
  
  
  printf("2\n\r");

  // Configure PWMC channel 0 (left-aligned)
  PWMC_ConfigureChannel(CHANNEL_PWM0, AT91C_PWMC_CPRE_MCKA, 0, 0);
  PWMC_SetPeriod(CHANNEL_PWM0, MAX_DUTY_CYCLE);
  PWMC_SetDutyCycle(CHANNEL_PWM0, 3);
    

  //моргаем светодиодом для проверки работоспособности
    unsigned long i;
  for(i = 0; i < 25; i++)
  {
    m_pPio->PIO_CODR = BIT18;    
    Delay(1000000);
    m_pPio->PIO_SODR = BIT18;  
    Delay(1000000);
  }
  

  
   // Configure interrupt on PWM channels #0
  IRQ_ConfigureIT(AT91C_ID_PWMC, 0, ISR_Pwmc);
  
  IRQ_EnableIT(AT91C_ID_PWMC);

  PWMC_EnableChannelIt(CHANNEL_PWM0);

  PWMC_EnableChannel(CHANNEL_PWM0);

//__enable_interrupt(); //пробовал, непомогло


  
  printf("9\n\r");
      
    // Main loop
    while (1)
      {

                      
      }
}

kumle
Вроде сам начинаю понимать что к чему:
Так как гружу bin через самбу в sram, то ставлю адрес начала 202000h, а не 200000h (чтобы при загрузке не затереть самбу) а так как вектор IRQ раположен по адресу 018h, то после команды REMAP естественно процессор не может перейти на мой обработчик прерывания!


Вот на at91.com наткнулся на решение похожей на мою проблемы:

Just reporting.


The board I'm using is a AT91SAM7S-EK with a AT91SAM7S64 chip. In this board, RAM is mapped at 0x200000 and there is a Remap feature that allows RAM to be accessed from 0x000000. The exception handler is located at 0x000000 (IRQ Handler lies at 0x000018).


After more than one month stuck and trying to figure out the problem (btw I have never used GNU Tools nor had any experience with ARM embedded programing), I found that the Linker Script provided by Atmel in Getting-Started-Project-GNU maps RAM at 0x202000, I don't know why. This way, the processor couldn't find the irqHandler (from C Startup assembler code) at 0x000018.


After fixing the Linker Script and after dealing hard with JTAG/Eclipse/Remote GDB I finally could use interrupt.

вот ссылка на обсуждение



Тогда, если я правильно понял, с помощью самбы приложение использующее прерывания нельзя корректно загрузить и выполнить в sram ?

Поправьте меня пожалуйста если что нетак!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.