stm32 USB host
stm32 USB host
Здравствуйте. Не могу установить постоянное подключение контроллера(stm32h745) с мышкой.
Хронология:
1. На прерывании Port connect detected делаю Port reset
2. ядро устанавливает Port enable
3. В GINTSTS прилетает disconnect и сбрасывается Port enable.
и так по кругу с частотой 1-2 гц.
Я должен успеть что-то отправить мышке (например get descriptor) или соединение уже должно быть постоянным?
Мышь low speed-ная, я вижу это в статусе подключения в HPRT. Я уж и фрейм интервал поставил 1мс (резет валуе 1.25) и частоту PHY 48/8=6 сделал. Может мне D+ D- поменять местами?
Пробую отправить get descriptor в момент подключения, в ответ... нифига.
В device режиме все работает, скопировал по дескрипторам мышку, жму кнопку - мышь едет.
Хронология:
1. На прерывании Port connect detected делаю Port reset
2. ядро устанавливает Port enable
3. В GINTSTS прилетает disconnect и сбрасывается Port enable.
и так по кругу с частотой 1-2 гц.
Я должен успеть что-то отправить мышке (например get descriptor) или соединение уже должно быть постоянным?
Мышь low speed-ная, я вижу это в статусе подключения в HPRT. Я уж и фрейм интервал поставил 1мс (резет валуе 1.25) и частоту PHY 48/8=6 сделал. Может мне D+ D- поменять местами?
Пробую отправить get descriptor в момент подключения, в ответ... нифига.
В device режиме все работает, скопировал по дескрипторам мышку, жму кнопку - мышь едет.
Re: stm32 USB host
Я точно не понял что произошло, но все заработало. Сначала я подключил флешку вместо мышки на FS, потом и мышка стала отвечать на LS.
Re: stm32 USB host
[uquote="danone78",url="/forum/viewtopic.php?p=4652393#p4652393"]Я точно не понял что произошло, но все заработало. Сначала я подключил флешку вместо мышки на FS, потом и мышка стала отвечать на LS.[/uquote]Если "не понял", то значит завтра с большой вероятностью снова отвалится. Раз причина не найдена.
Re: stm32 USB host
Притом, с большой вероятностью сработает такая же последовательность действий. Я бы проверил цепи питания, на предмет ненужных пульсаций, всплесков/провалов, помех.
Эти слова (если не в шутку сказаны) немного пугают и наводят на всякие мысли... это демо-отладочная плата, или что-то самодельное? если последнее, то к схеме и трассировке USB множество вопросов может быть.danone78 писал(а):Может мне D+ D- поменять местами?
Re: stm32 USB host
Не то чтобы все отвалилось, но далеко я не продвинулся. Все что удалось это отправить get descriptor, получить ACK+XFRC одновременно, потом отправить пустой пакет. Пытаюсь отправить токен IN - или ошибка передачи или STALL. Можно принимать ответы на том же канале на котором отправляю запросы? А то с другими каналами совсем плохо, все зависает по непонятным причинам, размаскировываю канал, отправляю пустой пакет или токен IN(то есть FIFO не трогаю) и зависаю, пытаюсь прочитать и очистить его регистр прерывания, а там нули и сбрасывать нечего, но с прерывания не выйти.
Добавлено after 13 minutes 41 second:
В Device режиме можно включить несколько конечных точек одновременно, с каналами видимо, надо выключать канал перед включением другого, хотя они по xfrc должны сами выключатсья, ща залогаю регистр управления каналом гляну что там происходит.
Добавлено after 5 hours 53 minutes 17 seconds:
Лед тронулся. Вот уж такую козу я не ожидал. Отправил get descriptor на CH0, получил АСК+XFRC. При отправке токена IN на CH1 выскакивают прерывания конечных точек! В общем я их замаскал и вуаля, получаю первый дескриптор.
Добавлено after 13 minutes 41 second:
В Device режиме можно включить несколько конечных точек одновременно, с каналами видимо, надо выключать канал перед включением другого, хотя они по xfrc должны сами выключатсья, ща залогаю регистр управления каналом гляну что там происходит.
Добавлено after 5 hours 53 minutes 17 seconds:
Лед тронулся. Вот уж такую козу я не ожидал. Отправил get descriptor на CH0, получил АСК+XFRC. При отправке токена IN на CH1 выскакивают прерывания конечных точек! В общем я их замаскал и вуаля, получаю первый дескриптор.
Re: stm32 USB host
Вообще из всей периферии на stm32, USB самая вредная. Все упирается в прерывания и статусный регистр:
- Некоторые прерывания просто не маскируются вообще
- некоторые маскируются (не срабатывают), но биты в статусном регистре устанавливаются
- есть и такие которые не устанавливают бит, но срабатывают.
- IEPINT срабатывает в принудительном хост режиме при DAINT=0.
Самое веселье начинается, когда переключаешь режим и делаешь core soft reset - карета превращается в ТЫКВУ!
Весь этот выпендрешь с On-The-Go приводит к глюкам в работе конечных автоматов.
- Некоторые прерывания просто не маскируются вообще
- некоторые маскируются (не срабатывают), но биты в статусном регистре устанавливаются
- есть и такие которые не устанавливают бит, но срабатывают.
- IEPINT срабатывает в принудительном хост режиме при DAINT=0.
Самое веселье начинается, когда переключаешь режим и делаешь core soft reset - карета превращается в ТЫКВУ!
Весь этот выпендрешь с On-The-Go приводит к глюкам в работе конечных автоматов.
Re: stm32 USB host
[uquote="danone78",url="/forum/viewtopic.php?p=4654784#p4654784"]Вообще из всей периферии на stm32, USB самая вредная. Все упирается в прерывания и статусный регистр:
- Некоторые прерывания просто не маскируются вообще
- некоторые маскируются (не срабатывают), но биты в статусном регистре устанавливаются[/uquote]Вообще-то это и правильно. Странно ожидать другого.
[uquote="danone78",url="/forum/viewtopic.php?p=4654784#p4654784"]- есть и такие которые не устанавливают бит, но срабатывают.[/uquote]С stm32h745 не работал, но ваял USB-device в STM32Lxxx. Не Кубом, а самостоятельно. И особенных проблем не встретил. Почти всё работало нормально. Единственный косяк, на который наткнулся - неполная поддержка изохронного режима.
Но у меня был только device-режим. Без всяких host или OTG.
- Некоторые прерывания просто не маскируются вообще
- некоторые маскируются (не срабатывают), но биты в статусном регистре устанавливаются[/uquote]Вообще-то это и правильно. Странно ожидать другого.
[uquote="danone78",url="/forum/viewtopic.php?p=4654784#p4654784"]- есть и такие которые не устанавливают бит, но срабатывают.[/uquote]С stm32h745 не работал, но ваял USB-device в STM32Lxxx. Не Кубом, а самостоятельно. И особенных проблем не встретил. Почти всё работало нормально. Единственный косяк, на который наткнулся - неполная поддержка изохронного режима.
Но у меня был только device-режим. Без всяких host или OTG.
Re: stm32 USB host
Мне повезло, раньше на куб инфы не было вообще, и мне пришлось начинать в Keil. А там есть возможность писать прямо в асме, что меня несказанно радовало. АРМовцы поздно прочухали что такое людям давать нельзя, вся их инфа вместе с архитектурами ядер разлетелась по свету.
STM-щики в своих RM-ах гениально обтекают многие нюансы. Мне вообще кажется, что у них наш Сергей Лавров работает на RM-ах.
Добавлено after 28 minutes 4 seconds:
У меня уже все работает, но вся эта возня с дескрипторами мне кажется не обязательна.
Если я подключаю USB устройство и знаю что это мышь и что она с конечной точки 1 будет слать мне interrupt данные, почему бы просто сразу не открыть ей канал и послать set_configuration, без адресации без ничего?
Я например так реализовал микро веб сервер, все htm страницы умещаются в один сегмент 1420 байт, я просто разворачиваю секвенции и отправляю ответы. Все гениально, просто и работает с любого смартфона через вайфай.
STM-щики в своих RM-ах гениально обтекают многие нюансы. Мне вообще кажется, что у них наш Сергей Лавров работает на RM-ах.
Добавлено after 28 minutes 4 seconds:
У меня уже все работает, но вся эта возня с дескрипторами мне кажется не обязательна.
Если я подключаю USB устройство и знаю что это мышь и что она с конечной точки 1 будет слать мне interrupt данные, почему бы просто сразу не открыть ей канал и послать set_configuration, без адресации без ничего?
Я например так реализовал микро веб сервер, все htm страницы умещаются в один сегмент 1420 байт, я просто разворачиваю секвенции и отправляю ответы. Все гениально, просто и работает с любого смартфона через вайфай.
Re: stm32 USB host
[uquote="danone78",url="/forum/viewtopic.php?p=4657655#p4657655"]мне пришлось начинать в Keil. А там есть возможность писать прямо в асме, что меня несказанно радовало. АРМовцы поздно прочухали что такое людям давать нельзя, вся их инфа вместе с архитектурами ядер разлетелась по свету.[/uquote]Вообще не понял что тут написано...
Как именно ARMовцы мешают вам писать на асме? Что "давать нельзя" и почему?
Или вы - конспиролог?
Как именно ARMовцы мешают вам писать на асме? Что "давать нельзя" и почему?
Или вы - конспиролог?
- HardWareMan
- Мучитель микросхем
- Сообщения: 429
- Зарегистрирован: Ср сен 02, 2015 07:47:20
Re: stm32 USB host
[uquote="danone78",url="/forum/viewtopic.php?p=4657655#p4657655"]Мне повезло, раньше на куб инфы не было вообще, и мне пришлось начинать в Keil. А там есть возможность писать прямо в асме, что меня несказанно радовало. АРМовцы поздно прочухали что такое людям давать нельзя, вся их инфа вместе с архитектурами ядер разлетелась по свету.
STM-щики в своих RM-ах гениально обтекают многие нюансы. Мне вообще кажется, что у них наш Сергей Лавров работает на RM-ах.[/uquote]
А мужики то не в курсе! Вот пример моего говнокодинга на асме под Eclipse для ARM EABI:
STM-щики в своих RM-ах гениально обтекают многие нюансы. Мне вообще кажется, что у них наш Сергей Лавров работает на RM-ах.[/uquote]
А мужики то не в курсе! Вот пример моего говнокодинга на асме под Eclipse для ARM EABI:
Спойлер
Код: Выделить всё
// Набор функций для дампинга картриджей Денди
#include "dumper/dendy.h"
// Отключение режима Денди
void Dendy_Off()
{ // Параметры
GPIO_InitTypeDef GPIO_InStr;
// Отключаем шину
ADR_BUS_Off(); CHR_BUS_Off(); PRG_BUS_Off();
// Деинит управляющих ног Dendy
PRG_F2_Off(); PRG_RnW_Rd(); CHR_PRD_Off(); CHR_PWR_Off(); CHR_nPA13_Off();
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM5, DISABLE); TIM5->CR1 = 0x0000;
GPIO_InStr.GPIO_Pin = 0x0001;
GPIO_InStr.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InStr.GPIO_Speed = GPIO_High_Speed;
GPIO_InStr.GPIO_OType = GPIO_OType_PP;
GPIO_InStr.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init( GPIOA, &GPIO_InStr );
GPIO_ResetBits( GPIOA, 0x0001 );
}
// Включение режима Денди
void Dendy_On()
{ // Параметры
GPIO_InitTypeDef GPIO_InStr;
// Инит общих управляющих ног
ADR_BUS_On(); CHR_BUS_Off(); PRG_BUS_Off();
// Инит управляющих ног Dendy
PRG_F2_Off(); PRG_RnW_Rd(); CHR_PRD_Off(); CHR_PWR_Off(); CHR_nPA13_Off();
GPIO_InStr.GPIO_Pin = 0x0001;
GPIO_InStr.GPIO_Mode = GPIO_Mode_AF;
GPIO_InStr.GPIO_Speed = GPIO_High_Speed;
GPIO_InStr.GPIO_OType = GPIO_OType_PP;
GPIO_InStr.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init( GPIOA, &GPIO_InStr );
GPIO_PinAFConfig( GPIOA, GPIO_PinSource0, GPIO_AF_TIM5 );
// F2: ____------- 200ns/360ns = 560ns/1.786MHz
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM5, ENABLE); TIM5->PSC = 0x0000; TIM5->ARR = 0x0000002E; TIM5->CCR1 = 0x0000001E; TIM5->CCMR1 = 0x0060;
TIM5->CCMR2 = 0x0000; TIM5->CCER = 0x0001; TIM5->SMCR = 0x0000; TIM5->DIER = 0x0000; TIM5->CR2 = 0x0000; TIM5->CR1 = 0x0001;
// Сбрасываем картридж
Dendy_Reset();
}
// Включить программный режим денди
void Dendy_Manual()
{ // Параметры
GPIO_InitTypeDef GPIO_InStr;
// Инит общих управляющих ног
ADR_BUS_On(); CHR_BUS_Off(); PRG_BUS_Off();
// Инит управляющих ног Dendy
PRG_F2_Off(); PRG_RnW_Rd(); CHR_PRD_Off(); CHR_PWR_Off(); CHR_nPA13_Off(); // PRG_ROM_Off();
GPIO_InStr.GPIO_Pin = 0x0001;
GPIO_InStr.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InStr.GPIO_Speed = GPIO_High_Speed;
GPIO_InStr.GPIO_OType = GPIO_OType_PP;
GPIO_InStr.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init( GPIOA, &GPIO_InStr );
// Деактивация F2
GPIO_ResetBits( GPIOA, 0x0001 );
}
// Сброс картриджа
void Dendy_Reset()
{ // Выключаем шину
ADR_BUS_Off(); Delay( 0x3567DFE );
GPIOC->ODR &= 0xFF00; GPIOE->ODR = 0x0000;
ADR_BUS_On(); Delay( 0x3567DFE );
}
// Чтение данных PRG в буфер
__attribute__ ((naked)) void Read_PRG( uint8_t *PBuf, uint32_t Start, uint32_t Size )
{ // Начинаем
__asm volatile
( "PUSH {R0-R8}\n"
// R0 = PBuf
// R1 = Start
// R2 = Size
// R3 = GPIOA_IDR (Для чтения F2)
"MOVW R3, #0x0010\n"
"MOVT R3, #0x4002\n"
// R4 = GPIOE_ODR (Для вывода адреса)
"MOVW R4, #0x1014\n"
"MOVT R4, #0x4002\n"
// R5 = GPIOD_IDR (Для ввода данных)
"MOVW R5, #0x0C10\n"
"MOVT R5, #0x4002\n"
// R6 = Маска $0000FFFF
"MOVW R6, #0xFFFF\n"
"MOVT R6, #0x0000\n"
// Выделим
"AND R1, R1, R6, LSL #0\n"
"AND R2, R2, R6, LSL #0\n"
// Синхронизируемся
"CPSID f\n"
"Read_PRG_Syn0:\n"
"LDR R7, [R3, #0]\n"
"ANDS R7, R7, #1\n"
"IT EQ\n"
"BEQ Read_PRG_Syn0\n"
"Read_PRG_Syn1:\n"
"LDR R7, [R3, #0]\n"
"ANDS R7, R7, #1\n"
"IT NE\n"
"BNE Read_PRG_Syn1\n"
// Цикл чтения
"Read_PRG_Loop:\n"
// Выставляем адрес
"STR R1, [R4, #0]\n"
// Ждем F2 = 1
"Read_PRG_LWt0:\n"
"LDR R7, [R3, #0]\n"
"ANDS R7, R7, #1\n"
"IT EQ\n"
"BEQ Read_PRG_LWt0\n"
// Увеличиваем адрес чтения
"ADD R1, R1, #1\n"
// Ждем F2 = 0
"Read_PRG_LWt1:\n"
"LDR R8, [R5, #0]\n"
"LDR R7, [R3, #0]\n"
"ANDS R7, R7, #1\n"
"IT NE\n"
"BNE Read_PRG_LWt1\n"
// Сохраняем данные
"AND R8, R8, #0x00FF\n"
"STRB R8, [R0, #0]\n"
// Следующий байт
"ADDS R0, R0, #1\n"
// Счетчик байт
"SUB R2, R2, #1\n"
"ANDS R2, R2, R6, LSL #0\n"
"IT NE\n"
"BNE Read_PRG_Loop\n"
"CPSIE f\n"
// Обнулим адрес
"MOVW R6, #0x0000\n"
"STR R6, [R4, #0]\n"
"POP {R0-R8}\n"
"BX LR\n"
);
}
// Чтение данных из картриджа в буфер
void Dendy_Read( uint8_t *PBuf, uint32_t Start, uint32_t Size )
{ // Переменные
uint32_t Delay;
GPIO_InitTypeDef GPIO_InStr;
// Начальные установки
PRG_RnW_Rd(); CHR_In(); PRG_In(); GPIOC->ODR &= 0xFF00;
GPIO_InStr.GPIO_Pin = 0xFFFF;
GPIO_InStr.GPIO_Mode = GPIO_Mode_IN;
GPIO_InStr.GPIO_Speed = GPIO_High_Speed;
GPIO_InStr.GPIO_OType = GPIO_OType_PP;
GPIO_InStr.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init( GPIOD, &GPIO_InStr );
CHR_BUS_On(); PRG_BUS_On();
// Это PRG или CHR?
if ((Start & 0x00FF0000) == 0)
{
Read_PRG( PBuf, Start, Size );
}
else
{ // Маски адресов и размеров
Start &= 0x00003FFF; Size &= 0x00003FFF;
while ((Size & 0x00003FFF) != 0)
{ // Выставляем адрес
GPIOE->ODR = Start & 0x0000FFFF;
// Активируем строб чтения CHR
CHR_PRD_On();
// Ждем
Delay = 3; while (Delay) { Delay -= 1; }
// Забираем данные и отключаем строб
*(PBuf) = (GPIOD->IDR >> 8) & 0x00FF;
// Деактивируем чтение
CHR_PRD_Off();
// Счетчики
PBuf += 1; Start += 1; Size -= 1;
}
}
CHR_BUS_Off(); PRG_BUS_Off();
}
// Запись данных буфера в PRG
__attribute__ ((naked)) void Write_PRG( uint8_t *PBuf, uint32_t Start, uint32_t Size )
{ // Начинаем
__asm volatile
( "PUSH {R0-R11}\n"
// R0 = PBuf
// R1 = Start
// R2 = Size
// R3 = GPIOA_IDR (Для чтения F2)
"MOVW R3, #0x0010\n"
"MOVT R3, #0x4002\n"
// R4 = GPIOA_BSRR (Для управления R/W)
"MOVW R4, #0x0018\n"
"MOVT R4, #0x4002\n"
// R5 = GPIOE_ODR (Для вывода адреса)
"MOVW R5, #0x1014\n"
"MOVT R5, #0x4002\n"
// R6 = GPIOD_ODR (Для вывода данных)
"MOVW R6, #0x0C14\n"
"MOVT R6, #0x4002\n"
// R7 = Маска $0000FFFF
"MOVW R7, 0xFFFF\n"
"MOVT R7, 0x0000\n"
// R8 = Маска $00020000
"MOVW R8, 0x0000\n"
"MOVT R8, 0x0002\n"
// R9 = Маска $00000002
"MOVW R9, 0x0002\n"
"MOVT R9, 0x0000\n"
// R10 - данные записи
"LDRB R10, [R0, #0]\n"
"AND R10, R10, 0x00FF\n"
// Выделим
"AND R1, R1, R7, LSL #0\n"
"AND R2, R2, R7, LSL #0\n"
"CPSID f\n"
// Синхронизируемся
"Write_PRG_Syn0:\n"
"LDR R11, [R3, #0]\n"
"ANDS R11, R11, #1\n"
"IT EQ\n"
"BEQ Write_PRG_Syn0\n"
"Write_PRG_Syn1:\n"
"LDR R11, [R3, #0]\n"
"ANDS R11, R11, #1\n"
"IT NE\n"
"BNE Write_PRG_Syn1\n"
// Выставляем запись
"STR R8, [R4, #0]\n"
// Цикл записи
"Write_PRG_Loop:\n"
// Выставляем адрес
"STR R1, [R5, #0]\n"
// Выставляем данные
"STR R10, [R6, #0]\n"
// Ждем F2 = 1
"Write_PRG_LWt0:\n"
"LDR R11, [R3, #0]\n"
"ANDS R11, R11, #1\n"
"IT EQ\n"
"BEQ Write_PRG_LWt0\n"
// Увеличиваем адрес записи
"ADD R1, R1, #1\n"
// Считываем новые данные
"ADD R0, R0, #1\n"
"LDRB R10, [R0, #0]\n"
"AND R10, R10, 0x00FF\n"
// Ждем F2 = 0
"Write_PRG_LWt1:\n"
"LDR R11, [R3, #0]\n"
"ANDS R11, R11, #1\n"
"IT NE\n"
"BNE Write_PRG_LWt1\n"
// Счетчик байт
"SUB R2, R2, #1\n"
"ANDS R2, R2, R7, LSL #0\n"
"IT NE\n"
"BNE Write_PRG_Loop\n"
// Убираем запись
"STR R9, [R4, #0]\n"
"CPSIE f\n"
// Обнулим адрес
"MOVW R7, 0x0000\n"
"STR R7, [R5, #0]\n"
"POP {R0-R11}\n"
"BX LR\n"
);
}
// Запись данных из буфера в картридж
void Dendy_Write( uint8_t *PBuf, uint32_t Start, uint32_t Size )
{ // Переменные
uint32_t Delay;
GPIO_InitTypeDef GPIO_InStr;
// Начальные установки
PRG_RnW_Rd(); CHR_Out(); PRG_Out(); GPIOC->ODR &= 0xFF00;
GPIO_InStr.GPIO_Pin = 0xFFFF;
GPIO_InStr.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InStr.GPIO_Speed = GPIO_High_Speed;
GPIO_InStr.GPIO_OType = GPIO_OType_PP;
GPIO_InStr.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init( GPIOD, &GPIO_InStr );
CHR_BUS_On(); PRG_BUS_On();
// Это PRG или CHR?
if ((Start & 0x00FF0000) == 0)
{
Write_PRG( PBuf, Start, Size );
}
else
{ // Маски адресов и размеров
Start &= 0x00003FFF; Size &= 0x00003FFF;
while ((Size & 0x00003FFF) != 0)
{ // Выставляем адрес и данные
GPIOE->ODR = Start & 0x0000FFFF; GPIOD->ODR = (GPIOD->ODR & 0x00FF) | (*(PBuf) * 0x100);
// Активируем строб записи CHR
CHR_PWR_On();
// Ждем
Delay = 3; while (Delay) { Delay -= 1; }
// Деактивируем чтение
CHR_PWR_Off();
// Счетчики
PBuf += 1; Start += 1; Size -= 1;
}
}
// Начальное состояние
GPIO_InStr.GPIO_Pin = 0xFFFF;
GPIO_InStr.GPIO_Mode = GPIO_Mode_IN;
GPIO_InStr.GPIO_Speed = GPIO_High_Speed;
GPIO_InStr.GPIO_OType = GPIO_OType_PP;
GPIO_InStr.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init( GPIOD, &GPIO_InStr );
CHR_BUS_Off(); PRG_BUS_Off(); CHR_In(); PRG_In();
}
// Чтение данных в буфер из картриджа в ручном режиме
void Dendy_ManualRead( uint8_t *PBuf, uint32_t Start, uint32_t Size )
{ // Переменные
uint32_t Delay;
GPIO_InitTypeDef GPIO_InStr;
// Начальные установки
PRG_F2_Off(); PRG_RnW_Rd(); CHR_In(); PRG_In(); GPIOC->ODR &= 0xFF00;
GPIO_InStr.GPIO_Pin = 0xFFFF;
GPIO_InStr.GPIO_Mode = GPIO_Mode_IN;
GPIO_InStr.GPIO_Speed = GPIO_High_Speed;
GPIO_InStr.GPIO_OType = GPIO_OType_PP;
GPIO_InStr.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init( GPIOD, &GPIO_InStr );
CHR_BUS_On(); PRG_BUS_On();
// Маски адресов и размеров
Start &= 0x0000FFFF; Size &= 0x0000FFFF;
while ((Size & 0x0000FFFF) != 0)
{ // Выставляем адрес
GPIOE->ODR = Start & 0x0000FFFF;
// Активируем строб чтения CHR
PRG_F2_On();
// Ждем
Delay = 3; while (Delay) { Delay -= 1; }
// Забираем данные и отключаем строб
*(PBuf) = GPIOD->IDR & 0x00FF;
// Деактивируем чтение
PRG_F2_Off();
// Счетчики
PBuf += 1; Start += 1; Size -= 1;
}
// Начальное состояние
PRG_F2_Off(); CHR_BUS_Off(); PRG_BUS_Off();
}
// Запись данных из буфера в картридж в ручном режиме
void Dendy_ManualWrite( uint8_t *PBuf, uint32_t Start, uint32_t Size )
{ // Переменные
uint32_t Delay;
GPIO_InitTypeDef GPIO_InStr;
// Начальные установки
PRG_F2_Off(); PRG_RnW_Wr(); CHR_Out(); PRG_Out(); GPIOC->ODR &= 0xFF00;
GPIO_InStr.GPIO_Pin = 0xFFFF;
GPIO_InStr.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InStr.GPIO_Speed = GPIO_High_Speed;
GPIO_InStr.GPIO_OType = GPIO_OType_PP;
GPIO_InStr.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init( GPIOD, &GPIO_InStr );
CHR_BUS_On(); PRG_BUS_On();
// Маски адресов и размеров
Start &= 0x0000FFFF; Size &= 0x0000FFFF;
while ((Size & 0x0000FFFF) != 0)
{ // Выставляем адрес и данные
GPIOE->ODR = Start & 0x0000FFFF; GPIOD->ODR = (GPIOD->ODR & 0xFF00) | *(PBuf);
// Активируем строб чтения CHR
PRG_F2_On();
// Ждем
Delay = 3; while (Delay) { Delay -= 1; }
// Деактивируем чтение
PRG_F2_Off();
// Счетчики
PBuf += 1; Start += 1; Size -= 1;
}
// Начальное состояние
PRG_F2_Off(); PRG_RnW_Rd();
GPIO_InStr.GPIO_Pin = 0xFFFF;
GPIO_InStr.GPIO_Mode = GPIO_Mode_IN;
GPIO_InStr.GPIO_Speed = GPIO_High_Speed;
GPIO_InStr.GPIO_OType = GPIO_OType_PP;
GPIO_InStr.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init( GPIOD, &GPIO_InStr );
CHR_BUS_Off(); PRG_BUS_Off(); CHR_In(); PRG_In();
}
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Re: stm32 USB host
[uquote="HardWareMan",url="/forum/viewtopic.php?p=4657762#p4657762"]А мужики то не в курсе! Вот пример моего говнокодинга на асме под Eclipse для ARM EABI:[/uquote]Ваш код полон таких пар. А какой смысл в них? Зачем??? 
PS: Код конечно..... ээээ...
как будто главная цель была - сделать как можно более громоздко и медленно. 
Добавлено after 1 hour 14 minutes 22 seconds:
[uquote="HardWareMan",url="/forum/viewtopic.php?p=4657762#p4657762"]А мужики то не в курсе! Вот пример моего говнокодинга на асме под Eclipse для ARM EABI:[/uquote]Если чуток причесать Write_PRG() и перенести её в asm-файл, то получим:
Итого: размер = 84 байта; вместо исходных 180 байт. Да и быстрее должна быть.

Код: Выделить всё
...
"IT EQ\n"
"BEQ Read_PRG_Syn0\n"
...
"IT NE\n"
"BNE Read_PRG_Syn1\n"
...
"IT EQ\n"
"BEQ Read_PRG_LWt0\n"
...PS: Код конечно..... ээээ...
Добавлено after 1 hour 14 minutes 22 seconds:
[uquote="HardWareMan",url="/forum/viewtopic.php?p=4657762#p4657762"]А мужики то не в курсе! Вот пример моего говнокодинга на асме под Eclipse для ARM EABI:
Спойлер
Код: Выделить всё
// Запись данных буфера в PRG
__attribute__ ((naked)) void Write_PRG( uint8_t *PBuf, uint32_t Start, uint32_t Size )
{ // Начинаем
__asm volatile
( "PUSH {R0-R11}\n"
// R0 = PBuf
// R1 = Start
// R2 = Size
// R3 = GPIOA_IDR (Для чтения F2)
"MOVW R3, #0x0010\n"
"MOVT R3, #0x4002\n"
// R4 = GPIOA_BSRR (Для управления R/W)
"MOVW R4, #0x0018\n"
"MOVT R4, #0x4002\n"
// R5 = GPIOE_ODR (Для вывода адреса)
"MOVW R5, #0x1014\n"
"MOVT R5, #0x4002\n"
// R6 = GPIOD_ODR (Для вывода данных)
"MOVW R6, #0x0C14\n"
"MOVT R6, #0x4002\n"
// R7 = Маска $0000FFFF
"MOVW R7, 0xFFFF\n"
"MOVT R7, 0x0000\n"
// R8 = Маска $00020000
"MOVW R8, 0x0000\n"
"MOVT R8, 0x0002\n"
// R9 = Маска $00000002
"MOVW R9, 0x0002\n"
"MOVT R9, 0x0000\n"
// R10 - данные записи
"LDRB R10, [R0, #0]\n"
"AND R10, R10, 0x00FF\n"
// Выделим
"AND R1, R1, R7, LSL #0\n"
"AND R2, R2, R7, LSL #0\n"
"CPSID f\n"
// Синхронизируемся
"Write_PRG_Syn0:\n"
"LDR R11, [R3, #0]\n"
"ANDS R11, R11, #1\n"
"IT EQ\n"
"BEQ Write_PRG_Syn0\n"
"Write_PRG_Syn1:\n"
"LDR R11, [R3, #0]\n"
"ANDS R11, R11, #1\n"
"IT NE\n"
"BNE Write_PRG_Syn1\n"
// Выставляем запись
"STR R8, [R4, #0]\n"
// Цикл записи
"Write_PRG_Loop:\n"
// Выставляем адрес
"STR R1, [R5, #0]\n"
// Выставляем данные
"STR R10, [R6, #0]\n"
// Ждем F2 = 1
"Write_PRG_LWt0:\n"
"LDR R11, [R3, #0]\n"
"ANDS R11, R11, #1\n"
"IT EQ\n"
"BEQ Write_PRG_LWt0\n"
// Увеличиваем адрес записи
"ADD R1, R1, #1\n"
// Считываем новые данные
"ADD R0, R0, #1\n"
"LDRB R10, [R0, #0]\n"
"AND R10, R10, 0x00FF\n"
// Ждем F2 = 0
"Write_PRG_LWt1:\n"
"LDR R11, [R3, #0]\n"
"ANDS R11, R11, #1\n"
"IT NE\n"
"BNE Write_PRG_LWt1\n"
// Счетчик байт
"SUB R2, R2, #1\n"
"ANDS R2, R2, R7, LSL #0\n"
"IT NE\n"
"BNE Write_PRG_Loop\n"
// Убираем запись
"STR R9, [R4, #0]\n"
"CPSIE f\n"
// Обнулим адрес
"MOVW R7, 0x0000\n"
"STR R7, [R5, #0]\n"
"POP {R0-R11}\n"
"BX LR\n"
);
}Спойлер
Код: Выделить всё
SECTION .text:CODE:NOROOT(2)
THUMB
IO_GPIOA EQU 0x40020000
IO_GPIOA_IDR EQU 0x40020010
IO_GPIOA_BSRR EQU 0x40020018
IO_GPIOD_ODR EQU 0x40020C14
IO_GPIOE_ODR EQU 0x40021014
Write_PRG_2: PUSH {R4}
;R0 = PBuf
;R1 = Start
;R2 = Size
;R3 = GPIOA_IDR (Для чтения F2)
LDR R3, =IO_GPIOA
;Выделим
UXTH R1, R1
SUBS R2, R2, #1
UXTH R2, R2
CPSID f
;Синхронизируемся
p2_Syn0: LDR R4, [R3, #IO_GPIOA_IDR - IO_GPIOA]
LSLS R4, R4, #31
BPL p2_Syn0 ;;;
p2_Syn1: LDR R4, [R3, #IO_GPIOA_IDR - IO_GPIOA]
LSLS R4, R4, #31
BMI p2_Syn1
;Выставляем запись
MOVS R4, #0x00020000
STR R4, [R3, #IO_GPIOA_BSRR - IO_GPIOA]
;Цикл записи
p2_Loop: ;Выставляем адрес
LDR R4, =IO_GPIOE_ODR
STR R1, [R4]
;Выставляем данные
LDRB R4, [R0], #1
STR R4, [R3, #IO_GPIOD_ODR - IO_GPIOA]
;Ждем F2 = 1
p2_LWt0: LDR R4, [R3, #IO_GPIOA_IDR - IO_GPIOA]
LSLS R4, R4, #31
BPL p2_LWt0
;Увеличиваем адрес записи
ADDS R1, R1, #1
;Ждем F2 = 0
p2_LWt1: LDR R4, [R3, #IO_GPIOA_IDR - IO_GPIOA]
LSLS R4, R4, #31
BMI p2_LWt1
;Счетчик байт
SUBS R2, R2, #1
BPL p2_Loop
;Убираем запись
MOVS R2, #2
STR R2, [R3, #IO_GPIOA_BSRR - IO_GPIOA]
CPSIE f
;Обнулим адрес
LDR R2, =IO_GPIOE_ODR
STR R4, [R2]
POP {R4}
BX LR- HardWareMan
- Мучитель микросхем
- Сообщения: 429
- Зарегистрирован: Ср сен 02, 2015 07:47:20
Re: stm32 USB host
jcxz, именно поэтому это и говнокод, была такая проба пера лет 10+ назад. Смысл послания был в том, что асм РУКИ не только никто не запрещает использовать, но и позволяется оформить __NAKED__ процедуры на, собсно, "голом" асме, если вы знаете т.н. "соглашение о вызове" для своего языка программирования.
Добавлено after 2 minutes 22 seconds:
[uquote="jcxz",url="/forum/viewtopic.php?p=4657880#p4657880"][uquote="HardWareMan",url="/forum/viewtopic.php?p=4657762#p4657762"]А мужики то не в курсе! Вот пример моего говнокодинга на асме под Eclipse для ARM EABI:[/uquote]Ваш код полон таких пар. А какой смысл в них? Зачем???
[/uquote]
Профдеформация после MCS80, MCS96 и т.д.
Добавлено after 2 minutes 22 seconds:
[uquote="jcxz",url="/forum/viewtopic.php?p=4657880#p4657880"][uquote="HardWareMan",url="/forum/viewtopic.php?p=4657762#p4657762"]А мужики то не в курсе! Вот пример моего говнокодинга на асме под Eclipse для ARM EABI:
Код: Выделить всё
...
"IT EQ\n"
"BEQ Read_PRG_Syn0\n"
...
"IT NE\n"
"BNE Read_PRG_Syn1\n"
...
"IT EQ\n"
"BEQ Read_PRG_LWt0\n"
...Профдеформация после MCS80, MCS96 и т.д.
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Re: stm32 USB host
[uquote="HardWareMan",url="/forum/viewtopic.php?p=4657946#p4657946"]если вы знаете т.н. "соглашение о вызове" для своего языка программирования.[/uquote]Именно поэтому PUSH/POP-ить регистры R0...R3 на входе/выходе функции не нужно. 
Re: stm32 USB host
ну да, при входе в прерывания r0-r3 залетают в стек автоматом, такова архитектура ядра. С вложенными прерываниями я пока не разбирался.
Re: stm32 USB host
[uquote="danone78",url="/forum/viewtopic.php?p=4658150#p4658150"]ну да, при входе в прерывания r0-r3 залетают в стек автоматом, такова архитектура ядра. С вложенными прерываниями я пока не разбирался.[/uquote]Причём тут прерывания? Речь шла о функции. Читайте что такое "соглашения вызова функций". Чтобы понимать о чём идёт речь.
Re: stm32 USB host
Ладно давайте вернемся к USB. Мышь работает не очень хорошо, то halt то nack ответит, через пень колоду короче. Запросы отправляю в начале кадра и только по одному запросу. Че за фигня, кто останавливает канал?
- HardWareMan
- Мучитель микросхем
- Сообщения: 429
- Зарегистрирован: Ср сен 02, 2015 07:47:20
Re: stm32 USB host
[uquote="danone78",url="/forum/viewtopic.php?p=4658369#p4658369"]Ладно давайте вернемся к USB. Мышь работает не очень хорошо, то halt то nack ответит, через пень колоду короче. Запросы отправляю в начале кадра и только по одному запросу. Че за фигня, кто останавливает канал?[/uquote]
А что за мышка? У меня есть аппаратный USB сниффер, я бы мог записать нормальный обмен как эталон, например. Для примеру записал обмен от беспроводной мышки, файл лога в аттаче. Софт для просмотра можно взять на сайте производителя, он с файлами логов работает и без самого устройства, есть ангельский язык, программа работает без установки. Брал его, кстати, как раз для отладки таких случаев, при реализации USB хоста на STM.
А что за мышка? У меня есть аппаратный USB сниффер, я бы мог записать нормальный обмен как эталон, например. Для примеру записал обмен от беспроводной мышки, файл лога в аттаче. Софт для просмотра можно взять на сайте производителя, он с файлами логов работает и без самого устройства, есть ангельский язык, программа работает без установки. Брал его, кстати, как раз для отладки таких случаев, при реализации USB хоста на STM.
- Вложения
-
- Снимок.PNG
- Скриншот
- (241.6 КБ) 67 скачиваний
-
- WirelessMouse.zip
- Wireless Mouse attach log
- (42.13 КБ) 64 скачивания
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: stm32 USB host
[uquote="jcxz",url="/forum/viewtopic.php?p=4654832#p4654832"]ваял USB-device в STM32Lxxx. Не Кубом, а самостоятельно. И особенных проблем не встретил. Почти всё работало нормально. Единственный косяк, на который наткнулся - неполная поддержка изохронного режима.[/uquote]
Ну да. Не считая наркоманский EPnR, у которых часть битов read-only, часть read-write, часть можно только стереть, причем нулем, а часть инвертировать, причем единицей.
А что за проблема с изохронными точками? У меня аудио-девайс (микрофон + динамик) вполне запустился.
Ну да. Не считая наркоманский EPnR, у которых часть битов read-only, часть read-write, часть можно только стереть, причем нулем, а часть инвертировать, причем единицей.
А что за проблема с изохронными точками? У меня аудио-девайс (микрофон + динамик) вполне запустился.
Так а хосту-то об этом откуда узнать? Как узнать сколько кнопок, какое абсолютное смещение соответствует передаваемым данным?danone78 писал(а):У меня уже все работает, но вся эта возня с дескрипторами мне кажется не обязательна.
Если я подключаю USB устройство и знаю что это мышь
Re: stm32 USB host
Пробовал на двух мышках, одна Genius вторая Zornwee, одинаково. Разобрался что надо PID чередовать, вот только черный нечетный кадр пробовал менять и разницы не увидел. Получается что раз в милисеунду обязательно на SOF прерывание залетать? И.. я не понял где кнопки? Смещения координат я получаю, а кнопки то куда? Жму кнопку, прилетает пакет с нулями.
Добавлено after 6 minutes 57 seconds:
К стати давно хотел спросить, какая разница между периодическими и непериодическими запросами?
Добавлено after 9 minutes 41 second:
Единственное отличие в работе мышек, в том что Zornwee переподключается если ей после остановки канала ничего не послать, а Genius нет, просто молчит.
Добавлено after 22 minutes 59 seconds:
Простите я наврал, кнопки прилетают.
Добавлено after 6 minutes 57 seconds:
К стати давно хотел спросить, какая разница между периодическими и непериодическими запросами?
Добавлено after 9 minutes 41 second:
Единственное отличие в работе мышек, в том что Zornwee переподключается если ей после остановки канала ничего не послать, а Genius нет, просто молчит.
Добавлено after 22 minutes 59 seconds:
Простите я наврал, кнопки прилетают.
Re: stm32 USB host
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4658459#p4658459"]Ну да. Не считая наркоманский EPnR, у которых часть битов read-only, часть read-write, часть можно только стереть, причем нулем, а часть инвертировать, причем единицей.[/uquote]Если все биты описаны в мануале, то нормально.
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4658459#p4658459"]А что за проблема с изохронными точками? У меня аудио-девайс (микрофон + динамик) вполне запустился.[/uquote]Значит у вас размер точек был маленький.
Проблема в том, что размер USB-памяти сильно ограничен. А так как в этой памяти нужно разместить дескрипторы всех точек, а также разместить память для ep0 и по 2 буфера под каждую изохронную точку, то получается, что максимальный размер изохронной точки может быть немного больше 230 байт (если всего одна точка активна).
Для USB-FS размер изохронных точек может быть - до 1023 байт. А значит - и максимальная скорость изохронной передачи ограничена - менее 1/4 от максимально возможной для USB-FS.
Получается - STM32L не соответствует даже требованиям USB-FS. Или не полностью соответствует.
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4658459#p4658459"]А что за проблема с изохронными точками? У меня аудио-девайс (микрофон + динамик) вполне запустился.[/uquote]Значит у вас размер точек был маленький.
Проблема в том, что размер USB-памяти сильно ограничен. А так как в этой памяти нужно разместить дескрипторы всех точек, а также разместить память для ep0 и по 2 буфера под каждую изохронную точку, то получается, что максимальный размер изохронной точки может быть немного больше 230 байт (если всего одна точка активна).
Для USB-FS размер изохронных точек может быть - до 1023 байт. А значит - и максимальная скорость изохронной передачи ограничена - менее 1/4 от максимально возможной для USB-FS.
Получается - STM32L не соответствует даже требованиям USB-FS. Или не полностью соответствует.