Страницы

Страницы

воскресенье, 6 сентября 2015 г.

Software RESET fot Cortex & STM32

In the library source file stm32f10x_nvic.c :

#define AIRCR_VECTKEY_MASK    ((u32)0x05FA0000)
/*******************************************************************************
* Function Name  : NVIC_GenerateSystemReset
* Description    : Generates a system reset.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void NVIC_GenerateSystemReset(void)
{
  SCB->AIRCR = AIRCR_VECTKEY_MASK | (u32)0x04;
}

or

    ldr     r0,=0xE000ED0C ; SCB AIRCR
    ldr     r1,=0x05FA0004
    str     r1, [r0, #0]

Other variant :

SystemReset     PROC
                EXPORT  SystemReset
                ldr     r1, =0xE000ED0C ; NVIC Application Interrupt and Controller
                ldr     r0, =0x05FA0004 ; Magic
                str     r0, [r1, #0]    ; Reset
self            b       self
                bx      lr
                ENDP

Saw a function in core_cm3.h. Didn't use it though.

/*    This function initiate a system reset request to reset the MCU. */
static __INLINE void NVIC_SystemReset(void)
{
  __DSB();                                                     /* Ensure all outstanding memory accesses included
                                                                  buffered write are completed before reset */
  SCB->AIRCR  = ((0x5FA << SCB_AIRCR_VECTKEY_Pos)      |
                 (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
                 SCB_AIRCR_SYSRESETREQ_Msk);                   /* Keep priority group unchanged */
  __DSB();                                                     /* Ensure completion of memory access */
  while(1);                                                    /* wait until reset */
}

суббота, 5 сентября 2015 г.

Hard Fault Handler for Cortex M4 & M3

In the Vector table you’ll see something like this

  .word  _estack
  .word  Reset_Handler
  .word  NMI_Handler
  .word  HardFault_Handler
  .word  MemManage_Handler
  .word  BusFault_Handler
  .word  UsageFault_Handler

We need to add the C code

void hard_fault_handler_c (unsigned int * hardfault_args)
{
  unsigned int stacked_r0;
  unsigned int stacked_r1;
  unsigned int stacked_r2;
  unsigned int stacked_r3;
  unsigned int stacked_r12;
  unsigned int stacked_lr;
  unsigned int stacked_pc;
  unsigned int stacked_psr;
 
  stacked_r0 = ((unsigned long) hardfault_args[0]);
  stacked_r1 = ((unsigned long) hardfault_args[1]);
  stacked_r2 = ((unsigned long) hardfault_args[2]);
  stacked_r3 = ((unsigned long) hardfault_args[3]);
 
  stacked_r12 = ((unsigned long) hardfault_args[4]);
  stacked_lr = ((unsigned long) hardfault_args[5]);
  stacked_pc = ((unsigned long) hardfault_args[6]);
  stacked_psr = ((unsigned long) hardfault_args[7]);
 
  printf ("\n\n[Hard fault handler - all numbers in hex]\n");
  printf ("R0 = %x\n", stacked_r0);
  printf ("R1 = %x\n", stacked_r1);
  printf ("R2 = %x\n", stacked_r2);
  printf ("R3 = %x\n", stacked_r3);
  printf ("R12 = %x\n", stacked_r12);
  printf ("LR [R14] = %x  subroutine call return address\n", stacked_lr);
  printf ("PC [R15] = %x  program counter\n", stacked_pc);
  printf ("PSR = %x\n", stacked_psr);
  printf ("BFAR = %x\n", (*((volatile unsigned long *)(0xE000ED38))));
  printf ("CFSR = %x\n", (*((volatile unsigned long *)(0xE000ED28))));
  printf ("HFSR = %x\n", (*((volatile unsigned long *)(0xE000ED2C))));
  printf ("DFSR = %x\n", (*((volatile unsigned long *)(0xE000ED30))));
  printf ("AFSR = %x\n", (*((volatile unsigned long *)(0xE000ED3C))));
  printf ("SCB_SHCSR = %x\n", SCB->SHCSR);
 
  while (1);
}

вторник, 1 сентября 2015 г.

SPL

Практически вся (если не вообще вся) периферия настраивается примерно одинаково, различия имеются только в специфических для каждого устройства параметрах и командах. Приведу пример: 

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init( GPIOC , &GPIO_InitStructure);

Это пример настройки порта ввода-вывода (GPIO). Рассмотрим его поподробнее.

1. Включение тактирования периферийного устройства


Первым делом на порт подаётся тактирование: 

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

Периферийные устройства тактируется либо от шины APB2, либо от APB1. От какой именно, можно узнать по названию константы. В нашем случае это RCC_APB2Periph_GPIOC, стало быть шина — APB2. Константа расположена в файлеstm32f10x_rcc.h, давайте найдем ее. В Eclipse для этого достаточно щелкнуть мышкой по константе, зажав Ctrl. 

Вот что мы находим в stm32f10x_rcc.h: 

#define RCC_APB2Periph_AFIO              ((uint32_t)0x00000001)
#define RCC_APB2Periph_GPIOA             ((uint32_t)0x00000004)
#define RCC_APB2Periph_GPIOB             ((uint32_t)0x00000008)
#define RCC_APB2Periph_GPIOC             ((uint32_t)0x00000010)
#define RCC_APB2Periph_GPIOD             ((uint32_t)0x00000020)
......
#define RCC_APB1Periph_TIM13             ((uint32_t)0x00000080)
#define RCC_APB1Periph_TIM14             ((uint32_t)0x00000100)
#define RCC_APB1Periph_WWDG              ((uint32_t)0x00000800)
#define RCC_APB1Periph_SPI2              ((uint32_t)0x00004000)
#define RCC_APB1Periph_SPI3              ((uint32_t)0x00008000)
#define RCC_APB1Periph_USART2            ((uint32_t)0x00020000)
...

Поблизости можно найти все необходимые нам константы для запуска тактирования любого периферийного устройства. К примеру, если мы хотим воспользоваться USART2, мы воспользуемся константой RCC_APB1Periph_USART2, а поскольку из её названия видно, что USART2 тактируется от шины APB1, включение тактирования мы произведем следующим образом:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

Не забывайте, что одним вызовом функции можно включить тактирование сразу несколько устройств, задав в параметре функции несколько констант через операторпобитовое ИЛИ:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC 
  | RCC_APB2Periph_ADC1, ENABLE);

Побитовое ИЛИ «соберёт» все единички из перечисленных констант, а сами константы, как вы уже догадались, являются маской, как раз предназначенной для такого использования.

Обратите внимание, что в некоторых случаях может потребоваться дополнительная настройка, например, для АЦП необходимо выставить предделитель частоты:

RCC_ADCCLKConfig(RCC_PCLK2_Div6);

Максимальная тактовая частота для АЦП составляет 12 МГц, это необходимо учесть при выборе предделителя. 

Идём дальше.