Ярлыки

_GetPixelIndex (1) _SetPixelIndex (1) 3-phase (1) 800x480 (1) АЦП (1) генератор (1) синхронный усилитель (2) структура (1) учебный курс (1) шаговый двигатель (1) ШИМ (2) accert (1) AD7608 (1) AD8429 (1) ADC (5) amplifer (1) arccos (1) arcsin (1) arctang (2) arctg (3) ARM (2) arm_sqrt_q15 (2) assembler (6) ASSERT (1) atan (2) bit (1) Bitband (1) boot (3) bootlloader (1) BUTTON (1) C (5) C# (1) CAN (2) CC2530 (5) CMSIS (4) command (1) Cordic (1) Core746I (1) CubeMX (4) DBGMCU (2) debug (2) debug.ini (1) delegate (1) Digital Potentiometers (1) DigitalPOT (1) Discovery (1) DMA (9) DMA2D (1) DSP (1) DSP library (1) DWT (1) EFM32 (5) EmWin (9) EXTI (1) FATFS (1) FMC (2) FreeRTOS (2) gl868-dual cmux (1) GPIO (4) GUI (2) GUIBuilder (1) GUIDRV_CompactColor_16 (1) HAL (3) HappyGecko (1) Hard Fault (2) heap (1) I2C (1) ID (1) ILI9320 (1) ILI9325 (1) Initialisation (1) InitLTDC (1) Instrumentithion (1) Interrupt (4) ITR (1) JTAG (1) Keil (5) LCDConf (2) lock-in (1) LTCD (1) LTDC (3) main (1) memory (1) MINI_STM32 Revision 01 (1) nBoot0 (1) NVIC (1) OnePulse (2) OSAL (4) pack (1) phase (1) printf (3) Pulse (1) PWM (12) RCC (2) RCR (1) Register (1) RESET (2) RS232 (3) RSS (1) RTC (3) RTOS-RTX (1) RTT (1) RTX-RTOS (1) SDCard (1) SDRAM (6) Segger (2) SPI (3) sqrt (3) SSD1298 (1) SSD1963 (1) Standart Peripherial Library (3) STANDBAY (1) startup (1) STemWin (8) stepper motor (1) STlink (2) STM32 (17) STM32429ZI (1) STM32Cube (1) STM32DBG.IN (1) STM32F (28) STM32F0 (4) STM32F1 (13) STM32F4 (10) STM32F4 Discovery (1) STM32F407ZG (1) STM32F429 (2) STM32F746 (1) STOP (1) string (1) struct (1) SWD (1) SWD JTAG (1) Synhronization (1) system_stm32f4xx.c (1) SystemInit (1) SysTick (1) task (4) telit (1) TIM (27) typedef (1) UART (1) USART (9) viewer (2) WM_PAINT (1) Z-stack (5) ZigBee (5)

воскресенье, 13 ноября 2016 г.

EFM32 UART DMA Tx

#include "em_device.h"
#include "em_chip.h"
#include "em_usart.h"
#include "em_gpio.h"
#include "em_dma.h"
#include "em_cmu.h"
#include "em_emu.h"
#include "em_timer.h"
#include "em_int.h"
#include "em_prs.h"
#include "InitDevice.h"

#define DMA_CHANNEL_UART_TX    0  //
/* DMA init structure */
DMA_Init_TypeDef dmaInit;
/* DMA callback structure */
DMA_CB_TypeDef cb[DMA_CHAN_COUNT];//DMA_CHAN_COUN????
/** DMA control block, requires proper alignment. */
DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMA_CHAN_COUNT * 2] __attribute__ ((aligned(256)));

uint8_t  ucComplete = 0;
uint8_t  Tx_buffer[8] = {0x30,0x31,0x32,0x33,0x34,0x35,0x0D,0x0A};

void UARTTxTransferComplete(unsigned int channel, bool primary, void *user)
{
    ucComplete = 1;
 GPIO_PinOutToggle(gpioPortE, 12);
}

