К1921ВГ015 общее

32-разрядные микроконтроллеры разработки АО "НИИЭТ"

Модераторы: ea, dav, bkolbov, Alis, pip, _sva_

RabidRabbit
Сообщения: 271
Зарегистрирован: 10 июн 2025, 12:11
Предприятие: HomeWork

Re: К1921ВГ015 общее

Сообщение RabidRabbit »

Проверено на компиляторах gcc-14.2 и gcc-16.1
Аватара пользователя
ejsan
Сообщения: 118
Зарегистрирован: 15 авг 2022, 21:17
Предприятие: vbrspb.ru

Re: К1921ВГ015 общее

Сообщение ejsan »

Так то CRC32, а я-то считал CRC16. Или цимес в том, что восьмибитный DR8 вносит задержки? Мм...или операции сдвига в процессе набивания DR, DR16 добавляют достаточно задержек, чтобы блок успевал проворачиваться? :?
RabidRabbit
Сообщения: 271
Зарегистрирован: 10 июн 2025, 12:11
Предприятие: HomeWork

Re: К1921ВГ015 общее

Сообщение RabidRabbit »

Не знаю, что такое "цимес".

Но в пример добавил CRC16 и CRC8. В функцию do_crc() на вход добавились полином и его размер.
Выхлоп этого примера при сборке с -Ofast:

Код: Выделить всё

CRC32/POSIX  = 0x765E7680 OK
CRC32/MPEG2  = 0x0376E6E7 OK
CRC32/BZIP2  = 0xFC891918 OK
CRC32/zlib   = 0xCBF43926 OK
CRC32/JAMCRC = 0x340BC6D9 OK
CRC32D       = 0x87315576 OK
CRC16/XModem = 0x000031C3 OK
CRC16/MODBUS = 0x00004B37 OK
CRC8/MAXIM   = 0x000000A1 OK
That's all, folks!
sam1970
Сообщения: 6
Зарегистрирован: 16 апр 2026, 15:56
Предприятие: КБ РУСЬ

Re: К1921ВГ015 общее

Сообщение sam1970 »

mkf писал(а): ↑27 июл 2026, 05:11
RabidRabbit писал(а): ↑24 июл 2026, 21:08 Быстрее микросекунды захода в прерывание не сделаете Особенно используя plib015.
plib015 тут прчием?
Вход в прерывание тут - startup_k1921vg015.S
Вот он и съедает основное время - сохраняет все регистры при вызове и восстанавливает при возврате.
Здесь да, будет больше 1 мкс.
Кардинально можно снизить накладные расходы на прерывания если заставить сохранять контекст сам компилятор.
Вот нерабочий пример.

Код: Выделить всё

float EF;
__attribute__((interrupt,flatten))  void IRQ(void)
{
	EF+=0.331f;
}
что дает нам прилично оптимизированный обработчик

Код: Выделить всё

40000062:	7179                	addi	sp,sp,-48
40000064:	d616                	sw	t0,44(sp)
40000066:	003022f3          	frcsr	t0
4000006a:	d23a                	sw	a4,36(sp)
4000006c:	d03e                	sw	a5,32(sp)
4000006e:	8000e737          	lui	a4,0x8000e
40000072:	e63a                	fsw	fa4,12(sp)
40000074:	e43e                	fsw	fa5,8(sp)
40000076:	e1072707          	flw	fa4,-496(a4) # 8000de10 <Font_5x8+0x608>
4000007a:	b681a787          	flw	fa5,-1176(gp) # 400202f8 <Ef>
4000007e:	d416                	sw	t0,40(sp)
40000080:	52a2                	lw	t0,40(sp)
40000082:	00e7f7d3          	fadd.s	fa5,fa5,fa4
40000086:	b6f1a427          	fsw	fa5,-1176(gp) # 400202f8 <Ef>
4000008a:	00329073          	fscsr	t0
4000008e:	52b2                	lw	t0,44(sp)
40000090:	5712                	lw	a4,36(sp)
40000092:	5782                	lw	a5,32(sp)
40000094:	6732                	flw	fa4,12(sp)
40000096:	67a2                	flw	fa5,8(sp)
40000098:	6145                	addi	sp,sp,48
4000009a:	30200073          	mret
к нему требуется обвязка:

Код: Выделить всё

trap_entry:

			addi	sp, sp, -16
			sw		a0, 4(sp)
			sw		a1, 8(sp)
			sw		a2, 12(sp)

			csrr	a2, mepc
			csrr	a0, mcause
			bgez	a0, __Trap	// if ( int(mcause) >= 0 ) goto __Trap

			andi	a0, a0, 15
			li		a1, 11
			bne		a0, a1, __Next	// if mcause != 11 goto __Next

			la		a0, __Label1
			csrw	mepc, a0 // mepc = __Label1

			li		a0,0x80 // MPIE
			csrc	mstatus, a0 // mstatus.MPIE = 0

			lui		a0, 0xc200
			lw		a1, 4(a0) // a1 = PLIC->MICC

			la		a0, mach_plic_handler
			sh2add	a0, a1, a0 // a0 = a0 + a1*4
			lw		a0, (a0) // a0 = mach_plic_handler[a1]

__CallIRQ:
			jr		a0	//  

__Label1:
			li		a0,0x1880		// MPP
			csrs	mstatus, a0		// mstatus.MPIE = 0 MPP = 0

			lui		a0, 0xc200
			sw		a1, 4(a0)		//  PLIC->MICC = a1

__trap_Exit:
			csrw	mepc,a2
			lw		a0, 4(sp)
			lw		a1, 8(sp)
			lw		a2, 12(sp)
			addi	sp, sp, 16
			mret

__Next:
			li		a1, 7
			bne		a0, a1, __Trap

			j		__trap_Exit

__Trap:

			csrr	a1, mtval
__TrapLoop: j __TrapLoop
Этот код уходит в __Trap после mret из вложенного обработчика с mcause = Instruction access fault по адресу __Label1.
Если кто может протестируйте на другом кристалле RISK-V архитектуры, не пойму в чем засада.
RabidRabbit
Сообщения: 271
Зарегистрирован: 10 июн 2025, 12:11
Предприятие: HomeWork

Re: К1921ВГ015 общее

Сообщение RabidRabbit »

sam1970 писал(а): ↑17 сен 2026, 16:37 к нему требуется обвязка:
Просьба пояснить, зачем функции с атрибутом "interrupt" нужна какая-то "обвязка?
Лично у меня в коде так:

Код: Выделить всё

reset_handler:
    ...
    # mtvec
    la_abs  t0, trap_handler
    csrw mtvec, t0
и так

Код: Выделить всё

__attribute__ ((interrupt,used,aligned(16)))
void trap_handler(void) {
  // регистр инфы о прерывании
  uint32_t v_mcause = read_csr(mcause);
  //
  if ( 0 != (v_mcause & MCAUSE_INTERRUPT_FLAG) ) {
    // то, что можно обработать
    v_mcause &= ~MCAUSE_INTERRUPT_FLAG;
    //
    switch ( v_mcause ) {
      case MCAUSE_INTERRUPT_MACHINE_EXTERNAL:
        process_machine_interrupt();
        break;
        
      case MCAUSE_INTERRUPT_MACHINE_TIMER:
        process_timer_interrupt();
        break;
        
      case MCAUSE_INTERRUPT_MACHINE_SOFTWARE:
        process_software_interrupt();
        // убираем флаг программного прерывания
        CLINT->MSIP0 = 0;
        break;
        
      default:
        // тут коды прерываний от S-mode, попадать сюда не должны, но если попали - так и будем тут
        break;
    }
  } else {
    // зависон, всё время будет сюда попадать
  }
}
RabidRabbit
Сообщения: 271
Зарегистрирован: 10 июн 2025, 12:11
Предприятие: HomeWork

Re: К1921ВГ015 общее

Сообщение RabidRabbit »

sam1970 писал(а): ↑17 сен 2026, 16:37 не пойму в чем засада.
Непонятка №1:

