تعلم RISC-V من البداية ، الجزء 2: المقاطعات ورسو السفن C



نواصل الغوص في هيكل وحدة التحكم GD32VF103CBT6. الآن دعونا نلقي نظرة على كيفية التعامل مع المقاطعات للعمل تحت سيطرة كود عالي المستوى.

الجزء الأول هنا







7. اتصال UART



عند اختيار مشكلة للتكرار ، واجهت مشكلة أن ثلاثة مصابيح LED ليست كافية لتصحيح الخوارزميات المعقدة. لذلك دعونا نضيف واجهة تصحيح أخطاء كاملة يمكن لبرنامج طرفي مثل الشاشة ربطها والتواصل مع وحدة التحكم باستخدام نص عادي. للقيام بذلك ، سوف نستخدم نفس USART0 المستخدم للبرنامج الثابت.

استطراد صغير يتعلق بالمصطلحات: USART (جهاز استقبال - مرسل متزامن عالمي) ، كما يوحي الاسم ، يمكن أن يعمل في كلا الوضعين المتزامن وغير المتزامن. وفي مجموعة من الآخرين ، لكنهم لم يثيروا اهتمامنا بعد. من الناحية العملية ، لم أرها تعمل في الوضع المتزامن. لذلك ، جنبًا إلى جنب مع USART ، سأستخدم تعيين UART ، مما يعني تحديدًا الوضع غير المتزامن.

كما هو الحال مع المنافذ ، فإن الخطوة الأولى هي تمكين هذه الوحدة من العمل. نحن ننظر في الوثائق لمعرفة أي بت RCU يتوافق معها ونرى 14 بت RCU_APB2EN_USART0EN. الميزة التالية لـ GD32VF103 ، التي تتبع STM ، هي الحاجة إلى تبديل وضع تشغيل طرف الإخراج من GPIO المعتاد إلى وظيفة بديلة يتم تنشيطها بواسطة القيمة GPIO_APP50 = 0b1011. وفقط للإخراج: يظل ساق الإدخال هو GPIO_HIZ المعتاد. أوه نعم ، في RCU ، يجب أيضًا تمكين إمكانية عمل الوظائف البديلة. يتم ذلك بواسطة البت 0 ، المعروف أيضًا باسم RCU_APB2EN_AFEN.

لكن إعداد UART نفسه ليس صعبًا: في سجل USART0_CTL0 ، نقوم ببساطة بتمكين تشغيله (USART_CTL0_UEN) ، وتشغيل جهاز الإرسال (USART_CTL0_TEN) وجهاز الاستقبال (USART_CTL0_REN) ، وبعد ذلك نقوم بتعيين سعر الصرف في USART0_BAUD كمقسم تردد على مدار الساعة. بتعبير أدق ، ليس تردد الساعة ، ولكن فقط ترددات ناقل APB2 ، ولكن حتى اكتشفنا التوقيت ، فإن ترددات جميع الحافلات هي نفسها وتساوي 8 ميجاهرتز:







  la t0, USART0_BASE
    li t1, 8000000 / 9600
  sw t1, USART_BAUD_OFFSET(t0)
    li t1, USART_CTL0_UEN | USART_CTL0_REN | USART_CTL0_TEN
  sw t1, USART_CTL0_OFFSET(t0)

  la t0, USART0_BASE
    li t1, 'S'
  sb t1, USART_DATA_OFFSET(t0)
      
      





, … , .

USART0_DATA.

, ,







$ screen /dev/ttyUSB0 9600
      
      





'S' . screen, ctrl+a, k, y.







8.



. UART : . , . , UART : 9600 , 115200. 8 , 108 , , . USART_STAT_TBE (Transmit data buffer empty) USART0_STAT.

:







void uart_puts(char *str){
  while(str[0] != '\0'){
    while(! (USART0_STAT & USART_STAT_TBE) ){}
    USART0_DATA = str[0];
    str++;
  }
}
      
      





, , 14 .

, USART_STAT_RBNE (Read data buffer not empty), '\r' '\n' .

UART , , .







9.



, . , , . , ?

— , , . (polling) . , . UART , , — .

, , USB, . , , (-, ), . ?

— , . : , . , .

RISC-V : , , ( ), . , . : , , . , , . , , , . , , , . , , .

, , sp.