void DMA_for_UART_Tx(void)
{
    DMA_CfgChannel_TypeDef  chnlCfg;
    DMA_CfgDescr_TypeDef    descrCfg;
 
    /* Setting up call-back function */
    cb[DMA_CHANNEL_UART_TX].cbFunc = UARTTxTransferComplete; //Set DMA is completed, whether to call the callback function. If there is no callback function, it is set to NULL
    cb[DMA_CHANNEL_UART_TX].userPtr = NULL;
 
    /* Setting up channel */
    chnlCfg.highPri = false;
    chnlCfg.enableInt = true;
    //Set the DMA to send the next byte of the conditions, here is: When the Tx is completed, DMA then start to take down a byte to send
    chnlCfg.select = DMAREQ_USART1_TXEMPTY;
 
    //Initializes the function of the callback part of the DMA register
    chnlCfg.cb = &(cb[DMA_CHANNEL_UART_TX]);
    DMA_CfgChannel(DMA_CHANNEL_UART_TX, &chnlCfg);
 
    //Register that defines the logical portion of the DMA
    /* Setting up channel descriptor */
    descrCfg.dstInc = dmaDataIncNone;   //Meaning of the target address unchanged
    descrCfg.srcInc = dmaDataInc1;      //This means that the source address is incremented by one byte at a time
    descrCfg.size = dmaDataSize1;       //The byte unit of each transmission
    descrCfg.arbRate = dmaArbitrate1;   //DMA arbitration, one arbitration for every 1 byte sent
    descrCfg.hprot = 0;
    DMA_CfgDescr(DMA_CHANNEL_UART_TX, true, &descrCfg);
}
void DMAInit(void)
{
    CMU_ClockEnable(cmuClock_DMA, true);
  /* Initializing the DMA */
  dmaInit.hprot = 0;
  dmaInit.controlBlock = dmaControlBlock;
  DMA_Init(&dmaInit);
}

int main(void)
{
/* Initialize chip */
CHIP_Init();
enter_DefaultMode_from_RESET();
GPIO_PinModeSet(gpioPortE, 12,  gpioModePushPullDrive, 0); /* TX */
DMAInit();
DMA_for_UART_Tx();
ucComplete = 1;
GPIO_PinOutSet(DE_PORT, DE_PIN);
/* Infinite blink loop */
while(1)
  {
  if(ucComplete)
    {
GPIO_PinOutSet(DE_PORT, DE_PIN);          
    DMA_ActivateBasic(DMA_CHANNEL_UART_TX,
      true,
      false,
      (void *)&(USART1->TXDATA),
      (void *)&Tx_buffer,
      sizeof(Tx_buffer) - 1);
    ucComplete = 0;
    }
  }
}

среда, 9 ноября 2016 г.

EFM32 Peripheral Reflex System (PRS)

   PRS позволяет периферийным устройствам общаться друг с другом, без участия процессора, даже когда он находится в состоянии сна. В качестве сигнала используется передача уровня или импульса (level or pulse).

  Producers, consumers and channels (Источники, приемники и каналы)
 
  Перефирийные устройства, которые создают сигналы называют источниками (produsers), а принимающие их приемниками (consumers). PRS для EFM32 в зависимости от серии содержит до 12 каналов для передачи сигналов, каждый из которых может быть подключен к любому источнику и к любому приемнику. Некоторые приемники способны принимать уровень сигнала, но большинство реагирует только на фронт имрульсного сигнала. Канал можно сконфигурировать с помощью emlib функции

 void PRS_SourceSignalSet(unsigned int ch, uint32_t source, uint32_t signal, PRS_Edge_TypeDef  edge)

/***************************************************************************//**
 * @brief
 *   Set source and signal to be used for a channel.
 *
 * @param[in] ch
 *   Channel to define signal and source for.
 *
 * @param[in] source
 *   Source to select for channel. Use one of PRS_CH_CTRL_SOURCESEL_x defines.
 *
 * @param[in] signal
 *   Signal (for selected @p source) to use. Use one of PRS_CH_CTRL_SIGSEL_x
 *   defines.
 *
 * @param[in] edge
 *   Edge (for selected source/signal) to generate pulse for.
 ******************************************************************************/
void PRS_SourceSignalSet(unsigned int ch,
                         uint32_t source,
                         uint32_t signal,
                         PRS_Edge_TypeDef edge)

Эта функция задает PRS каналы по которым будут передавться сигналы между периферийными устройствами. Сигналы можно генерировать и программно с помощью регистров PRS_SWPULSE и PRS_SWLEVEL.


EFM32 Timer frequency meter

