RISC-Vを最初から学ぶ、パート2:割り込みとCドッキング



GD32VF103CBT6コントローラーの構造について引き続き詳しく説明します。次に、高レベルのコードの制御下で機能するように割り込みを処理する方法を見てみましょう。

最初の部分はここにあります







7.UART接続



再帰の問題を選択するときに、複雑なアルゴリズムをデバッグするには3つのLEDでは不十分であるという問題に遭遇しました。それでは、screenのような端末プログラムがプレーンテキストを使用してコントローラーとフックして通信できる本格的なデバッグインターフェイスを追加しましょう。これを行うには、ファームウェアに使用されているのと同じUSART0を使用します。

用語に関連する小さな逸脱:USART(ユニバーサル同期-非同期受信機-送信機)は、その名前が示すように、同期モードと非同期モードの両方で機能します。そして他の多くの人たちですが、彼らはまだ私たちにとって興味がありません。実際には、同期モードで動作するのを見たことがありません。したがって、USARTとともに、非同期モードを意味するUART指定を使用します。

ポートと同様に、最初のステップはこのモジュールを有効にすることです。ドキュメントを調べて、対応するRCUビットを確認し、RCU_APB2EN_USART0ENの14番目のビットを確認します。 STMに続くGD32VF103の次の機能は、出力ピンの動作モードを通常の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バス周波数のみですが、クロッキングがわかるまで、すべてのバスの周波数は同じで、8MHzに等しくなります。







  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

ます。https: //doc.nucleisys.com/nuclei_spec/isa/eclic.html

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








All Articles