Код: Выделить всё

			la		a0, __Label1
			csrw	mepc, a0 // mepc = __Label1
			...
__CallIRQ:
			jr		a0	//  
Вы похоже запускаете отсюда код, который завершается командой mret, при этом ещё и сбрасываете MSTATUS.MPIE, чтобы при возврате прерывания были выключены. Не проще ли обойтись без этого и звать обычную функцию, которая завершается командой ret?

Засада №1:

Код: Выделить всё

__trap_Exit:
			csrw	mepc,a2
Здесь Вы якобы восстанавливаете содержимое MEPC, хотя вызываемый Вами код обработчика вполне законно может затереть содержимое регистра A2, так как забота о сохранности содержимого этого регистра лежит на вызывающем коде. Т.е. здесь вместо A0..A2 лучше бы использовать S0..S2, так как их при необходимости сохранит вызываемая функция.
sam1970
Сообщения: 6
Зарегистрирован: 16 апр 2026, 15:56
Предприятие: КБ РУСЬ

Re: К1921ВГ015 общее

Сообщение sam1970 »

:lol: Это оказывается рабочий код, нужно было после прошивки питанием перезагружать. Подвис контроллер прерываний.
В приведенном подходе внутри кода на С или С++ мы пишем обработчики которые имеют атрибут _прерывания_.
Посмотрите на объявление IRQ.

Код: Выделить всё

float EF;
__attribute__((interrupt,flatten))  void IRQ(void)
{
	EF+=0.331f;
}

void main()
{
	PLIC_SetIrqHandler( Plic_Mach_Target, VECTNUM, IRQ ); // mach_plic_handler[VECTNUM] = IRQ
}
Это позволяет самому компилятору оптимизировать контекст сохранения, что было приведено в дизассемблере IRQ.
Теперь откройте ассемблерный код вашего обработчика и сравните. В Вашем случае компилятор сохраняет полный контекст.
В приведенном мной примере задержки от возникновения до обработки в разы меньше, особенно при использовании FPU.
RabidRabbit
Сообщения: 271
Зарегистрирован: 10 июн 2025, 12:11
Предприятие: HomeWork

Re: К1921ВГ015 общее

Сообщение RabidRabbit »

Да, ваш способ ускорения весьма оригинален и наверняка даст заметное уменьшение накладных расходов там, где идёт борьба за доли микросекунд.

В моём случае для trap_handler сохраняются только регистры, которые нужно сохранять вызывающей стороне, что вроде бы не тянет на "полный контекст" :) К тому же, не люблю писать на ассемблере без крайней необходимости :)
durimar_13
Сообщения: 114
Зарегистрирован: 26 фев 2025, 13:06
Предприятие: Radioamateur
Откуда: Свердловская обл.

Re: К1921ВГ015 общее

Сообщение durimar_13 »

RabidRabbit писал(а): ↑17 сен 2026, 21:09 Да, ваш способ ускорения весьма оригинален и наверняка даст заметное уменьшение накладных расходов там, где идёт борьба за доли микросекунд.

В моём случае для trap_handler сохраняются только регистры, которые нужно сохранять вызывающей стороне, что вроде бы не тянет на "полный контекст" :) К тому же, не люблю писать на ассемблере без крайней необходимости :)
В силу низкой квалификации понял только, что есть способ ускорить обработку прерываний. И это для меня актуально будет. Возьму на заметку!
Спасибо вам обоим.
С уважением, Виктор.
Baloda
Сообщения: 3
Зарегистрирован: 23 сен 2026, 16:16
Предприятие: ГранатБиоТех

Re: К1921ВГ015 общее

Сообщение Baloda »

Здравствуйте. Не могу понять, что делаю неправильно.
Стандартный пример ADCSD. На вход подключена разряженная батарейка 0.9В.
Отсчеты с АЦП гуляют в десятых вольта. Это для данной АЦП нормально, или что-то я не включил/настроил?
Заранее спасибо.
Ответить

Вернуться в «32-разрядные микроконтроллеры»