// $[TIMER0...3  initialization]
TIMER_Init_TypeDef init = TIMER_INIT_DEFAULT;

init.enable = 1;
init.debugRun = 0;
init.dmaClrAct = 0;
init.sync = 0;
init.clkSel = timerClkSelHFPerClk;
init.prescale = timerPrescale1;
init.fallAction = timerInputActionNone;
init.riseAction = timerInputActionNone;
init.mode = timerModeUp;
init.quadModeX4 = 0;
init.oneShot = 0;
init.count2x = 0;
init.ati = 0;
TIMER_Init(TIMER3, &init);
// [TIMER0...3  initialization]$


// $[TIMER CC0 ... CC2 init]
TIMER_InitCC_TypeDef initCC0 = TIMER_INITCC_DEFAULT;

initCC0.prsInput = false;
initCC0.prsSel = timerPRSSELCh0;
initCC0.edge = timerEdgeRising;
initCC0.mode = timerCCModeOff;
initCC0.eventCtrl = timerEventEveryEdge;
initCC0.filter = 0;
initCC0.cofoa = timerOutputActionNone;
initCC0.cufoa = timerOutputActionNone;
initCC0.cmoa = timerOutputActionNone;
initCC0.coist = 0;
initCC0.outInvert = 0;
TIMER_InitCC(TIMER3, 0, &initCC0);
// [TIMER CC0 ... CC2 init]$

вторник, 8 ноября 2016 г.

EFM32 Timer pulse generate with & without IRQ

// with IRQ (GPIO output)

/**************************************************************************//**
 * @brief TIMER0_IRQHandler
 * Interrupt Service Routine TIMER0 Interrupt Line
 *****************************************************************************/
void TIMER0_IRQHandler(void)
{
  /* Clear flag for TIMER0 overflow interrupt */
  TIMER_IntClear(TIMER0, TIMER_IF_OF);

  /* Toggle LED ON/OFF */
  GPIO_PinOutToggle(gpioPortC, 0);
}
/**************************************************************************//**
 * @brief  Main function
 * Main is called from __iar_program_start, see assembly startup file
 *****************************************************************************/
int main(void)
{
  /* Initialize chip */
  CHIP_Init();
 
  /* Enable clock for GPIO module */
  CMU_ClockEnable(cmuClock_GPIO, true);

  /* Enable clock for TIMER0 module */
  CMU_ClockEnable(cmuClock_TIMER0, true);

  /* Configure pin as push pull output for LED/pin drive */
  GPIO_PinModeSet(LED_PORT, LED_PIN, gpioModePushPullDrive, 0);

  /* Select TIMER0 parameters */
  TIMER_Init_TypeDef timerInit =
  {
    .enable     = true,
    .debugRun   = true,
    .prescale   = timerPrescale1024,
    .clkSel     = timerClkSelHFPerClk,
    .fallAction = timerInputActionNone,
    .riseAction = timerInputActionNone,
    .mode       = timerModeUp,
    .dmaClrAct  = false,
    .quadModeX4 = false,
    .oneShot    = false,
    .sync       = false,
  };

  /* Enable overflow interrupt */
  TIMER_IntEnable(TIMER0, TIMER_IF_OF);

  /* Enable TIMER0 interrupt vector in NVIC */
  NVIC_EnableIRQ(TIMER0_IRQn);

  /* Set TIMER Top value */
  TIMER_TopSet(TIMER0, TOP);

  /* Configure TIMER */
  TIMER_Init(TIMER0, &timerInit);

  while(1)
  {
    /* Go to EM1 */
    EMU_EnterEM1();
  }

}


//without IRQ (TIMER output)

/**************************************************************************//**
 * @brief  Main function
 * Main is called from __iar_program_start, see assembly startup file
 *****************************************************************************/
int main(void)
{
  /* Initialize chip */
  CHIP_Init();
   
  /* Enable clock for GPIO module */
  CMU_ClockEnable(cmuClock_GPIO, true);
 
  /* Enable clock for TIMER0 module */
  CMU_ClockEnable(cmuClock_TIMER0, true);
 
  /* Set CC0 location 3 pin (PD1) as output */
  GPIO_PinModeSet(gpioPortD, 1, gpioModePushPull, 0);

  /* Select CC channel parameters */
  TIMER_InitCC_TypeDef timerCCInit =
  {
    .cufoa      = timerOutputActionNone,
    .cofoa      = timerOutputActionToggle,
    .cmoa       = timerOutputActionNone,
    .mode       = timerCCModeCompare,
    .filter     = true,
    .prsInput   = false,
    .coist      = false,
    .outInvert  = false,
  };
 
  /* Configure CC channel 0 */
  TIMER_InitCC(TIMER0, 0, &timerCCInit);

  /* Route CC0 to location 3 (PD1) and enable pin */
  TIMER0->ROUTE |= (TIMER_ROUTE_CC0PEN | TIMER_ROUTE_LOCATION_LOC3);
 
  /* Set Top Value */
  TIMER_TopSet(TIMER0, TOP);
 
  /* Select timer parameters */
  TIMER_Init_TypeDef timerInit =
  {
    .enable     = true,
    .debugRun   = true,
    .prescale   = timerPrescale64,
    .clkSel     = timerClkSelHFPerClk,
    .fallAction = timerInputActionNone,
    .riseAction = timerInputActionNone,
    .mode       = timerModeUp,
    .dmaClrAct  = false,
    .quadModeX4 = false,
    .oneShot    = false,
    .sync       = false,
  };
 
  /* Configure timer */
  TIMER_Init(TIMER0, &timerInit);
 
  while(1)
  {
    /* Go to EM1, while TIMER tuns compare output */
    EMU_EnterEM1();
  }
 
}



пятница, 21 октября 2016 г.

STM32F ADC with DMA on CMSIS