, . GD32VF103 eclic (Enhanced Core Local Interrupt Controller). , . , , , . : (NMI), (traps) (interrupts). , . ( breakpoint ecall ebreak), . , ( ) . UART`.

eclic . , . scrr () scrw (). , , mtvec. 26 , 6 — : 3 eclic, — , clic ( ?):







  la t0, trap_entry
    andi t0, t0, ~(64-1) #      64 
    ori t0, t0, CSR_MTVEC_ECLIC
  csrw CSR_MTVEC, t0
      
      





, , , 64- . .align 6:







.align 6
trap_entry:
  push t0
  push t1
  push a0

  la t0, GPIOB_OCTL
  lh t1, 0(t0)
    xori t1, t1, (1<<GLED)
  sh t1, 0(t0)

  la t0, USART0_BASE
    la t1, USART_CTL0_UEN | USART_CTL0_REN | USART_CTL0_TEN
  sw t1, USART_CTL0_OFFSET(t0)
    la t1, 'I'
  sw t1, USART_DATA_OFFSET(t0)

  la a0, 100000
  call sleep

  pop a0
  pop t1
  pop t0
mret
      
      





UART`, . , - . , — . UART USART_CTL0_TBEIE, , . . 'I' . . , , - .

USART_CTL0_TBEIE USART0_CTL0, . eclic . :







  #    USART0 (eclic_int_ie[i] = 1)
  la t0, (ECLIC_ADDR_BASE + ECLIC_INT_IE_OFFSET + USART0_IRQn*4)
    la t1, 1
  sb t1, 0(t0)

  #  
  csrrs zero, CSR_MSTATUS, MSTATUS_MIE
      
      





. ECLIC_ADDR_BASE + ECLIC_INT_IP_OFFSET , . :







struct{
  uint8_t clicintip; //interrupt pending
  uint8_t clicintie; //interrupt enable
  uint8_t clicintattr; //attributes
  uint8_t clicintctl; //level and priority
}eclic_interrupt[ECLIC_NUM_INTERRUPTS];
      
      





  • clicintip — . . .
  • clicintie — . , clicintip . .
  • clicintattr — . clicintip ( 0->1 1->0) . .
  • clicintctl — . .


, 8-, sb. , - , . , , , , . , , .

USART0_IRQ 56- , clicintie, 1.

, USART_CTL0_TBEIE, . , , , .

UPD: : . , ? , — , ( ?), . ( RISC-V ) mscratchcsw. :







csrrw sp, mscratchcsw, sp
  # - 
csrrw sp, mscratchcsw, sp
      
      





10.



, , , . . , ecall. , . , , 16-, 32-. , . 32-. ra, mepc, 4 .

, . , . mcause, 31- , . 1, , 0 — . . 0-11 ( 31- 0) ( 1). :







0 — instruction address misaligned,

1 — instruction access fault,

2 — illegal instruction,

3 — breakpoint, ebreak

4 — load address misaligned,

5 — load address fault,

6 — store/AMO misaligned,

7 — store/AMO access fault,

8 — enviroment call from U-mode, ecall,

9 — ?

10 — ?

11 — Enviroment call from M-mode, ecall,

2, 3 11.

( 2) . , 0xFFFF'FFFF ( ).

ebreak ( 3) . 32-. , ebreak 2 . , .

ecall 11- , 8- . , , . .

