petrdynin

Mik32+mtime_IRQ+mcycle

Oct 6th, 2025
600
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.55 KB | Source Code | 0 0
  1. #include "mik32_hal_pcc.h"
  2. #include "mik32_hal_gpio.h"
  3. #include "mik32_memory_map.h"
  4. #include "csr.h"
  5. #include "scr1_timer.h"
  6. #include "scr1_csr_encoding.h"
  7.  
  8. /*
  9.  * Данный пример демонстрирует работу с mtime и mcycle
  10.  *
  11.  */
  12.  
  13. void SystemClock_Config();
  14. void GPIO_Init();
  15. void Systick_Initialize();
  16. void trap_handler(void);
  17.  
  18. int main()
  19. {
  20.  
  21.     SystemClock_Config();
  22.  
  23.     GPIO_Init();
  24.  
  25.     PM->CLK_APB_M_SET = PM_CLOCK_APB_M_EPIC_M;
  26.     Systick_Initialize();
  27.     // global interrupt enable
  28.     set_csr(mstatus, MSTATUS_MIE);  // Global interrupt enable
  29.     set_csr(mie, MIE_MEIE);         // Machine External Interrupt Enable
  30.  
  31.     while (1)
  32.     {
  33.         HAL_GPIO_TogglePin(GPIO_0, GPIO_PIN_9);
  34.         HAL_DelayMs(500);
  35.     }
  36. }
  37.  
  38. void SystemClock_Config(void)
  39. {
  40.     PCC_InitTypeDef PCC_OscInit = {0};
  41.  
  42.     PCC_OscInit.OscillatorEnable = PCC_OSCILLATORTYPE_ALL;
  43.     PCC_OscInit.FreqMon.OscillatorSystem = PCC_OSCILLATORTYPE_OSC32M;
  44.     PCC_OscInit.FreqMon.ForceOscSys = PCC_FORCE_OSC_SYS_UNFIXED;
  45.     PCC_OscInit.FreqMon.Force32KClk = PCC_FREQ_MONITOR_SOURCE_OSC32K;
  46.     PCC_OscInit.AHBDivider = 0;
  47.     PCC_OscInit.APBMDivider = 0;
  48.     PCC_OscInit.APBPDivider = 0;
  49.     PCC_OscInit.HSI32MCalibrationValue = 128;
  50.     PCC_OscInit.LSI32KCalibrationValue = 8;
  51.     PCC_OscInit.RTCClockSelection = PCC_RTC_CLOCK_SOURCE_AUTO;
  52.     PCC_OscInit.RTCClockCPUSelection = PCC_CPU_RTC_CLOCK_SOURCE_OSC32K;
  53.     HAL_PCC_Config(&PCC_OscInit);
  54. }
  55.  
  56. void GPIO_Init()
  57. {
  58.     GPIO_InitTypeDef GPIO_InitStruct = {0};
  59.  
  60.     __HAL_PCC_GPIO_0_CLK_ENABLE();
  61.     __HAL_PCC_GPIO_1_CLK_ENABLE();
  62.  
  63.     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
  64.     GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_OUTPUT;
  65.     GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE;
  66.    
  67.     HAL_GPIO_Init(GPIO_0, &GPIO_InitStruct);
  68. }
  69.  
  70.  
  71. void Systick_Initialize(void )
  72. {
  73.     SCR1_TIMER->TIMER_DIV = 0;
  74.     *(unsigned long long *) &SCR1_TIMER->MTIME = 0;
  75.     *(unsigned long long *) &SCR1_TIMER->MTIMECMP = 3200000;
  76.     SCR1_TIMER->TIMER_CTRL |= SCR1_TIMER_CTRL_ENABLE_M ;
  77.     set_csr(mie, MIE_MTIE);   //Machine Timer Interrupt Enable
  78. }
  79.  
  80.  
  81. volatile  uint64_t tick;
  82.  
  83. void __attribute__((section(".ram_text"))) trap_handler(void)
  84. {
  85.     unsigned long mcause = read_csr(mcause);
  86.     static uint16_t led;
  87.  
  88.     uint32_t mcycle_lo, mcycle_hi, mcycle_hi2;
  89.     uint64_t mcycle_64;
  90.  
  91.     static uint64_t mcycle_old_64 = 0;
  92.  
  93.     // --- правильное чтение согласованного mcycle (64 бита) ---
  94.     do {
  95.         mcycle_hi  = read_csr(mcycleh);
  96.         mcycle_lo  = read_csr(mcycle);
  97.         mcycle_hi2 = read_csr(mcycleh);
  98.     } while (mcycle_hi != mcycle_hi2);
  99.  
  100.     mcycle_old_64 = ((uint64_t)mcycle_hi << 32) | mcycle_lo;
  101.  
  102.     asm("nop");
  103.     asm("nop");
  104.     asm("nop");
  105.     asm("nop");
  106.     asm("nop");
  107.     asm("nop");
  108.  
  109.     // --- правильное чтение согласованного mcycle (64 бита) ---
  110.     do {
  111.        mcycle_hi  = read_csr(mcycleh);
  112.        mcycle_lo  = read_csr(mcycle);
  113.        mcycle_hi2 = read_csr(mcycleh);
  114.     } while (mcycle_hi != mcycle_hi2);
  115.  
  116.     mcycle_64 = ((uint64_t)mcycle_hi << 32) | mcycle_lo;
  117.  
  118.     // --- вычисление дельты ---
  119.     tick = mcycle_64 - mcycle_old_64;
  120.  
  121.     // --- обработка прерывания таймера ---
  122.     if ((mcause & MCAUSE_EC) == 7 && (mcause & MCAUSE_INT)) {
  123.         *(unsigned long long *)&SCR1_TIMER->MTIMECMP += 3200;
  124.  
  125.         if (++led >= 500) {
  126.             led = 0;
  127.             GPIO_0->OUTPUT ^= (1 << 10);
  128.         }
  129.     }
  130. }
  131.  
  132.  
Advertisement
Add Comment
Please, Sign In to add comment