void DMA2_Stream4_IRQHandler(void)
{
        
GPIOD->ODR        ^=((1<<12)|(1<<13)|(1<<14)|(1<<15));
}
uint16_t BUFF[100];int main(void)
{
    
SystemInit();
//*********************GPIO*************************
        
RCC->AHB1ENR    |= RCC_AHB1ENR_GPIOAEN;
        
RCC->AHB1ENR    |= RCC_AHB1ENR_GPIODEN;
        
GPIOA->MODER    |= GPIO_MODER_MODER6;        //ADC1 CH6 PA6


//*********************TIM3*************************
        
RCC->APB1ENR    |= RCC_APB1ENR_TIM3EN;        // тактирование таймера
        
TIM3->PSC         160-1;                    // предделитель
        
TIM3->ARR         1000-1;                    // переполнение
        
TIM3->CR2         |= TIM_CR2_MMS_1;            // output (TRGO)
        
TIM3->DIER         |= TIM_DIER_UDE;
        
TIM3->CR1         |= TIM_CR1_CEN;                //запуск счета


//********************DMA***************************
        
RCC->AHB1ENR    |= RCC_AHB1ENR_DMA2EN;
        
DMA2_Stream4->CR&=~ DMA_SxCR_CHSEL;            // 000: channel 0 selected
        
DMA2_Stream4->PAR= (uint32_t)&ADC1->DR;     //
        
DMA2_Stream4->M0AR=(uint32_t)&BUFF[0];        // Массив
        
DMA2_Stream4->NDTR=100;                        // Длина буфера
        
DMA2_Stream4->CR|= DMA_SxCR_MINC;            // Инкремент адреса
        
DMA2_Stream4->CR|= DMA_SxCR_MSIZE_0;        // 16 бит
        
DMA2_Stream4->CR|= DMA_SxCR_PSIZE_0;        // 16 бит
        
DMA2_Stream4->CR|= DMA_SxCR_CIRC;            // Непрерывный режим
        
DMA2_Stream4->CR&=~ DMA_SxCR_DIR;            // 01: peripheral-to-Memory
        
DMA2_Stream4->CR|= DMA_SxCR_PL;                // 11: Very high приоритет
        
DMA2_Stream4->CR|= DMA_SxCR_TCIE;            // Transfer complete interrupt enable
        
DMA2_Stream4->CR|= DMA_SxCR_EN;                 // Вкл. передачу
        
NVIC_EnableIRQ(DMA2_Stream4_IRQn);
        
NVIC_SetPriority(DMA2_Stream4_IRQn,5);

//********************ADC1**CH6 PA6***************
        
RCC->APB2ENR    |= RCC_APB2ENR_ADC1EN;
        
ADC1->CR1         |=ADC_CR1_SCAN;                // Scan mode
        
ADC1->CR2        |=(ADC_CR2_EXTSEL_3);        //tim 3 (TRGO)
        
ADC1->SQR3        =6;                            //выбор канала PA6
        
ADC1->CR2         |=ADC_CR2_DMA;                //разрешаем рабуту DMA
        
ADC1->CR2         |=ADC_CR2_DDS;                //DMA disable selection (for single ADC mode)
        
ADC1->CR2        &=~ADC_CR2_CONT;            //Continuous conversion
        
ADC1->CR2        |=ADC_CR2_EXTEN_0;            //01: Trigger detection on the rising edge
        
ADC1->CR2        |= ADC_CR2_EOCS;            //разрешаем прерывания
        
ADC1->CR2         |=ADC_CR2_ADON;                //Вкл. переобразования  

понедельник, 19 сентября 2016 г.

STM32F051 Continuous mode and Discontinuous mode explanation for the sequence conversion

The following illustrations present the differences among various configuration for continuous mode and discontinuous mode for 2 channels:

With both modes disabled: the conversion sequence start from the first channel until the last channel and then stop. Each time the channel conversion is done, the End of Conversion (EOC) interrupt flag will be triggered until the last channel, End of sequence (EOS) will be on.

 continuous mode disabled, and discontinuous mode disabled

With continuous mode enabled, and discontinuous mode disabled: similarly to single channel, the conversion process will be restarted automatically when the last channel is finished.

continuous mode enabled, and discontinuous mode disabled

With continuous mode disabled, and discontinuous mode enabled: Everytime the channel conversion is done, we need to trigger the start of ADC module again to move on to the next channel in the sequence.
continuous mode disabled, and discontinuous mode enabled


вторник, 13 сентября 2016 г.

STM32F ADC config (CMSIS, HAL SPL)

CMSIS

Настройка преобразования первых 8ми регулярных каналов АЦП по запуску из программы с использованием канала DMA

// настройка ADC1
        RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //  такты на ADC1

        ADC1->SMPR2 |= ADC_SMPR2_SMP0 | ADC_SMPR2_SMP1
        | ADC_SMPR2_SMP2 | ADC_SMPR2_SMP3 | ADC_SMPR2_SMP4
        | ADC_SMPR2_SMP5 | ADC_SMPR2_SMP6 | ADC_SMPR2_SMP7;       // количество циклов преобразования 239.5

        ADC1->SQR1 |= ADC_SQR1_L_2 | ADC_SQR1_L_1 | ADC_SQR1_L_0; // длина последовательности регулярных каналов = 8;
        // добавление в последовательность каналов
        ADC1->SQR2 |= ADC_SQR2_SQ8_2 | ADC_SQR2_SQ8_1 | ADC_SQR2_SQ8_0 //канал 7
        | ADC_SQR2_SQ7_2 | ADC_SQR2_SQ7_1;                             // канал 6

        ADC1->SQR3 |=  ADC_SQR3_SQ6_2 | ADC_SQR3_SQ6_0                 //канал 5
        | ADC_SQR3_SQ5_2                                               //канал 4
        | ADC_SQR3_SQ4_1 | ADC_SQR3_SQ4_0                              //канал 3
        | ADC_SQR3_SQ3_1                                               //канал 2
        | ADC_SQR3_SQ2_0;                                              // канал 1
        //канал 0 включен по умолчанию т.к. в младших битах SQ3 0

//      ADC1->CR2 |= ADC_CR2_CONT;      // включаем если нужно непрерывное преобразование последовательности в цикле

        ADC1->CR2 |= ADC_CR2_DMA //включаем работу с DMA
        | ADC_CR2_EXTTRIG //включаем работу от внешнего события
        | ADC_CR2_EXTSEL //выбираем триггером запуска регулярной последовательности событие SWSTART
        | ADC_CR2_JEXTSEL; // выбираем триггером запуска выделенной последовательности событие JSWSTART дабы эти каналы не отнимали у мк времени
        ADC1->CR1 |= ADC_CR1_SCAN; // включаем автоматический перебор всех каналов в последовательности

//макросы для включения/выключения АЦП с DMA
#define ADC_ON ADC1->CR2 |= ADC_CR2_ADON;  \
                                ADC1->CR2 |= ADC_CR2_SWSTART; \
                                DMA1_Channel1->CCR |= DMA_CCR1_TCIE | DMA_CCR1_EN;      //включаем преобразование прерывание DMA
#define ADC_OFF ADC->CR2 &= (~(ADC_CR2_ADON)); \
                                DMA1_Channel1->CCR &= (~(DMA_CCR1_TCIE | DMA_CCR1_EN)); //выключаем преобразование и прерывание DMA
     

===============================================================

STM32 STANDBAY STOP mode

#define RCC_APB1ENR_PWREN ((unsigned long)0x10000000)
#define SCB_SCR_SLEEPONEXIT ((u8)0x02) /*!< Sleep on exit bit */
#define SCB_SCR_SLEEPDEEP ((u8)0x04) /*!< Sleep deep bit */
#define SCB_SCR_WUP ((u16)0x100)
#define PWR_CR_PDDS ((u16)0x0002) /*!< Power Down Deepsleep */
#define PWR_CR_CWUF ((u16)0x0004) /*!< Clear Wakeup Flag */

void GoStandBy(void){

RCC->APB1ENR |= RCC_APB1ENR_PWREN; 

/* Clear Wakeup flag */
PWR->CR |= PWR_CR_CWUF; 
/* Select STANDBY mode */
PWR->CR |= PWR_CR_PDDS; 
/* Set SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR |= SCB_SCR_SLEEPDEEP;
/* Wakeup pin enable */
PWR->CSR |= SCB_SCR_WUP;
__wfi(); //команда ухода в сон


Перевод в STOP режим (ADC & DAC):

ADC_Cmd(ADC1, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, DISABLE);
DAC_Cmd(DAC_Channel_1,DISABLE);
DAC_Cmd(DAC_Channel_2,DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, DISABLE); 
PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);


Stop

Останов процессора является базовым режимом ядра Cortex-M3, поэтому присутствует во всех микроконтроллерах. Он накладывает большие ограничения на работу внутренних схем, вследствие чего является наименее энергозатратным, из «спящих» режимов. Так, в данном режиме, производится остановка практически всей периферии микроконтроллера, а также любого основного тактового генератора. Вариантом режима Stop является случай, когда в работе остается модуль часов реального времени с соответствующим источником частоты. Для обеспечения минимального энергопотребления в данном режиме рекомендуется настройка внутреннего регулятора напряжения, а также отключение систем VrefntBORPVDADCDAC и встроенного датчика температуры. Состояние линий ввода вывода при переходе в режим STOP не изменяется, содержимое памяти и регистров сохраняется.
Для перевода в режим останова необходимо выполнить следующие действия:
  • Установить бит SLEEPDIP в регистре SCB
  • Очистить бит PDDS в регистре PWR_CR
  • Очистить бит WUF в регистре PWR_CSR
  • Настроить регулятор напряжения LPSDSR в регистре PWR_CR
  • Настроить событие или прерывание выхода из режима STOP
  • Подать команду WFI или WFE

Stadby

Режим ожидания стоит несколько особняком от других вариантов пониженного энергопотребления по причине отключения процессора и памяти. Фактически данный режим равноценен состоянию сброса. Содержимое памяти и всех регистров за исключением PWR_CSR теряется. Все порты ввода/вывода переводятся в высокоимпедансное состояние за исключением следующих линий, отвечающих за пробуждение процессора:
  • вход сброса
  • RTC_AF1 (PC13), если он сконфигурирован как вход для функций Wakeup (WKUP2), защиты данных (tamper), захвата времени (time-stamp), или как выход тревоги по таймеру (RTC Alarm), или тактовый выход RTC clock.
  • PA0 и PE6, если они сконфигурированы в качестве входов сигнала пробуждения WKUP.
Выход из режима ожидания выполняется при поступлении сигналов сброса, внешних сигналов пробуждения (WKUP), событий часов реального времени, событий несанкционированного доступа к данным или записи временной метки.
Для перевода в режим останова необходимо выполнить следующие действия:

  • Установить бит SLEEPDIP в регистре SCB
  • Включить бит PDDS в регистре PWR_CR
  • Очистить бит WUF в регистре PWR_CSR
  • Очистить флаги источников пробуждения
  • Подать команду WFI или WFE
Чтобы отладчик работал со спящими режимами нужно установить следующие биты
#if defined(DEBUG)
  DBGMCU_Config(DBGMCU_SLEEP, ENABLE);
  DBGMCU_Config(DBGMCU_STOP, ENABLE);
  DBGMCU_Config(DBGMCU_STANDBY, ENABLE);
#endif


понедельник, 1 августа 2016 г.

STM32 config

В STM32 перед тем как что то использовать НЕОБХОДИМО РАЗРЕШИТЬ это что то . По умолчанию все находится в отключенном состоянии . Поэтому любая инициализация периферии должна начинаться со строчек типа этого даже если напрямую в мануале нет об этом упоминаний 

/* Enable ADCx, DMA and GPIO clocks ****************************************/ 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);