( 0xFFFF'FFFF), ecall. .







. , eclic? mcause. . UART` . "" , . , :







.align 6
trap_entry:
  push t0
  push t1
  push a0

  csrr a0, CSR_MCAUSE
  la t1, (1<<31)
  and t1, a0, t1 #t1 - interrupt / trap
    beqz t1, trap_exception
 #interrupt

  la t0, GPIOB_OCTL
  lh t1, 0(t0)
    xori t1, t1, (1<<GLED)
  sh t1, 0(t0)

  la t0, 0xFFF
  and a0, a0, t0
  la t0, USART0_IRQn
    bne t0, a0, trap_end

  la t0, USART0_BASE
    la t1, USART_CTL0_UEN | USART_CTL0_REN | USART_CTL0_TEN
  sw t1, USART_CTL0_OFFSET(t0)
    la t1, 'I'
  sw t1, USART_DATA_OFFSET(t0)

trap_end:
  la a0, 100000
  call sleep

  pop a0
  pop t1
  pop t0
mret
trap_exception:
  la t0, GPIOB_OCTL
  lh t1, 0(t0)
    xori t1, t1, (1<<RLED)
  sh t1, 0(t0)

  csrr t0, CSR_MEPC
  addi t0, t0, 4
  csrw CSR_MEPC, t0
j trap_end
      
      





11.



: . , . mtvt2: 30 , 1- , (mtvt2 + mtvec) 1, . , 4- . :







  la t0, irq_entry
  csrw CSR_MTVT2, t0 #   4 
  csrs CSR_MTVT2, 1
      
      





. , mcause:







align 2
irq_entry:
  push t0
  push t1
  push a0

  csrr a0, CSR_MCAUSE
  la t0, 0xFFF
  and a0, a0, t0
  la t0, USART0_IRQn
    bne t0, a0, irq_end

  la t0, USART0_BASE
    la t1, USART_CTL0_UEN | USART_CTL0_REN | USART_CTL0_TEN
  sw t1, USART_CTL0_OFFSET(t0)
    la t1, 'I'
  sw t1, USART_DATA_OFFSET(t0)

  la t0, GPIOB_OCTL
  lh t1, 0(t0)
    xori t1, t1, (1<<YLED)
  sh t1, 0(t0)

  la a0, 100000
  call sleep

irq_end:
  pop a0
  pop t1
  pop t0
mret
      
      





, .







12.



. . 64, 128, 256, 512, 1024, 2048, 4096, 8192 16384 . , : - (OR) . 86 , 4 , 344 . , — 512, .align 9. , , . . : . , . , 4 :







.text
.section .init
...
.align 9
vector_base:
  j _start
  .align    2
  .word     0
  .word     0
  .word     eclic_msip_handler
...
  .word     RTC_IRQHandler
...
  .word     SPI1_IRQHandler
  .word     USART0_IRQHandler
...
.align 2
.text
.global _start
_start:
  la sp, _stack_end
...
      
      





. . , UART







USART0_IRQHandler:
  push t0
  push a0

  la t0, USART0_BASE
    la a0, USART_CTL0_UEN | USART_CTL0_REN | USART_CTL0_TEN
  sw a0, USART_CTL0_OFFSET(t0)
    la a0, 'U'
  sw a0, USART_DATA_OFFSET(t0)

  la t0, GPIOB_OCTL
  lh a0, 0(t0)
    xori a0, a0, (1<<GLED)
  sh a0, 0(t0)

  la a0, 100000
  call sleep

  pop a0
  pop t0
mret
      
      





mtvt:







  la t0, vector_base
  csrw CSR_MTVT, t0
      
      





clicintattr . : 1 2 :

0b00, 0b01 — , clicintip

0b10 — , 0 1

0b11 — , 1 0.

, EXTI, . .

0 - . 0 ( ) - , 1 — .







#     (eclic_int_attr[i] = 1)
  la t0, (ECLIC_ADDR_BASE+ECLIC_INT_ATTR_OFFSET+USART0_IRQn*4)
    la t1, 1
  sw t1, 0(t0)
      
      





- , UART .

- , .







  la t0, nmi_entry
  csrs CSR_MNVEC, t0
  li t0, (1<<9)
  csrs CSR_MMISC_CTL, t0
      
      





13.



, . . . , , . , startup.S, main.c. ` , UART' , , . -. , . pinmacro.h :







#define RLED B, 5, 1, GPIO_PP50
#define SBTN B, 0, 0, GPIO_HIZ
...
GPIO_config( RLED );
GPIO_config( SBTN );
GPO_ON( RLED );
if( GPI_ON( SBTN ) )GPIO_OFF( RLED);
      
      





main . argc argv. - return.







  li a0, 0
  li a1, 0
  call main

INF_LOOP:
.weak UnhandledInterruptHandler
UnhandledInterruptHandler:
  j INF_LOOP
      
      





, . , :







.weak IRQHandler
IRQHandler:
.weak NMIHandler
NMIHandler:
.weak TrapHandler
TrapHandler:
j UnhandledInterruptHandler
      
      





, . , . . UnhandledInterruptHandler .

.weak, , , (, , ...) - , , , , , "".

, , '. , , .start, , .

, ' . , . lib.







14.



, . , , . , lib/Firmware/RISCV/drivers/n200_func.c. eclic_set_vmode ( ) eclic_enable_interrupt ( ). - . , :







#define eclic_global_interrupt_enable() set_csr(mstatus, MSTATUS_MIE)
#define eclic_global_interrupt_disable() clear_csr(mstatus, MSTATUS_MIE)
      
      





n200_func.c makefile src. , eclic_init, ( !). , . , SystemCoreClock. , .

, : ( t0-t6), mret ret. ' , , :







__attribute__((interrupt)) void USART0_IRQHandler(void)
      
      





, , lib/interrupt_util.h . , .

, , main , — , . , , :







__attribute__((naked)) int main();
      
      





, , .







, .









RISC-V , AVR ARM . , , , , . : , — . , , .

USART_DATA( USART0 ) DMA , stm32. .

RISC-V ARM, , . RISC-V : - ( li, , , "Myriad sequences"). , .

GD32VF103 ? . . GigaDevice stm32f103, . , stm32l151. — , , stm32f103. , RISC-V — x86, ARM, RISC-V - .









https://habr.com/ru/post/516006/

https://www.youtube.com/watch؟v=M0dEugoU8PM&list=PL6kSdcHYB3x4okfkIMYgVzmo3ll6a9dPZ

https://www.youtube.com/watch؟v=LyQcTmNcSpY&list=PL6kSdcHYB3x6KOBxEP1YZAzR8hkMQoEva

الشبكي: //doc.nucleisys.com/nuclei_spec/isa/eclic.html

http://www.gd32mcu.com/en/download/0؟kw=GD32VF1








All Articles