Autor Tema: Assembler en ARM - Probando  (Leído 19865 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Carl47D

  • PIC16
  • ***
  • Mensajes: 160
Re:Assembler en ARM - Probando
« Respuesta #45 en: 13 de Octubre de 2015, 21:01:02 »
Ustedes ya fueron y regresaron 3 veces, yo apenas voy.
Gracias a la info de Leonardo sobre el DWT pude testear la funcion de delay en un M3 y me cuenta los 16 ciclos esperados, para los que usen psoc5lp acá dejo el código:

Código: C
  1. #include <project.h>
  2.  
  3. extern void retardo(uint16_t us);
  4.  
  5. int main(){
  6.     CyGlobalIntEnable;
  7.    
  8.     (*(reg32*)CYREG_CORE_DBG_EXC_MON_CTL) |= CoreDebug_DEMCR_VC_CHKERR_Msk; /* CoreDebug_DEMCR_VC_CHKERR_Msk = 0x1000000 */
  9.     (*(reg32*)CYREG_DWT_CTRL) |= DWT_CTRL_CYCCNTENA_Msk; /* DWT_CTRL_CYCCNTENA_Msk = 0x1 */
  10.     (*(reg32*)CYREG_DWT_CYCLE_COUNT) = 0;
  11.     retardo(1);
  12.  
  13.     for(;;){
  14.        
  15.     }
  16. }
  17.  
  18. /* [] END OF FILE */

Y la subrutina:
Código: ASM
  1. .syntax unified
  2.     .text
  3.     .global retardo
  4.     .func retardo, retardo
  5.     .thumb_func
  6. retardo:
  7.     SUBS    r0, #1
  8.     NOP
  9.     NOP
  10.     NOP
  11.     NOP
  12.     NOP
  13.     NOP
  14.     NOP
  15.     NOP
  16.     NOP
  17.     NOP
  18.     NOP
  19.     BNE.N   retardo
  20.     BX      lr
  21.     .endfunc
  22.  
  23.     .end
  24.  
  25. /* [] END OF FILE */

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Assembler en ARM - Probando
« Respuesta #46 en: 14 de Octubre de 2015, 00:12:09 »
Citar
Gracias a la info de Leonardo sobre el DWT pude testear la funcion de delay en un M3 y me cuenta los 16 ciclos esperados, para los que usen psoc5lp acá dejo el código:

Probalo con 2 y vas a tener 33 o 34, cada 1 mas que agregues le va a sumar 1 ciclo :P
Imagino, solo resta probar, xD hace varias instrucciones/funciones de una sola ves. Asi no grabas 100 veces el micro :P

EDIT: Habria que ver cuanto tarda el salir y entrar a la funcion.
De realizarse el salto podrias hacer:
Código: ASM
  1. retardo:
  2.     NOP
  3. 1: SUBS    r0, #1
  4.     NOP
  5.     NOP
  6.     NOP
  7.     NOP
  8.     NOP
  9.     NOP
  10.     NOP
  11.     NOP
  12.     NOP
  13.     NOP
  14.     BNE.N   1b
  15.     BX      lr

Asi, si se produce el salto, se realiza un NOP menos, al menos el bucle ahora tendria la misma cantidad de instrucciones si es que entra o no dentro del salto.

Ahora tenes que el bucle es fijo. Pero las instrucciones de entrada y salida son fijos. asi que seria

instrucciones de entrada,salida + N * bucle

Con lo cual seguro que no es un multiplo exacto de 16 xD, Para 1 si, pero para los demas no :/
« Última modificación: 14 de Octubre de 2015, 04:35:27 por KILLERJC »

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Assembler en ARM - Probando
« Respuesta #47 en: 14 de Octubre de 2015, 09:10:49 »
Lo que me parece raro son esos 37 ciclos. son demasiados.

Hay 6 instrucciones, de 32bits, no se si tomarlas como 12 ciclos o 6,
Supongamos 12, que luego por el pipeline se introduzca algunas bubbles por necesidad de los datos. eso lo aumentaria a cerca de 3 ciclos mas.
Sigiuiendo tenes el CALL y RETURN ( BL y BX ) eso va a depender exactamente del PC a donde se dirija, si es un salto a registro y no un literal, tomaria 3 ciclos, si es un literal 2 ciclos, si es un salto el cual no esta alineado a 32 bits tomaria 4 ciclos. entonces supongamos:
12 + 3 + 4 = 17 maximo.. incluso haciendo el doble en las instrucciones el cual NO deberia.

Ahí probé. El tema es donde pongo el break point.
Código: C
  1. *DWT_CYCCNT = 0;
  2.         invertido = Invertir(MC);
  3.         count = *DWT_CYCCNT;
Si lo pongo en Invertido=Invertir.... y hago el paso a paso, le lleva 5 ciclos para entrar a la funcion, luego 6 ciclos por las 6 instrucciones y 5 más para volver. Total 16 ciclos.
Pero si pongo el break en count=.... entonces me cuenta 37 ciclos...

Luego hice esto:

Código: C
  1. *DWT_CYCCNT = 0;
  2.         invertido = Invertir(MC);
  3.         count = *DWT_CYCCNT;
  4.  
  5.         *DWT_CYCCNT = 0;
  6.         invertido = Invertir(MC);
  7.         count = *DWT_CYCCNT;
  8.  
  9.         *DWT_CYCCNT = 0;
  10.         invertido = Invertir(MC);
  11.         count = *DWT_CYCCNT;

y puse break point en cada count=... El primero me arroja 37, el segundo 19 y el tercero 19. (siempre antes de ejecutar la instruccion count=*DWT....) El resultado lo veo en el visor de variables de Eclipse...

Saludos!
-
Leonardo Garberoglio

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Assembler en ARM - Probando
« Respuesta #48 en: 14 de Octubre de 2015, 09:15:58 »
Código: ASM
  1. Invertir:
  2.         RBIT    R2, R1                  ;@ R2 = Inv(R1)
  3.         RBIT    R3, R0                  ;@ R0 = Inv(R0)
  4.         LSRS    R2, R2, #16             ;@ R2:    00  : R0f[15:0]
  5.         PKHTB   R1, R1, R3, ASR #16     ;@ R1f[31:16]:R1f[15:0] = R1[31:16]:R3[31:16] = R1
  6.         PKHBT   R0, R2, R3, LSL #16     ;@ R0f[31:16]:R0f[15:0] = R3[15:0]:R2[15:0] = R0  (Aca R2 esta luego del Shift, sino hubiera sido [31:16])
  7.         .end

Una sola instruccion menos .... :/, crei que lo podia hacer con 4 pero no pude...
y 3 bytes menos en memoria de programa, por que el LSRS ocupa 16 bytes

Falta el BX      lr al final.

15 hermosos ciclos, jeje. Funciona de 10!!!
-
Leonardo Garberoglio

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Assembler en ARM - Probando
« Respuesta #49 en: 14 de Octubre de 2015, 14:51:29 »
Me olvide del BX :P

Y lo feo es que usas el salto... si no fuera por el salto invertir los bits no seria nada que ocupe tiempo ( 5 ciclos ) el tema es como agregar esto a C sin salto xD. ademas que justo los datos esten en R0/R1.
Se podria intentar un codigo en C que haga lo mismo y comprarar el ASM generado, si es que vale la pena. pero no veo nada que haga una inversion de bits en C :/

O directamente construir lo que pasa del primer buffer al de video en ASM, que es donde se usaria la inversion. Lo feo que esto es solamente valido para un M3/M4

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Assembler en ARM - Probando
« Respuesta #50 en: 14 de Octubre de 2015, 15:24:26 »
No creo que en C se pueda hacer nada similar:

http://stackoverflow.com/questions/746171/best-algorithm-for-bit-reversal-from-msb-lsb-to-lsb-msb-in-c
https://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious

acá hay una integracion interesante de C y ASM:

http://stackoverflow.com/questions/20436466/lsb-to-msb-bit-reversal-on-arm ver la última respuesta.

Si, eso estaría bueno, hacer la rutina de conversion del buffer de video al buffer de salida en ASM aprovechando las instrucciones de manipulacion de bits/bytes/...

L oque tengo que definir es con qué micro voy a trabajar... Porque los candidatos son el stm32f411 (M4F) muy sobrado, pero es con lo que estoy trabajando en este momento (despues les cuento un error en las librerías HAL que me tuvieron 2 días renegando con el SPI  :5] en otro proyecto) o con el LPC11u67 (M0+) el cual es más acorde. Estimo que voy a volver para este proyecto a NXP...