Если используются прерывания то необходимо также настроить контроллер по типу этого 

static void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

/* Configure the preemption priority and subpriority:
- 1 bits for pre-emption priority: possible value are 0 or 1 
- 3 bits for subpriority: possible value are 0..7
- Lower values gives higher priority 
*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

/* Enable the WAKEUP_BUTTON_EXTI_IRQn Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = WAKEUP_BUTTON_EXTI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ubPreemptionPriorityValue;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

/* Enable the KEY_BUTTON_EXTI_IRQn/TAMPER_BUTTON_EXTI_IRQn Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = BUTTON_EXTI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

и не забыть создать обработчик прерывания 


/**
* @brief This function handles External line 0 interrupt request.
* @param None
* @retval None
*/
void EXTI0_IRQHandler(void)
{
/* Generate SysTick exception */
SCB->ICSR |= 0x04000000;

/* Clear WAKEUP_BUTTON_EXTI_LINE pending bit */
EXTI_ClearITPendingBit(WAKEUP_BUTTON_EXTI_LINE);
}

в противном случае программа будет вываливаться в какой нить обработчик системных ошибок типа BusFault_Handler,MemManage_Handler,HardFault_Handler в зависимости от того как построена система в каждом конкретном случае . 

вторник, 7 июня 2016 г.

