{"id":728,"date":"2015-12-29T19:59:19","date_gmt":"2015-12-29T18:59:19","guid":{"rendered":"https:\/\/www.livediesel.de\/?p=728"},"modified":"2015-12-30T22:08:23","modified_gmt":"2015-12-30T21:08:23","slug":"increase-msp432-spi-performance-part-2","status":"publish","type":"post","link":"https:\/\/www.livediesel.de\/?p=728","title":{"rendered":"Increase MSP432\u2122 SPI Performance \u2013 Part 2"},"content":{"rendered":"<p>Ok, here it is, the Fill function written in assembler.<br \/>\nDue some caching of hardware register addresses in the Core registers, I was able to reduce the following code from 8+ steps to 4.<\/p>\n<pre lang=\"c\">\r\nUCB2TXBUF = data;\r\nwhile (UCB2STATW & UCBUSY);\r\n<\/pre>\n<p>The following assembler source is the first full standalone assembler code I wrote. Don&#8217;t be mad at me!<\/p>\n<pre lang=\"arm\">\r\nILICTL_POUT   .word 0x40004C42 ; P5OUT\r\nILIUCI_TXBUF  .word 0x4000280E ; UCB2TXBUF\r\nILIUCI_STATW  .word 0x40002808 ; UCB2STATW\r\nILI9341_RAMWR .set 0x2c\r\nILICTL_DCX    .set 0x0004\r\nUCBUSY        .set 0x0001\r\n\r\n;############################################################################################\r\n; extern void ILI9341_FillASM(uint16_t color, uint32_t count32);\r\n    .global ILI9341_FillASM\r\nILI9341_FillASM: .asmfunc\r\n\r\nColor   .set r0 ; r0 = Color ; Param 0\r\nCount   .set r1 ; r1 = Count ; Param 1\r\nTXBUF   .set r2 ; r2 = ILIUCI_TXBUF\r\nSTATW   .set r3 ; r3 = ILIUCI_STATW\r\nPOUT    .set r4 ; r4 = ILICTL_POUT\r\nColorH  .set r5 ; r5 = Color >> 8\r\nSlow    .set r6 ; r6 = Count & 0x0007\r\nBuffer  .set r7\r\n\r\n    push {r4-r7}\r\n\r\n; cache hardware register addresses\r\n    ldr TXBUF, ILIUCI_TXBUF\r\n    ldr STATW, ILIUCI_STATW\r\n    ldr POUT, ILICTL_POUT\r\n\r\n; ILI_COMMAND\r\n    ldrb Buffer, [POUT]\r\n    bic Buffer, Buffer, #ILICTL_DCX\r\n    strb Buffer, [POUT]\r\n\r\n; transmit ramwr byte\r\n    mov Buffer, #ILI9341_RAMWR\r\n    strb Buffer, [TXBUF]\r\n\r\nRAMWR_Busy_L: ; wait until transmit\r\n        ldrb Buffer, [STATW]\r\n        tst Buffer, #UCBUSY\r\n        bne RAMWR_Busy_L\r\n\r\n; ILI_DATA\r\n    ldrb Buffer, [POUT]\r\n    orr Buffer, Buffer, #ILICTL_DCX\r\n    strb Buffer, [POUT]\r\n\r\n    lsr ColorH, Color, #8 ; Color >> 8\r\n    ands Slow, Count, #0x0007 ; Test if lower bits of count is set\r\n    beq Fast\r\n\r\nSlow_L: ; Slow data loop\r\n        strb ColorH, [TXBUF] ; Color H\r\nSlow_Busy_L0: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Slow_Busy_L0\r\n        strb Color, [TXBUF] ; Color L\r\nSlow_Busy_L1: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Slow_Busy_L1\r\n        subs Slow, Slow, #1\r\n        bne Slow_L ; continue while slow data\r\n\r\nFast: ; Fast data\r\n    lsrs Count, Count, #3 ; count >> 3\r\n    beq End ; if count = 0, goto end\r\n\r\nFast_L: ; fast data loop\r\n        ; ----------------- Data 0 -----------------\r\n        strb ColorH, [TXBUF] ; Color H\r\nFast_Busy_L0: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L0\r\n        strb Color, [TXBUF] ; Color L\r\nFast_Busy_L1: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L1\r\n\r\n        ; ----------------- Data 1 -----------------\r\n        strb ColorH, [TXBUF] ; Color H\r\nFast_Busy_L2: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L2\r\n        strb Color, [TXBUF] ; Color L\r\nFast_Busy_L3: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L3\r\n\r\n        ; ----------------- Data 2 -----------------\r\n        strb ColorH, [TXBUF] ; Color H\r\nFast_Busy_L4: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L4\r\n        strb Color, [TXBUF] ; Color L\r\nFast_Busy_L5: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L5\r\n\r\n        ; ----------------- Data 3 -----------------\r\n        strb ColorH, [TXBUF] ; Color H\r\nFast_Busy_L6: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L6\r\n        strb Color, [TXBUF] ; Color L\r\nFast_Busy_L7: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L7\r\n\r\n        ; ----------------- Data 4 -----------------\r\n        strb ColorH, [TXBUF] ; Color H\r\nFast_Busy_L8: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L8\r\n        strb Color, [TXBUF] ; Color L\r\nFast_Busy_L9: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L9\r\n\r\n        ; ----------------- Data 5 -----------------\r\n        strb ColorH, [TXBUF] ; Color H\r\nFast_Busy_L10: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L10\r\n        strb Color, [TXBUF] ; Color L\r\nFast_Busy_L11: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L11\r\n\r\n        ; ----------------- Data 6 -----------------\r\n        strb ColorH, [TXBUF] ; Color H\r\nFast_Busy_L12: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L12\r\n        strb Color, [TXBUF] ; Color L\r\nFast_Busy_L13: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L13\r\n\r\n        ; ----------------- Data 7 -----------------\r\n        strb ColorH, [TXBUF] ; Color H\r\nFast_Busy_L14: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L14\r\n        strb Color, [TXBUF] ; Color L\r\nFast_Busy_L15: ; wait until transmit\r\n            ldrb Buffer, [STATW]\r\n            tst Buffer, #UCBUSY\r\n            bne Fast_Busy_L15\r\n\r\n        subs Count, Count, #1\r\n        bne Fast_L ; continue while fast data\r\n\r\nEnd:\r\n    pop {r4-r7}\r\n    bx lr\r\n    .endasmfunc\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Ok, here it is, the Fill function written in assembler. Due some caching of hardware register addresses in the Core registers, I was able to reduce the following code from 8+ steps to 4. UCB2TXBUF = data; while (UCB2STATW &#038; UCBUSY); The following assembler source is the first full standalone assembler code I wrote. Don&#8217;t [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21,64,13],"tags":[52,65,67,59,51],"class_list":["post-728","post","type-post","status-publish","format-standard","hentry","category-mikrocontroller","category-msp432","category-programming","tag-msp","tag-msp432","tag-msp432p401r","tag-spi","tag-ti"],"_links":{"self":[{"href":"https:\/\/www.livediesel.de\/index.php?rest_route=\/wp\/v2\/posts\/728","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.livediesel.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.livediesel.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.livediesel.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.livediesel.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=728"}],"version-history":[{"count":5,"href":"https:\/\/www.livediesel.de\/index.php?rest_route=\/wp\/v2\/posts\/728\/revisions"}],"predecessor-version":[{"id":733,"href":"https:\/\/www.livediesel.de\/index.php?rest_route=\/wp\/v2\/posts\/728\/revisions\/733"}],"wp:attachment":[{"href":"https:\/\/www.livediesel.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=728"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.livediesel.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=728"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.livediesel.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=728"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}