4

NXP LPC1850 評価ボード用に作成したソフトウェアをデバッグしようとしています。現時点では、コードを停止すると、C コードのどこにあるのかわかりませんが、逆アセンブラー ウィンドウには表示されます。

ハングしている行はアドレス 0x40 にあります。命令は BN です。ARM インフォメーション センターで調べましたが、アセンブラについては何も知りません。

      0x0: 0x9ff0         LDR       R7, [SP, #0x3c0]
      0x2: 0x1008         ASRS      R0, R1, #32
      0x4: 0x2bad         CMP       R3, #173                ; 0xad
      0x6: 0x1040         ASRS      R0, R0, #1
      0x8: 0x0041         LSLS      R1, R0, #1
      0xa: 0x1040         ASRS      R0, R0, #1
      0xc: 0x0043         LSLS      R3, R0, #1
      0xe: 0x1040         ASRS      R0, R0, #1
     0x10: 0x0045         LSLS      R5, R0, #1
     0x12: 0x1040         ASRS      R0, R0, #1
     0x14: 0x0047         LSLS      R7, R0, #1
     0x16: 0x1040         ASRS      R0, R0, #1
     0x18: 0x0049         LSLS      R1, R1, #1
     0x1a: 0x1040         ASRS      R0, R0, #1
     0x1c: 0x0000         MOVS      R0, R0
     0x1e: 0x0000         MOVS      R0, R0
     0x20: 0x0000         MOVS      R0, R0
     0x22: 0x0000         MOVS      R0, R0
     0x24: 0x0000         MOVS      R0, R0
     0x26: 0x0000         MOVS      R0, R0
     0x28: 0x0000         MOVS      R0, R0
     0x2a: 0x0000         MOVS      R0, R0
     0x2c: 0x004b         LSLS      R3, R1, #1
     0x2e: 0x1040         ASRS      R0, R0, #1
     0x30: 0x004d         LSLS      R5, R1, #1
     0x32: 0x1040         ASRS      R0, R0, #1
     0x34: 0x0000         MOVS      R0, R0
     0x36: 0x0000         MOVS      R0, R0
     0x38: 0x004f         LSLS      R7, R1, #1
     0x3a: 0x1040         ASRS      R0, R0, #1
     0x3c: 0x1645         ASRS      R5, R0, #25
     0x3e: 0x1040         ASRS      R0, R0, #1
     0x40: 0xe7fe         B.N       0x40
     0x42: 0xe7fe         B.N       0x42
     0x44: 0xe7fe         B.N       0x44
     0x46: 0xe7fe         B.N       0x46
     0x48: 0xe7fe         B.N       0x48
     0x4a: 0xe7fe         B.N       0x4a
     0x4c: 0xe7fe         B.N       0x4c
     0x4e: 0xe7fe         B.N       0x4e
     0x50: 0x0000         MOVS      R0, R0
     0x52: 0x0000         MOVS      R0, R0
     0x54: 0x0000         MOVS      R0, R0
     0x56: 0x0000         MOVS      R0, R0
     0x58: 0x0000         MOVS      R0, R0
     0x5a: 0x0000         MOVS      R0, R0
     0x5c: 0x0000         MOVS      R0, R0
     0x5e: 0x0000         MOVS      R0, R0

誰かが何が起こっているのか、そしておそらくその時点でプログラムがハングしている理由を説明できれば、私は非常に感謝しています.

編集:以下にCコードを追加

#include "NXP\iolpc4350.h"
#include "stdint.h"
#include "modules\i2c_drv.h"
#include "modules\drv_nvic.h"

#define IRC_FREQ       12000000
#define XTAL_FREQ      12000000

//nt32_t ClockFrequency;

uint32_t I2C0_PCLK;

unsigned char Data[2];

#define MULTF 15

#define PCA9502_ADDR  0x4D

volatile uint8_t flag0=0;

#define flTick               ( flag0 )
#define flTickSet()          ( flag0 = 0xFF )
#define flTickClear()        ( flag0 = 0x00 )

/*************************************************************************
 * Function Name: InitClock
 * Parameters: none
 *
 * Return: none
 *
 * Description: Initialize PLL and clock dividers. FCCO = 320MHz,
 *              PLL1_OUT = 160MHz
 *
 *************************************************************************/
void InitClock(void)
{
  /* 1. Init XTAL OSC */
  CGU_XTAL_OSC_CTRL_bit.HF = 0;       /* Xtal.freq is between 1MHz and 15MHZ */
  CGU_XTAL_OSC_CTRL_bit.BYPASS = 0;   /* Xtal.osc is connected */
  CGU_XTAL_OSC_CTRL_bit.ENABLE = 0;   /* Xtal.osc is enabled */

  /* 2.  Wait for OSC ready > 2ms */
  for(volatile uint32_t j = 20000; j; j--);

  /* 3. Switch to OSC clk */
  /* BASE_M4_CLK */
  CGU_BASE_M4_CLK = (1ul  << 11)      /* Autoblock during freq.change enabled */
                  | (6ul  << 24)      /* Source is XTAL osc. */
                    ;
  /* BASE_APB1_CLK */
  CGU_BASE_APB1_CLK = (1ul  << 11)    /* Autoblock during freq.change enabled */
                    | (6ul  << 24)    /* Source is XTAL osc. */
                    ;
  /* BASE_APB3_CLK */
  CGU_BASE_APB3_CLK = (1ul  << 11)    /* Autoblock during freq.change enabled */
                    | (6ul  << 24)    /* Source is XTAL osc. */
                    ;
  /* BASE_SPIFI_CLK */
  CGU_BASE_SPIFI_CLK = (1ul  << 11)   /* Autoblock during freq.change enabled */
                     | (6ul  << 24)   /* Source is XTAL osc. */
                    ;

  /* 4. Init PLL1 - In clk - OSC (12MHz)
     N = 3, M = 80, P = 1 VCO - 320MHz, PLL1 OUT - 160MHz */
  CGU_PLL1_CTRL_bit.PD = 1;           /* Power down PLL1 */
  CGU_PLL1_CTRL_bit.BYPASS = 0;       /* CCO clock sent to post-dividers */
  CGU_PLL1_CTRL_bit.DIRECT = 0;       /* Direct CCO output disabled */
  CGU_PLL1_CTRL_bit.FBSEL = 0;        /* CCO output as feedback divider */
  CGU_PLL1_CTRL_bit.PSEL = 1-1;       /* Post divider P = 1 */
  CGU_PLL1_CTRL_bit.NSEL = 3-1;       /* N = 3 */
  CGU_PLL1_CTRL_bit.MSEL = 80-1;      /* M = 80 */
  CGU_PLL1_CTRL_bit.CLK_SEL = 6;      /* Source is XTAL osc. */
  CGU_PLL1_CTRL_bit.AUTOBLOCK = 1;    /* Autoblock during freq.change enabled */

  /* 5. Enable PLL1 */
  CGU_PLL1_CTRL_bit.PD = 0;           /* Power up (enable) PLL1 */

  /* 5. Wait for the PLL1 to achieve lock */
  while(!CGU_PLL1_STAT_bit.LOCK);

  /* 6. Dividers */
  /* IDIVA - /4 input 160MHz, output 40MHz */
  CGU_IDIVA_CTRL_bit.AUTOBLOCK = 1;   /* Autoblock during freq.change enabled */
  CGU_IDIVA_CTRL_bit.IDIV = 4-1;      /* IDIV = 4 */
  CGU_IDIVA_CTRL_bit.CLK_SEL = 9;     /* Source is PLL1 */
  CGU_IDIVA_CTRL_bit.PD = 0;          /* Enable IDIVA */

  /* 7. Init Clock output stages */
  /* BASE_M4_CLK, APB0, APB2 - 160MHz */
  CGU_BASE_M4_CLK = (1ul  << 11)      /* Autoblock during freq.change enabled */
                  | (9ul  << 24)      /* Source is PLL1 */
                    ;
  /* BASE_APB1_CLK - 160MHz*/
  CGU_BASE_APB1_CLK = (1ul  << 11)    /* Autoblock during freq.change enabled */
                    | (9ul << 24)     /* Source is PLL1 */
                    ;
  /* BASE_SPIFI_CLK - 40MHz */
  CGU_BASE_SPIFI_CLK = (1ul  << 11)   /* Autoblock during freq.change enabled */
                     | (12ul << 24)   /* Source is IDIVA */
                    ;
  /* Enable M4 Bus clock */
  CCU1_CLK_M4_BUS_CFG_bit.RUN = 1;

  /* Enable APB 1 Bus clock */
  CCU1_CLK_APB1_BUS_CFG_bit.RUN = 1;

  /* Enable SCU clock */
  CCU1_CLK_M4_SCU_CFG_bit.RUN = 1;

  /* Set I2C0 module frequency = APB1 freq */
  I2C0_PCLK = 160000000;
}

/*************************************************************************
 * Function Name: RIT_IRQHandler
 * Parameters: none
 *
 * Return: none
 *
 * Description: Repetitive interrupt timer handler
 *
 *************************************************************************/
void RITIMER_IRQHandler(void)
{
    flTickSet();
    /* Clear interrupt */
    RIT_CTRL_bit.RITINT = 1;
    NVIC_ClearPendingIRQ(NVIC_RITIMER);
}

/*************************************************************************
 * Function Name: RIT_Init
 * Parameters: none
 *
 * Return: none
 *
 * Description: Initialization of repetitive interrupt timer
 *
 *************************************************************************/
void RITIMER_Init(void)
{
  /* Value for 0.25s timer interrupt @ 180MHz timer clock */
  RIT_COUNTER = 0;
  RIT_COMPVAL = 0x2AEA540;
  RIT_CTRL_bit.RITEN = 1;
  RIT_CTRL_bit.RITENCLR = 1;
  /* Enable interrupt */
  NVIC_EnableIRQ(NVIC_RITIMER);
  NVIC_SetPriority(NVIC_RITIMER, 16);
}

/*************************************************************************
 * Function Name: main
 * Parameters: none
 *
 * Return: none
 *
 * Description: main
 *
 *************************************************************************/
int main()
{
  // Configures Clock Generation Unit
  InitClock();
  // Force a RESET to Cortex-M0
  RGU_RESET_CTRL1 = ~RGU_RESET_ACTIVE_STATUS1 | RGU_RESET_CTRL1_M0APP_RST;
  // Configures Repetitve Interrupt Timer
  RITIMER_Init();
  // Configure the onboard LED - GPIO4.1
  GPIO_CLR4 = 1 << 1;
  GPIO_DIR4 |= 1 << 1;
  // Init I2C
  I2C_InitMaster(400000);

  // Everything below this line I have added in myself - Mitchell

  /* Configure PC_11 and PC_12 to serve as
     GPIO6[10] and GPIO6[11] to act as data select
     for SPP0_SSEL multiplexer

     1. Set as outputs
     2. Choose INTLCD_SSEL (option 0) as output by clearing both outputs
     3. Configure both pins as GPIO
  */

  // 1
  GPIO_DIR6 |= 0x0C;

  // 2
  GPIO_PIN6 &= ~0x0C;;

  // 3
  SCU_SFSPC_11_bit.MODE = 4;
  SCU_SFSPC_12_bit.MODE = 4;

  // Set LCD_RST to reset the LCD
  RGU_RESET_CTRL0 |= RGU_RESET_CTRL0_LCD_RST;
  // LCD_RST autoclears when complete
  // wait until this done before moving on
  while(RGU_RESET_STATUS1_bit.LCD_RST == 1);

  /* SPI slave select is an active low signal.
     This means that to communicate with the onboard LCD,
     SSP0_SSEL must be cleared
  */


  while(1)
  {

  }
}
4

3 に答える 3

6

Cortex-M3 では、最下位アドレスはコードではなく、ベクタ テーブルです。たとえば、0 のエントリは のリセット値でありSP、4 はリセットPCであり、次のエントリはさまざまな例外です。ダンプをデータとして再解釈すると、次のようになります。

00 DCD 0x10089FF0
04 DCD 0x10402BAD
08 DCD 0x10400041
0C DCD 0x10400043
10 DCD 0x10400045
14 DCD 0x10400047
18 DCD 0x10400049
1C DCD 0
20 DCD 0
24 DCD 0
28 DCD 0
2C DCD 0x1040004B
30 DCD 0x1040004D
34 DCD 0
38 DCD 0x1040004F
3C DCD 0x10401645

コードが 10400000 から実行するようにリンクされていることが明らかになります。それを考慮して整数をオフセットに変換すると、次のようになります。

00  DCD 0x10089FF0          ; Initial SP
04  DCD 0x10402BAD          ; reset PC
08  DCD loc_10400040+1      ; NMI handler
0C  DCD loc_10400042+1      ; Hard Fault handler
10  DCD loc_10400044+1      ; MPU Fault Handler
14  DCD loc_10400046+1      ; Bus Fault Handler
18  DCD loc_10400048+1      ; Usage Fault Handler
1C  DCD 0
20  DCD 0
24  DCD 0
28  DCD 0
2C  DCD loc_1040004A+1      ; SVCall Handler
30  DCD loc_1040004C+1      ; Debug Monitor Handler
34  DCD 0
38  DCD loc_1040004E+1      ; PendSV Handler
3C  DCD 0x10401645          ; SysTick Handler

40 loc_10400040
40   B loc_10400040

(ターゲットが Thumb コードであることを示すために、Cortex-M3 のコード ポインタにビット 0 を設定する必要があるため、オフセットは +1 になります。)

は、逆アセンブルのにloc_10400040対応します。B.N 0x40したがって、どうやら、NMI ハンドラーに行き着いたようです。

LPC18xx ユーザー マニュアルを確認すると、NMI はピンP4_0またはピンによってのみトリガーできるようPE_4です。ボードの回路図や GPIO 構成コードを再確認することをお勧めします。

于 2013-07-29T10:51:38.393 に答える
0
  • まず、すべての最適化がオフになっていることを確認する必要があります (プロジェクト オプションを調べます)。最適化が何をしているのか興味がある場合は、それらをオフにしてから一度に 1 つずつ導入し、アセンブリがどのように変化するかを観察してください。

  • これらの MOVS 命令は、本質的に実行遅延を提供する NOP として機能しているようです。これらは、コンパイラの最適化の結果として、1 つ以上の while ループを置き換えている可能性があります。
    • インライン遅延命令はより最適であり、コンパイラが遅延を事前に決定できると判断した場合は、循環条件分岐 (while ループ) を置き換えることがあります。

  • コメントに記載されているように、BN 命令は無限ループを提供しています。実際には、メインの最後に、コードに少なくとも 1 つの無限ループがあります。
于 2013-08-14T14:03:13.020 に答える