FreeRTOS

void ATaskFunction( void *pvParameters );
void ATaskFunction( void *pvParameters )
{
   /* Переменные могут быть определены точно так же, как и в обычной функции. Каждый экземпляр созданной по этой функции задачи будет иметь собственную копию переменной iVariableExample. Это не верно, если переменная была продекларирована как статическая (static) – в этом случае будет сущесвовать только одна копия переменной, и она будет использоваться совместно всеми созданными экземплярами задачи. */


   int iVariableExample = 0;

  /* Задача должна быть нормально реализована как бесконечный цикл. */
  for( ;; )
  {
     /* Код, который реализует функционал задачи, должен быть помещен здесь. */
  }

   /* Код должен быть организован так, чтобы в случае выхода (break) из указанного 
выше бесконечного цикла задачи, задача должна быть удалена ПРЕЖДЕ чем управление достигнет конца этой функции. Параметр NULL, переданный vTaskDelete(), показывает, что должна быть удалена вызванная (эта, которая работает) задача. */
   vTaskDelete( NULL );
}


portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode,
                           const signed portCHAR * const pcName,
                           unsigned portSHORT usStackDepth,
                           void *pvParameters,
                           unsigned portBASE_TYPE uxPriority,
                           xTaskHandle *pxCreatedTask );




pvTaskCodeЗадачи - это простые C-функции, которые никогда не делают возврата из своего тела (постоянно выполняют свой бесконечный цикл). Параметр pvTaskCode - простой указатель на функцию (т. е. просто имя функции), которая реализует задачу.
 pcName
Описательное имя для задачи. Оно никак не используется внутри FreeRTOS, и нужно только для целей отладки. Идентификация задачи по легкочитаемому имени намного проще, чем по хендлу задачи (handle).
В приложении указана константа времени компиляции configMAX_TASK_NAME_LEN, которая задает максимальную длину для этого имени - включая нулевой байт окончания строки. Если в качестве pcName предоставлена более длинная строка, то она молча урезается до величины, заданной configMAX_TASK_NAME_LEN.
 usStackDepth
