Advertisement
Guest User

Untitled

a guest
Jun 18th, 2019
208
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 20.35 KB | None | 0 0
  1. #include "mcu_support_package/inc/stm32f10x.h"
  2.  
  3. #include <app_cfg.h>
  4.  
  5. #include  <ucos_ii.h>
  6.  
  7. #include  <cpu.h>
  8. #include  <lib_def.h>
  9. #include  <lib_mem.h>
  10. #include  <lib_str.h>
  11.  
  12. #include  <bsp.h>
  13.  
  14. #define APP_ASSERT( statement ) do { if(! (statement) ) { __disable_irq(); while(1){ __BKPT(0xAB); if(0) break;} }  } while(0)
  15.  
  16. /***************************************************************************************************
  17.                                  Стеки для тасков
  18.  ***************************************************************************************************/
  19.  
  20. static OS_STK App_TaskStartStack[APP_TASK_START_STACK_SIZE];
  21.  
  22. static OS_STK App_ButtonStack[APP_TASK_BUTTON_STACK_SIZE];
  23.  
  24. static OS_STK App_TaskLed8Stack[APP_TASK_LED8_STACK_SIZE];
  25.  
  26. static OS_STK App_TaskScanKeyboardStack[APP_TASK_KEYBOARD_STACK_SIZE];
  27.  
  28. static OS_STK App_TaskPlaySoundStack[APP_TASK_SOUND_STACK_SIZE];
  29.  
  30. static OS_STK App_TaskSendButtonNumStack[APP_TASK_SEND_BUTTON_NUM_STACK_SIZE];
  31.  
  32. /***************************************************************************************************
  33.                                  Таски - объявления
  34.  ***************************************************************************************************/
  35.  
  36. static void App_TaskStart( void * p_arg );
  37.  
  38. static void App_TaskButton( void * p_arg );// сканирование кнопки PA0
  39.  
  40. static void App_TaskLed8( void * p_arg ); // зажигание светодиода PC8 по нажатию PA0
  41.  
  42. static void App_TaskScanKeyboard( void * p_arg ); // сканирование клавиатуры
  43.  
  44. static void App_TaskPlaySound( void * p_arg ); // играть звук согласно нажатой кнопке
  45.  
  46. static void App_TaskSendButtonNum( void * p_arg ); // отправлять номер нажатой клавиши
  47. //на клавиатуре по USART
  48. OS_EVENT * semaphore;// указатель на семафор
  49. OS_EVENT * queue;// указатель на очередь
  50. #define QUEUE_SIZE 128
  51. static void * queueStorage[ QUEUE_SIZE ]; // массив, в котором будут лежать сообщения
  52.  
  53. int main(void) {
  54.  
  55.     // запрет прерываний и инициализация ОС
  56.     BSP_IntDisAll();
  57.     OSInit();
  58.  
  59.     // создание стартового таска - в нем создаются все остальные
  60.     // почему не создавать всё сразу в main'e?
  61.     // возможно, вы хотите создавать их в зависимости от каких-нибудь условий,
  62.     // для которых уже должна работать ОС
  63.    
  64.     INT8U res = OSTaskCreate(
  65.                     App_TaskStart,     // указатель на таск        
  66.                     NULL,              // параметр вызова (без параметра)
  67.                     &App_TaskStartStk[APP_TASK_START_STK_SIZE - 1], // указатель на стек
  68.                     APP_TASK_START_PRIO // приоритет
  69.                 );
  70.  
  71.  
  72.    
  73.     APP_ASSERT( res == OS_ERR_NONE );
  74.  
  75.     // запуск многозадачности
  76.     OSStart();
  77.  
  78.     // до сюда выполнение доходить не должно
  79.     return 0;
  80.  
  81. }
  82.  
  83. /***************************************************************************************************
  84.                                  Таски
  85.  ***************************************************************************************************/
  86.  
  87. // стартовый таск
  88. static void App_TaskStart(void * p_arg) {
  89.     // это чтобы убрать warning о неиспользуемом аргументе
  90.     (void)p_arg;
  91.  
  92.     //  Фактически - только настройка RCC - 72 МГц от ФАПЧ  (Initialize BSP functions)
  93.     BSP_Init();
  94.  
  95.     // настройка СисТика
  96.     OS_CPU_SysTickInit();
  97.  
  98.     // таск для сбора статистики - если он нужен                            
  99. #if (OS_TASK_STAT_EN > 0)
  100.     OSStatInit();
  101. #endif
  102.  
  103.     // дальше создаются пользовательские таски
  104.    
  105.     INT8U res;
  106.  
  107.     res = OSTaskCreate(
  108.               App_TaskButton, // указатель на функцию      
  109.               NULL,            // параметр - без параметра              
  110.               &App_ButtonStack[APP_TASK_BUTTON_STACK_SIZE - 1], // указатель на массив для стека  
  111.               APP_TASK_BUTTON_PRIO // приоритет
  112.           );
  113.                
  114.     APP_ASSERT( res == OS_ERR_NONE );
  115.  
  116.     res = OSTaskCreate(
  117.               App_TaskLed8,
  118.               NULL,
  119.               &App_TaskLed8Stack[APP_TASK_LED8_STACK_SIZE - 1],
  120.               APP_TASK_LED8_PRIO
  121.           );
  122.                
  123.     APP_ASSERT( res == OS_ERR_NONE );
  124.  
  125.     res = OSTaskCreate(  
  126.               App_TaskScanKeyboard, // указатель на функцию
  127.               NULL, // параметр - без параметра
  128.               &App_TaskScanKeyboardStack[APP_TASK_KEYBOARD_STACK_SIZE - 1], // указатель на массив для стека
  129.               APP_TASK_SCAN_KEYBOARD_PRIO // приоритет
  130.           );
  131.                      
  132.     APP_ASSERT(res == OS_ERR_NONE);
  133.        
  134.     res = OSTaskCreate(
  135.               App_TaskPlaySound, // указатель на функцию
  136.               NULL, // параметр - без параметра
  137.               &App_TaskPlaySoundStack[APP_TASK_SOUND_STACK_SIZE - 1], // указатель на массив для стека
  138.               APP_TASK_PLAY_SOUND_PRIO // приоритет
  139.           );
  140.  
  141.     APP_ASSERT( res == OS_ERR_NONE );
  142.        
  143.     res = OSTaskCreate(
  144.               App_TaskSendButtonNum, // указатель на функцию
  145.               NULL, // параметр - без параметра
  146.               &App_TaskSendButtonNumStack[APP_TASK_SEND_BUTTON_NUM_STACK_SIZE - 1], // указатель на массив для стека
  147.               APP_TASK_SEND_BUTTON_NUM_PRIO // приоритет
  148.           );
  149.  
  150.     APP_ASSERT( res == OS_ERR_NONE );
  151.  
  152.     // этот таск больше не нужен
  153.     OSTaskDel (OS_PRIO_SELF);
  154.                      
  155. }
  156.  
  157. static bool is_button_on = false; // запоминает состояние кнопки PA0
  158.  
  159. // этот таск зажигает светодиод по нажатию кнопки
  160. static void App_TaskLed8( void * p_arg ) {
  161.     // это чтобы убрать warning о неиспользуемом аргументе
  162.     (void)p_arg;
  163.  
  164.     // настройка портов светодиодов и кнопки - делается при первом вызове таска
  165.     // подаем тактирование
  166.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
  167.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
  168.  
  169.     // делаем РС.0 - floating input
  170.     GPIO_InitTypeDef gpioA;
  171.     gpioA.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  172.     gpioA.GPIO_Pin = GPIO_Pin_0;
  173.     gpioA.GPIO_Speed = GPIO_Speed_10MHz;
  174.  
  175.     GPIO_Init( GPIOA, &gpioA );
  176.     // делаем РС.8 - выходом пуш-пулл
  177.     GPIO_InitTypeDef gpioC;
  178.     gpioC.GPIO_Mode = GPIO_Mode_Out_PP;
  179.     gpioC.GPIO_Pin = GPIO_Pin_8;
  180.     gpioC.GPIO_Speed = GPIO_Speed_10MHz;
  181.  
  182.     GPIO_Init( GPIOC, &gpioC );
  183.  
  184.     // таск никогда не должен завершаться через закрывающую скобку
  185.     // поэтому внутри или удаление или бесконечный цикл
  186.     while (1) {
  187.         if (is_button_on == true)
  188.         GPIOC -> ODR |= 1 << 8; // зажечь светодиод при нажатой кнопке
  189.         else GPIOC -> ODR &= ~(1 << 8); // иначе погасить
  190.         // засыпаем на 5 миллисекунд,чтобы поток кнопки захватил управление
  191.         OSTimeDlyHMSM(0, 0, 0, 5);
  192.     }
  193. }
  194.  
  195. // все что делает этот таск - сканирует кнопку
  196. static void App_TaskButton( void * p_arg ) {
  197.     // это чтобы убрать warning о неиспользуемом аргументе
  198.     (void)p_arg;
  199.  
  200.     // настройка портов - делается при первом вызове таска
  201.     // да, в таске для кнопки порты тоже настраиваются - но ведь другой таск может
  202.     // быть и не активен!
  203.  
  204.     // подаем тактирование
  205.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
  206.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
  207.  
  208.     // делаем РС.0 - floating input
  209.     GPIO_InitTypeDef gpioA;
  210.     gpioA.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  211.     gpioA.GPIO_Pin = GPIO_Pin_0;
  212.     gpioA.GPIO_Speed = GPIO_Speed_10MHz;
  213.  
  214.     GPIO_Init( GPIOA, &gpioA );
  215.     // делаем РС.8 - выходом пуш-пулл
  216.     GPIO_InitTypeDef gpioC;
  217.     gpioC.GPIO_Mode = GPIO_Mode_Out_PP;
  218.     gpioC.GPIO_Pin = GPIO_Pin_8;
  219.     gpioC.GPIO_Speed = GPIO_Speed_10MHz;
  220.  
  221.     GPIO_Init( GPIOC, &gpioC );
  222.  
  223.     // таск никогда не должен завершаться через закрывающую скобку
  224.     // поэтому внутри или удаление или бесконечный цикл
  225.     while (1) {
  226.         //если кнопка нажата
  227.         if(((GPIOA->IDR)&1))
  228.         is_button_on = true;
  229.         else is_button_on = false;
  230.         // засыпаем на 5 миллисекунд, чтобы дать время поменять состояние светодиода
  231.         OSTimeDlyHMSM(0, 0, 0, 5);
  232.     }
  233. }
  234.  
  235. static uint8_t button_num = 0;
  236.  
  237. static void App_TaskScanKeyboard(void * p_arg) {
  238.  
  239.     (void) p_arg;
  240.  
  241.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  242.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
  243.     GPIO_InitTypeDef PortA;
  244.     PortA.GPIO_Mode = GPIO_Mode_IPU;
  245.     PortA.GPIO_Pin = (GPIO_Pin_1) | (GPIO_Pin_2) | (GPIO_Pin_3) | (GPIO_Pin_4);
  246.     PortA.GPIO_Speed = GPIO_Speed_50MHz;
  247.     GPIO_Init(GPIOA, &PortA); // строки клавиатуры
  248.  
  249.     GPIO_InitTypeDef PortC;
  250.     PortC.GPIO_Mode = GPIO_Mode_Out_OD;
  251.     PortC.GPIO_Pin = (GPIO_Pin_1) | (GPIO_Pin_2) | (GPIO_Pin_3);
  252.     PortC.GPIO_Speed = GPIO_Speed_50MHz;
  253.     GPIO_Init(GPIOC, &PortC); // столбцы клавиатуры
  254.     GPIO_SetBits(GPIOC, (GPIO_Pin_1) | (GPIO_Pin_2) | (GPIO_Pin_3)); // установим столбцы в 1
  255.  
  256.     while (1) {
  257.         INT8U err;
  258.         OSSemPend(semaphore, 0, &err);
  259.         APP_ASSERT(err == OS_ERR_NONE);
  260.         button_num = 0;
  261.         for (uint8_t cols = 1; cols < 4; cols++) {
  262.             GPIO_ResetBits(GPIOC, 1 << cols); // ставим 0 по очереди по столбцам
  263.             OSTimeDlyHMSM(0, 0, 0, 4); // подождать 4 миллисекунды
  264.         for (uint8_t rows = 1; rows < 5; rows++) { // по очереди проверяем строки
  265.             if (!(GPIOA->IDR&(1«rows))) {
  266.                 button_num = (cols-1)+3*(rows-1) + 1; // запоминает номер нажатой кнопки, иначе 0
  267.                 break;
  268.                 }
  269.             //GPIOB->ODR ^= 1«10; // apply alternating voltage to the dynamic membrane
  270.             //delay(1000000/(2*ar[(cols-1)+3*(rows-1)]));
  271.             }
  272.         GPIO_SetBits(GPIOC, 1 << cols);
  273.         }
  274.     OSSemPost(semaphore); // освобождение семафора
  275.     OSTimeDlyHMSM(0, 0, 0, 10);
  276.     }
  277. }
  278.  
  279. static void TIM3_IRQHandler() {
  280.     TIM_ClearFlag(TIM3, TIM_IT_Update);
  281.     GPIOB-> ODR ^= 1 << 5;
  282. }
  283.  
  284. static void App_TaskPlaySound(void * p_arg) {
  285.  
  286.     (void)p_arg;
  287.  
  288.     static const uint16_t freq[12] = {600, 800, 1000, 1200, 1400, 1600, 1800, 2000, 2200, 2400, 2600,
  289. 2800}; // массив частот в Герцах для каждой из кнопок
  290.  
  291.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
  292.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  293.  
  294.     TIM_TimeBaseInitTypeDef tim3_struct;
  295.     TIM_TimeBaseStructInit(&tim3_struct);
  296.     tim3_struct.TIM_Period = 100;
  297.     tim3_struct.TIM_CounterMode = TIM_CounterMode_Down;
  298.     TIM_TimeBaseInit(TIM3,&tim3_struct);
  299.  
  300.     TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE);//настройка прерываний TIM3
  301.     TIM_Cmd(TIM3,ENABLE);//запуск таймера
  302.     BSP_IntVectSet(BSP_INT_ID_TIM3,TIM3_IRQHandler);//разрешаем прерывания
  303.  
  304.     GPIO_InitTypeDef gpioB; // настройка динамика
  305.     gpioB.GPIO_Mode = GPIO_Mode_Out_PP;
  306.     gpioB.GPIO_Pin = GPIO_Pin_5;
  307.     gpioB.GPIO_Speed = GPIO_Speed_10MHz;
  308.     GPIO_Init(GPIOB, &gpioB);
  309.  
  310.     while(1) {
  311.         INT8U err;
  312.         OSSemPend(semaphore, 0, &err);
  313.         APP_ASSERT(err == OS_ERR_NONE);
  314.         //если кнопка нажата           
  315.         if(button_num) {
  316.             tim3_struct.TIM_Prescaler = (72000000 / (200*freq[button_num - 1]))-1;
  317.             TIM_TimeBaseInit(TIM3,&tim3_struct);
  318.             NVIC_EnableIRQ(TIM3_IRQn);//разрешение прерываний таймера TIM3
  319.             //если ничего не нажато
  320.             } else {
  321.             NVIC_DisableIRQ(TIM3_IRQn);
  322.             GPIO_ResetBits(GPIOB,GPIO_Pin_5);
  323.             }
  324.         OSSemPost(semaphore);
  325.         OSTimeDlyHMSM(0, 0, 0, 10);
  326.         }
  327. }
  328.  
  329. volatile char tx_buffer[16];
  330. static int8_t counter = 0;
  331.  
  332. static void USART1_IRQHandler(void) {
  333.     if(USART_GetITStatus(USART1, USART_IT_TC) == SET){ //прерывание по передаче
  334.     USART_SendData(USART1,tx_buffer[counter++]);
  335.     }
  336.     if (counter > 15) {
  337.     counter = 0;
  338.     USART_ITConfig(USART1, USART_IT_TC, DISABLE);
  339.     }
  340. }
  341.  
  342. static void App_TaskSendButtonNum(void * p_arg) {
  343.  
  344.     (void)p_arg;
  345.  
  346.     char ASCII;//значение кнопки в ASCII
  347.  
  348.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  349.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  350.  
  351.     GPIO_InitTypeDef gpioB;
  352.     gpioB.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  353.     gpioB.GPIO_Pin = GPIO_Pin_7; //настройка ножки RX USART1
  354.  
  355.     gpioB.GPIO_Mode = GPIO_Mode_AF_PP;
  356.     gpioB.GPIO_Pin = GPIO_Pin_6; //настройка ножки TX USART1
  357.  
  358.     gpioB.GPIO_Speed = GPIO_Speed_2MHz;
  359.     GPIO_Init(GPIOB,&gpioB);
  360.  
  361.     USART_InitTypeDef Usart_struct;
  362.     Usart_struct.USART_BaudRate = 57600;
  363.     Usart_struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  364.     Usart_struct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  365.     Usart_struct.USART_Parity = USART_Parity_No;
  366.     Usart_struct.USART_StopBits = USART_StopBits_1;
  367.     Usart_struct.USART_WordLength = USART_WordLength_8b;
  368.     USART_Init(USART1,&Usart_struct);//настройка режима работы USART
  369.  
  370.     USART_ITConfig(USART1,USART_IT_TC,DISABLE);
  371.     USART_Cmd(USART1, ENABLE);
  372.     BSP_IntVectSet(BSP_INT_ID_USART1,USART1_IRQHandler);//разрешаем прерывания
  373.     NVIC_EnableIRQ(USART1_IRQn);//разрешение прерываний USART1
  374.     while(1) {
  375.         INT8U err;
  376.         OSSemPend( semaphore,0,&err);
  377.         APP_ASSERT(err == OS_ERR_NONE);
  378.         if(button_num) {
  379.             // перевод кнопки в ASCII
  380.             if(button_num==12) ASCII = 35;// #
  381.             if(button_num==11) ASCII = 48;// 0
  382.             if(button_num==10) ASCII = 42;// *
  383.             else if(button_num<10) ASCII = button_num + 0x30;
  384.             tx_buffer[0] = 'p';
  385.             tx_buffer[1] = 'r';
  386.             tx_buffer[2] = 'e';
  387.             tx_buffer[3] = 's';
  388.             tx_buffer[4] = 's';
  389.             tx_buffer[5] = 'e';
  390.             tx_buffer[6] = 'd';
  391.             tx_buffer[7] = ' ';
  392.             tx_buffer[8] = 'b';
  393.             tx_buffer[9] = 'u';
  394.             tx_buffer[10] = 't';
  395.             tx_buffer[11] = 't';
  396.             tx_buffer[12] = 'o';
  397.             tx_buffer[13] = 'n';
  398.             tx_buffer[14] = ' ';
  399.             tx_buffer[15] = ASCII; // место в сообщении, где должен стоять номер кнопки
  400.             USART_ITConfig(USART1, USART_IT_TC, ENABLE);
  401.         }
  402.                
  403.         //если ничего не нажато
  404.         if(!button_num) {
  405.             tx_buffer[0] = 'n';
  406.             tx_buffer[1] = 'o';
  407.             tx_buffer[2] = 't';
  408.             tx_buffer[3] = 'h';
  409.             tx_buffer[4] = 'i';
  410.             tx_buffer[5] = 'n';
  411.             tx_buffer[6] = 'g';
  412.             tx_buffer[7] = ' ';
  413.             tx_buffer[8] = 'p';
  414.             tx_buffer[9] = 'r';
  415.             tx_buffer[10] = 'e';
  416.             tx_buffer[11] = 's';
  417.             tx_buffer[12] = 's';
  418.             tx_buffer[13] = 'e';
  419.             tx_buffer[14] = 'd';
  420.             tx_buffer[15] = ' ';
  421.             USART_ITConfig(USART1, USART_IT_TC, ENABLE);
  422.         }
  423.         counter = 0;
  424.         OSSemPost(semaphore);
  425.         OSTimeDlyHMSM(0, 0, 0, 8);
  426.     }
  427. }
  428.  
  429.  
  430. //STOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOP
  431. // все что делает этот таск - мигает светодиодом РС8
  432. static void App_TaskLed1( void * p_arg )
  433. {
  434.     // это чтобы убрать warning о неиспользуемом аргументе
  435.     (void)p_arg;
  436.  
  437.     // настройка порта светодиода - делается при первом вызове таска
  438.     // подаем тактирование
  439.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
  440.  
  441.     // делаем РС.8 - выходом пуш-пулл
  442.     GPIO_InitTypeDef gpioC;
  443.     gpioC.GPIO_Mode = GPIO_Mode_Out_PP;
  444.     gpioC.GPIO_Pin = GPIO_Pin_8;
  445.     gpioC.GPIO_Speed = GPIO_Speed_10MHz;
  446.  
  447.     GPIO_Init( GPIOC, &gpioC );
  448.  
  449.     // таск никогда не должен завершаться через закрывающую скобку
  450.     // поэтому внутри или удаление или бесконечный цикл
  451.     while ( 1 )
  452.     {
  453.         // собственно мигание
  454.         GPIOC->ODR ^= 1 << 8;
  455.  
  456.         // а до следующего мигания делать нечего
  457.         // засыпаем на 1 секунду
  458.         OSTimeDlyHMSM( 0, 0, 1, 0 );
  459.     }
  460.  
  461. }
  462.  
  463.  
  464. // все что делает этот таск - мигает светодиодом РС9
  465. static void App_TaskLed2( void * p_arg )
  466. {
  467.     // это чтобы убрать warning о неиспользуемом аргументе
  468.     (void)p_arg;
  469.  
  470.     // настройка порта светодиода - делается при первом вызове таска
  471.     // да, в другом таске порт тоже настраивается - но ведь другой таск может
  472.     // быть и не активен!
  473.  
  474.     // подаем тактирование
  475.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
  476.  
  477.     // делаем РС.9 - выходом пуш-пулл
  478.     GPIO_InitTypeDef gpioC;
  479.     gpioC.GPIO_Mode = GPIO_Mode_Out_PP;
  480.     gpioC.GPIO_Pin = GPIO_Pin_9;
  481.     gpioC.GPIO_Speed = GPIO_Speed_10MHz;
  482.  
  483.     GPIO_Init( GPIOC, &gpioC );
  484.  
  485.     // таск никогда не должен завершаться через закрывающую скобку
  486.     // поэтому внутри или удаление или бесконечный цикл
  487.     while ( 1 )
  488.     {
  489.         // собственно мигание
  490.         GPIOC->ODR ^= 1 << 9;
  491.  
  492.         // а до следующего мигания делать нечего
  493.         // засыпаем на 500 миллисекунд
  494.         OSTimeDlyHMSM( 0, 0, 0, 500 );
  495.     }
  496.  
  497. }
  498.  
  499. #ifdef USE_FULL_ASSERT
  500.  
  501. // эта функция вызывается, если assert_param обнаружил ошибку
  502. void assert_failed(uint8_t * file, uint32_t line) {
  503.     /* User can add his own implementation to report the file name and line number,
  504.      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  505.  
  506.     (void)file;
  507.     (void)line;
  508.  
  509.     __disable_irq();
  510.     while(1) {
  511.         // это ассемблерная инструкция "отладчик, стой тут"
  512.         // если вы попали сюда, значит вы ошиблись в параметрах вызова функции из SPL.
  513.         // Смотрите в call stack, чтобы найти ее
  514.         __BKPT(0xAB);
  515.     }
  516. }
  517.  
  518. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement