|
|
  |
STM32 >> STR R1, [R0] >> сохраняется не корректно |
|
|
|
Jul 20 2012, 03:15
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Буэнос утрас, амигас!  STM32F103RC + IAR 6.30 + J-LINK Использую SPI1, через пины PB3, PB4 и PB5. Основная функция PB3, это JTDO. А основная функция PB4, это NJTRST. Обе мне не нужны, поскольку работаю через Serial Wire. Что бы вывести на эти ноги сигналы SPI1, конфигурирую их как альтернативные и делаю remap: Код McuPinInit( BSP_PIN_ISM_CSn, MCU_PIN_MODE_OUT_GP_PP_10MHZ ); McuPinInit( BSP_PIN_ISM_SCK, MCU_PIN_MODE_OUT_AF_PP_10MHZ ); McuPinInit( BSP_PIN_ISM_SI, MCU_PIN_MODE_OUT_AF_PP_10MHZ ); McuPinInit( BSP_PIN_ISM_SO, MCU_PIN_MODE_OUT_AF_PP_10MHZ ); McuPinInit( BSP_PIN_ISM_GDO2, MCU_PIN_MODE_INP_FLOATING ); McuPinInit( BSP_PIN_ISM_GDO0, MCU_PIN_MODE_INP_FLOATING );
McuPioRemap( MCU_PIO_REMAP_SPI1_ENABLE ); //McuPioRemap( MCU_PIO_REMAP_SWJ_CFG_JTAG_DIS_SW_EN ); McuPioRemap( MCU_PIO_REMAP_SWJ_CFG_FULL_WITHOUT_NJTRST ); По конфигурации проблем нет, клок на GPIOx и AFIO включается в McuPinInit(). А вот с remap творится чертовщина. Ниже текст текущего варианта McuPioRemap(). Лишнее покоцал, но суть и так понятна: CODE typedef enum MCU_PIO_REMAP_e { MCU_PIO_REMAP_SWJ_CFG_FULL, MCU_PIO_REMAP_SWJ_CFG_FULL_WITHOUT_NJTRST, MCU_PIO_REMAP_SWJ_CFG_JTAG_DIS_SW_EN, MCU_PIO_REMAP_SWJ_CFG_JTAG_DIS_SW_DIS, ... MCU_PIO_REMAP_I2C1_DISABLE, MCU_PIO_REMAP_I2C1_ENABLE, MCU_PIO_REMAP_SPI1_DISABLE, MCU_PIO_REMAP_SPI1_ENABLE } MCU_PIO_REMAP;
//////////////////////////////////////////////////////////////////////////////// void McuPioRemap( MCU_PIO_REMAP Remap ) { switch( Remap ) { case MCU_PIO_REMAP_SWJ_CFG_FULL: AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_0; AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_1; AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_2; break;
case MCU_PIO_REMAP_SWJ_CFG_FULL_WITHOUT_NJTRST: AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_0; AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_1; AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_2; break;
case MCU_PIO_REMAP_SWJ_CFG_JTAG_DIS_SW_EN: AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_0; AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_1; AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_2; break;
case MCU_PIO_REMAP_SWJ_CFG_JTAG_DIS_SW_DIS: AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_0; AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_1; AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_2; break;
...
case MCU_PIO_REMAP_I2C1_DISABLE: AFIO->MAPR &= ~AFIO_MAPR_I2C1_REMAP; break;
case MCU_PIO_REMAP_I2C1_ENABLE: AFIO->MAPR |= AFIO_MAPR_I2C1_REMAP; break;
case MCU_PIO_REMAP_SPI1_DISABLE: AFIO->MAPR &= ~AFIO_MAPR_SPI1_REMAP; break;
case MCU_PIO_REMAP_SPI1_ENABLE: AFIO->MAPR |= AFIO_MAPR_SPI1_REMAP; break;
default: break; } } Сначала у меня перестал откликаться SW, пришлось временно закомментить remap. Подумал, что либо сам ошибся, либо в <stm32f10x.h> косячёк в #define. Полез смотреть по шагам. Вижу вполне корректный ассемблер: Код AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_0; ??McuPioRemap_4: 0x8000d40: 0xf8df 0x03f8 LDR.W R0, ??DataTable4_6; AFIO_MAPR 0x8000d44: 0x6801 LDR R1, [R0] 0x8000d46: 0xf041 0x7180 ORR.W R1, R1, #16777216; 0x1000000 0x8000d4a: 0x6001 STR R1, [R0] AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_1; 0x8000d4c: 0x6801 LDR R1, [R0] 0x8000d4e: 0xf021 0x7100 BIC.W R1, R1, #33554432; 0x2000000 0x8000d52: 0x6001 STR R1, [R0] AFIO->MAPR &= ~AFIO_MAPR_SWJ_CFG_2; 0x8000d54: 0x6801 LDR R1, [R0] 0x8000d56: 0xf021 0x6180 BIC.W R1, R1, #67108864; 0x4000000 0x8000d5a: 0xe127 B.N ??McuPioRemap_3; 0x8000fac
...
??McuPioRemap_3: 0x8000fac: 0x6001 STR R1, [R0] } Когда дохожу до строки 0x8000d4a: 0x6001 STR R1, [R0]в регистрах вижу корректные значения, в R1 значение 0x01000001, а в R0 адрес AFIO->MAPR ( 0x40010004 ). Сразу после исполнения STR R1, [R0] в AFIO->MAPR вижу уже 0x02000001, вместо 0x01000001. Ну и на следующей инструкции, конечно, считывается как 0x02000001. Ну как-же так, доктор? Причем каждый из трех бит SWJ_CFG так же аккуратно сдвигается на единицу влево. А вот младшая 1, это remap SPI1, который был сделан ранее, причем этой же функцией. И ведь все корректно!
P.S. В еррате ничего похожего не нашел.
Сообщение отредактировал IgorKossak - Jul 20 2012, 07:11
Причина редактирования: [codebox] для длинного кода!!!
|
|
|
|
|
Jul 20 2012, 06:23
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Пара дополнений. 1. Согласно даташит, значения из SWJ_CFG не считываются корректно: Цитата Bits 26:24 SWJ_CFG[2:0]: Serial wire JTAG configuration These bits are write-only (when read, the value is undefined). They are used to configure the SWJ and trace alternate function I/Os. The SWJ (Serial Wire JTAG) supports JTAG or SWD access to the Cortex debug port. The default state after reset is SWJ ON without trace. This allows JTAG or SW mode to be enabled by sending a specific sequence on the JTMS / JTCK pin.
000: Full SWJ (JTAG-DP + SW-DP): Reset State 001: Full SWJ (JTAG-DP + SW-DP) but without NJTRST 010: JTAG-DP Disabled and SW-DP Enabled 100: JTAG-DP Disabled and SW-DP Disabled Other combinations: no effect Но я сужу об их поведении по внешнему проявлению - у меня при записи комбинации бит 010 сразу отключается SW и, как следствие, отваливается отладчик. Т.е. ведет себя так, как если бы была записана комбинация 100. 2. Если поменять местами вызовы функций, т.е. сделать вот так: McuPioRemap( MCU_PIO_REMAP_SWJ_CFG_FULL_WITHOUT_NJTRST ); McuPioRemap( MCU_PIO_REMAP_SPI1_ENABLE );то все чудесным образом начинает работать. И SPI пероиферию инициализирует, и отладчик не отваливается...
|
|
|
|
|
Jul 20 2012, 07:18
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(scifi @ Jul 20 2012, 10:55)  Вы уже сами написали, что работа с AFIO_MAPR у вас ведётся некорректно. Какой смысл разбираться дальше? Делайте как положено: AFIO_MAPR = (AFIO_MAPR & 0xF8FFFFFF) | new_val. Угу. Хотя это не лучший выход. Правда маска в стандартной библиотеке 0xF0FFFFFF, а не 0xF8FFFFFF, как в доке. Думаю, что не случайно, особенно в свете поведения AFIO_MAPR при записи ( я про сдвиг на один бит влево в группе SWJ_CFG ). Цитата(scifi @ Jul 20 2012, 11:12)  Только не берите пример с этой библиотеки. Качество кода там оставляет желать лучшего, мягко говоря. Первоисточник - это Reference Manual. Конечно. Потому и приходится, к сожалению, изобретать велосипед - писать своё. По мере надобности дописываю нужные куски.
|
|
|
|
|
Jul 20 2012, 07:43
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(scifi @ Jul 20 2012, 11:22)  Первоисточник - Reference Manual, остальное - от лукавого. В целом - да. Но в данном случае, судя по всему, не корректен имено Reference Manual. Вот это: Цитата 000: Full SWJ (JTAG-DP + SW-DP): Reset State не соотвествует действительности. Как я писал ранее: Цитата 2. Если поменять местами вызовы функций, т.е. сделать вот так: McuPioRemap( MCU_PIO_REMAP_SWJ_CFG_FULL_WITHOUT_NJTRST ); McuPioRemap( MCU_PIO_REMAP_SPI1_ENABLE ); то все чудесным образом начинает работать. И SPI пероиферию инициализирует, и отладчик не отваливается... Т.е. сначала я отключаю JTAG, а потом ( если верить мануалу ), записывая 0x00000001, тем самым записываю и 000 в SWJ_CFG. А стало быть, снова включаю JTAG, то бишь отключаю SPI1. Однако ж SPI1 остается "живее всех живых"(с), потому что продлолжает спокойно работать с периферией. И еще, насчет мануала. Ничего не имею против поведения NSS в SPI, как его организовали ST. Сначала огорчился, но потом пришел к выводу, что ничего фатального в этом нет: для single операций скорость все равно не критична, а для DMA, как правило, все равно приходится использовать прерывание об окончании трансфера, так что одно обращение к пину в нем особо погоды не делает. Но мало того, что они криво описали поведение NSS ( написанное в мануале расходилось с реальным поведенпием пина ), так ещё и не хотели сознаваться, что у них свой, особенный взгляд на NSS в SPI.
|
|
|
|
|
Jul 20 2012, 07:47
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Tahoe @ Jul 20 2012, 11:43)  не соотвествует действительности. Не верю. Цитата(Tahoe @ Jul 20 2012, 11:43)  Т.е. сначала я отключаю JTAG, а потом ( если верить мануалу ), записывая 0x00000001, тем самым записываю и 000 в SWJ_CFG. Это вы так думаете. В связи с тем, что работа с регистром у вас сделана некорректно, на самом деле может происходить что-то совсем иное. Дальше разбираться лень, да и пользы от этого не будет.
|
|
|
|
|
Jul 20 2012, 08:28
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(scifi @ Jul 20 2012, 11:47)  В связи с тем, что работа с регистром у вас сделана некорректно Да что ж тут может быть не корректного?  По сути, речь про одну строчку: Код AFIO->MAPR = 0x00000001; CODE //////////////////////////////////////////////////////////////////////////////// void McuPioRemap( MCU_PIO_REMAP Remap ) { uint32_t Temp = AFIO->MAPR & 0xF0FFFFFF;
switch( Remap ) { case MCU_PIO_REMAP_SWJ_CFG_FULL: Temp &= ~AFIO_MAPR_SWJ_CFG; break;
case MCU_PIO_REMAP_SWJ_CFG_FULL_WITHOUT_NJTRST: Temp &= ~AFIO_MAPR_SWJ_CFG; Temp |= AFIO_MAPR_SWJ_CFG_0; break;
case MCU_PIO_REMAP_SWJ_CFG_JTAG_DIS_SW_EN: Temp &= ~AFIO_MAPR_SWJ_CFG; Temp |= AFIO_MAPR_SWJ_CFG_1; break;
case MCU_PIO_REMAP_SWJ_CFG_JTAG_DIS_SW_DIS: Temp &= ~AFIO_MAPR_SWJ_CFG; Temp |= AFIO_MAPR_SWJ_CFG_2; break; ...
case MCU_PIO_REMAP_I2C1_DISABLE: Temp &= ~AFIO_MAPR_I2C1_REMAP; break;
case MCU_PIO_REMAP_I2C1_ENABLE: Temp |= AFIO_MAPR_I2C1_REMAP; break;
case MCU_PIO_REMAP_SPI1_DISABLE: Temp &= ~AFIO_MAPR_SPI1_REMAP; break;
case MCU_PIO_REMAP_SPI1_ENABLE: Temp |= AFIO_MAPR_SPI1_REMAP; break;
default: break; }
AFIO->MAPR = Temp; } Хотя неоднозначность заложена в самом мануале. Он должен описать поведение PB3, PB4, которые используются и JTAG, и SPI. При этом значение 0x00000001 для MAPR допустимо. Оно одновременно должно включать как SPI1 remap, так и JTAG-DP. Учитывая, что в том же мануале, основная функция PB3 это как раз JTDO, да и приоритеты явно не указаны, логично ожидать, что PB3 не будет функционировать как SPI1_SCK, а будет исполнять свою основную функцию JTDO. Ладно, забудем.  Сейчас проверил окончательный вариант. Пока не передернул питание, состояние SWJ_CFG не менялось. А вот когда питание передернул, доступ к периферии уже отсутствовал. В общем вывод остается прежним - remap JTAG делать в самую последнюю очередь. А в библиотеках от ST просто в наглую подставляется константа. И совсем не факт, что она совпадет с тем, как ранее настроил программер.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|