Каждая задача имеет собственное уникальное хранилище состояния, выделенное ядром при создании задачи. Значение параметра usStackDepth говорит ядру, какой величины стек необходимо создать.
Значение usStackDepth указывает количество слов, которое можно сохранить в стеке, а не количество байт. Например, если стек имеет ширину 32 бита, и переданное значение usStackDepth равно 100, то под стек будет выделено 400 байт (100 * 4 байт). Глубина стека, умноженная на его ширину, не должна превышать максимальное значение, которое может содержать переменная типа size_t.
Размер стека, используемого для задачи ожидания (idle task, об этой задаче подробнее говорится далее), задается константой configMINIMAL_STACK_SIZE. Значение, назначенное этой константе в демо-приложении FreeRTOS (для определенной архитектуры микроконтроллера) может быть использовано как минимально рекомендованное для любой задачи. Если Ваша программа использует пространство в стеке, то нужно указать для константы configMINIMAL_STACK_SIZE увеличенное значение.
Нет простого способа узнать, какого размера стек нужен для задачи. Этот размер можно вычислить, но в большинстве случаев можно просто назначить подходящее значение, подобранное опытным путем, либо взятое приблизительно. Подобрать правильный размер стека важно, чтобы обеспечить адекватное использование RAM без ненужных затрат. Часть 6 содержит информацию о том, как запросить размер стека, используемого задачей.
 pvParametersФункции задач принимают параметр, имеющий тип указателя на void (т. е. void*). Значение, указанное в pvParameters, будет передано в задачу. Несколько примеров в этом документе демонстрируют, как этот параметр может быть использован в реальных задачах.
 uxPriority
Задает приоритет, с которым будет выполняться задача. Приоритеты могут быть назначены в любое значение от 0 минимальный приоритет до (configMAX_PRIORITIES – 1) максимальный приоритет.
Константа configMAX_PRIORITIES определяется пользователем. Нет ограничения на верхний предел для количества приоритетов, которые можно задать (кроме ограничения на лимит используемого типа данных ограничения по количеству RAM, доступному в микроконтроллере), но желательно использовать как можно меньшее количество приоритетов, которое действительно необходимо - с целью уменьшения расхода RAM.
Передача в параметре значения uxPriority выше (configMAX_PRIORITIES – 1) приведет к молчаливому назначению приоритета задачи в максимально допустимое значение configMAX_PRIORITIES.
 pxCreatedTask
Параметр pxCreatedTask может использоваться для передачи наружу хендла созданной задачи. Этот хендл можно использовать как ссылку на задачу в вызовах API FreeRTOS, например для изменения приоритета задачи или для удаления задачи.
Если Ваше приложение не использует хендл задачи, то pxCreatedTask может быть установлен в NULL.
Возвращаемое значение
Имеется два возможных возвращаемых значения:
1. pdTRUE показывает, что задача успешно создана.
2. errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY показывает, что задача не создана, так как в куче (heap) недостаточно свободной памяти для FreeRTOS, чтобы она могла выделить место для структур данных задачи и стека. Часть 5 предоставляет больше информации по управлению памятью.


int main( void )
{
  /* Создание одной из двух задач. Имейте в виду, что реальное приложение должно
     проверить возвращаемое значение из вызова xTaskCreate(), чтобы удостовериться,
     что задача была успешно создана. */
  xTaskCreate( vTask1,  /* Указатель на функцию, которая реализует задачу. */
               "Task 1",/* Текстовое имя задачи. Этот параметр нужен только для
                           упрощения отладки. */
               1000,    /* Глубина стека - самые маленькие микроконтроллеры будут
                           использовать значение намного меньше, чем здесь
                           указано. */

               NULL,    /* Мы не используем параметр задачи. */
               1,       /* Задача будет запущена с приоритетом 1. */
               NULL );  /* Мы не будем использовать хендл задачи. */
  /* Создание другой задачи полностью совпадает с созданием первой, 
     приориет задачи тот же. */
  xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL );

  /* Запуск шедулера, после чего задачи запустятся на выполнение. */
  vTaskStartScheduler();

  /* Если все хорошо, то управление в main() никогда не дойдет до этой точки,
     и теперь шедулер будет управлять задачами. Если main() довела 
управление
     до 
этого места, то это может означать, что не хватает памяти кучи
     
(heap) для создания специальной задачи ожидания (idle task, об этой задаче
     
далее). Часть 5 предоставляет больше информации по управлению памятью. */
  for( ;; );
}