saludos!
-
Leonardo Garberoglio

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Assembler en ARM - Probando
« Respuesta #51 en: 14 de Octubre de 2015, 16:08:16 »
El M0 no tiene RBIT :P
Es mas no tiene ninguna instruccion para invertir los bits xD, asi que a mano xD

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2980
Re:Assembler en ARM - Probando
« Respuesta #52 en: 14 de Octubre de 2015, 16:23:53 »
Citar
(despues les cuento un error en las librerías HAL que me tuvieron 2 días renegando con el SPI  :5] en otro proyecto)

MUERTE A ST!!!!!  :D :D :D otro que no quiero ni regalado como PIC32 :D :D

yo sigo pensando que la idea de una matriz de 3 dimensiones es buena, es lo que se utiliza para definir toda la gama de colores.


un saludo

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Assembler en ARM - Probando
« Respuesta #53 en: 15 de Octubre de 2015, 09:48:09 »
MUERTE A ST!!!!!  :D :D :D otro que no quiero ni regalado como PIC32 :D :D

Si, muerte a ST!!!! pero lamentablemente soy víctima de sus super bajos precios y tengo un monton de placas de evaluacion  :?
Les comento rapido, estoy comunicando un f411 con un ads1299 (un front end de TI para EEG) por el SPI. Es una comunicacion donde el micro manda comandos y el ads responde con datos, registros etc. El tema es que st tiene 3 funciones SPI_Transmit, SPI_Receive y SPI_TransmitReceive. Cuando quiero enviar un comando uso SPI_Transmit y todo de 10. Pero cuando quería recivir los datos del ADS ponía SPI_Receive y la cosa andaba de a ratos. Fallos aleatorios. Por ahí andaba bien unas lecturas y luego no andaba más (andar significa que el ADS me ponga la señal DRY a 0 cada x mseg para que yo pida los datos)... En fin, con un oscilloscopio de 4 canales veía CLK, DRDY, CS y MOSI cuando transmitía y MISO cuando recivía... en un momento, cuando ya no podía probar más nada por software (el transmit andaba bien, ya que podia configurar los registros sin problemas y leer 1 solo dato tmb andaba bien) decidí ver CLK, DRDY, MOSI y MISO a la vez. Cuando DRDY se iba a 0 veía que en MISO tenía datos llegando desde el ADS, pero había datos tambien saliendo por el MOSI del micro!! WTF!
Me voy como un rayo  a la implementacion del SPI_Receive y me encuentro que para poder recivir llaman a SPI_Transmit_Receive (evidentemente para que se generen los pulsos de clk tienen que hacer uso de la transmision. Pero bueno eso no sería nada, el proble es que los hijos de mil en vez de transmitir 0's transmiten datos!!!!!

Código: C
  1. /**
  2.   * @brief  Receive an amount of data in blocking mode
  3.   * @param  hspi: pointer to a SPI_HandleTypeDef structure that contains
  4.   *                the configuration information for SPI module.
  5.   * @param  pData: pointer to data buffer
  6.   * @param  Size: amount of data to be sent
  7.   * @param  Timeout: Timeout duration
  8.   * @retval HAL status
  9.   */
  10. HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
  11. ....
  12. ....
  13. ....
  14.     if((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES))
  15.     {
  16.       /* Process Unlocked */
  17.       __HAL_UNLOCK(hspi);
  18.  
  19.       /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
  20.       return HAL_SPI_TransmitReceive(hspi, [color=red]pData[/color], pData, Size, Timeout);
  21.     }

En la hoja de datos del ADS pide que la linea DIN este en cero cuando el ADS está enviando datos.... Mi pregunta es, porque no mandan 0's!!!! y te aseguras que no vas a interferir con algunos integrados como estos?

saludos
-
Leonardo Garberoglio

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2980
Re:Assembler en ARM - Probando
« Respuesta #54 en: 15 de Octubre de 2015, 10:19:49 »
Mandan datos?? Y eso para que?
Si al final no te puedes fiar ni de las librerías de los fabricantes, muchas veces son una pesadilla mas que una ayuda. :?
Cada vez que veo una librería de comunicación esperando datos con while, como pasa en microchip se me revuelve el estomago.
Vete a saber si no mandan datos por algún fallo del silicio y han intentado que funcione de esa manera.
Un saludo

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Assembler en ARM - Probando
« Respuesta #55 en: 16 de Octubre de 2015, 07:33:04 »
En el TIVAWare (TI ), posee tambien unos cuantos comandos para el tema del SPI. al principio me resulto un poco complejo entenderlo xD por que uno estaria acostumbrado a eso, como se manejan las HAL, a enviar y recibir, Lo que yo veo que ahi en las HAL de ST estan usando los mismos datos del buffer que estas usando para recibir.

Para juanjo que le gusta tanto los while

Código: C
  1. void
  2. SSIDataPut(uint32_t ui32Base, uint32_t ui32Data)
  3. {
  4.     //
  5.     // Check the arguments.
  6.     //
  7.     ASSERT(_SSIBaseValid(ui32Base));
  8.     ASSERT((ui32Data & (0xfffffffe << (HWREG(ui32Base + SSI_O_CR0) &
  9.                                        SSI_CR0_DSS_M))) == 0);
  10.  
  11.     //
  12.     // Wait until there is space.
  13.     //
  14.     while(!(HWREG(ui32Base + SSI_O_SR) & SSI_SR_TNF))
  15.     {
  16.     }
  17.  
  18.     //
  19.     // Write the data to the SSI.
  20.     //
  21.     HWREG(ui32Base + SSI_O_DR) = ui32Data;
  22. }

No te enojes juanjo, tambien hay funciones que no son bloqueantes :P y hacen lo mismo
Lo que si, no hay una funcion de "Enviar" y "Recibir" el DataPut sirve para enviar en su forma bloqueante o no. El DataGet simplemente lee la FIFO nada mas, asi que si tu idea es leer sos vos el que mandas un 0. Y no se asume que debes enviar un 0 o lo que sea. Como que un poco costo entender esto en mi cabeza, uno espera que poner un DataGet y recibiste.

Código: C
  1. SSIDataPut(SSI_BASE,Data);
  2.         SSIDataPut(SSI_BASE,0x00);
  3.         SSIAdvDataPutFrameEnd(SSI2_BASE, 0x00);  //Esto es genial puedo controlar el CS/FSS a mi gusto!
  4.         SSIDataGet(SSI_BASE,&valor[0]); //dummy read para el primer write (generado por el "data"
  5.         SSIDataGet(SSI_BASE,&valor[0]);
  6.         SSIDataGet(SSI_BASE,&valor[1]);

Con lo cual cuando hice el driver para el Touch quedo asi. Tenia que enviar el dato, y luego recibir 16bits sin que el CS subiera, desde que escribia hasta que leia. Si ven ahi Envio los datos + 2 bytes con 0x00 a la FIFO , y luego debo leerlos.

Hay una parte fea que es la de tener que leer los datos cuando uno escribe, y que por ahi no te sirven ( especialmente en el primer dato, como se ve ) Pero eso imagino que te da la mayor flexibilidad para hacer lo que sea. Hasta ahora no tuve problemas con las librerias de TI, son todas muy basicas, funciones super simples que cargan valores a los registros directamente, incluso tienen un Macro ( HW_REG ) para acceder a la direccion que apuntan. Creo que es lo mejor poder verlo asi.

Desconectado juaperser1

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 2980
Re:Assembler en ARM - Probando
« Respuesta #56 en: 16 de Octubre de 2015, 12:21:07 »
Citar
No te enojes juanjo, tambien hay funciones que no son bloqueantes :P y hacen lo mismo
Lo que si, no hay una funcion de "Enviar" y "Recibir" el DataPut sirve para enviar en su forma bloqueante o no. 

Se que hay funciones con while bien escritas, pero te invito a que le heches un vistazo a las de i2c para pic32 :D y te reto a que intentes quitarle el while, lo dejes por pulling y que funcione en un pic32mx de la serie 2.

 :D :D


Desconectado Carl47D

  • PIC16
  • ***
  • Mensajes: 160
Re:Assembler en ARM - Probando
« Respuesta #57 en: 24 de Octubre de 2015, 17:39:00 »
Que tal,
vengo con otro error n00b, estaba tratando de correr unas instrucciones simples en el cortex-m0 que tengo, la funcion es re simple, esta en formato UAL.

Código: ASM
  1. .syntax unified
  2.     .text
  3.     .global rotate
  4.     .func rotate, rotate
  5.     .thumb_func
  6. rotate:
  7.     RORS r0, r0, #3
  8.     BX lr
  9.     .endfunc
  10.  
  11.     .end
  12.  
  13. /* [] END OF FILE */

ni siquiera la puedo compilar, me tira este error:
Citar
Build error: cannot honor width suffix -- `rors r0,r0,#3'

Buscando en internet solo encontre esto:
arm-assembly-cannot-use-immediate-values-and-adds-adcs-together

Cambie el RORS por un MOV r1, #3 y nada, ni eso compila xD
Alguna idea de porque me marca dicho error?

Desconectado Carl47D

  • PIC16
  • ***
  • Mensajes: 160
Re:Assembler en ARM - Probando
« Respuesta #58 en: 24 de Octubre de 2015, 20:54:24 »
Ya está, el problema era yo que no se leer  :mrgreen:, RORS no acepta valores inmediatos como operando, tenia que guardar el número en un registro y usar ese registro después, asi termino la función (no es nada util, solo rota el byte en r0 2 posiciones en este caso):

Código: ASM
  1. .syntax unified
  2.     .text
  3.     .func rotate, rotate
  4.     .thumb_func
  5.     .global rotate
  6. rotate:
  7.     MOVS r4, #2
  8.     RORS r0, r0, r4
  9.     BX lr
  10.     .endfunc
  11.  
  12.     .end
  13.  
  14. /* [] END OF FILE */

La llamada desde el main en c:
Código: C
  1. extern void rotate(uint8_t r);
  2.  
  3. int main(){    
  4.    
  5.     rotate(0x08);
  6.    
  7.     for(;;){
  8.     }
« Última modificación: 24 de Octubre de 2015, 21:05:36 por Carl47D »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Assembler en ARM - Probando
« Respuesta #59 en: 24 de Octubre de 2015, 21:27:43 »
es jodido no tener Thumb-2... Como en ese caso, yo llegue tarde para la respuesta xD.